25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_wdc.c,v 1.33 2005/04/14 20:55:23 debug Exp $ |
* $Id: dev_wdc.c,v 1.37 2005/05/27 07:29:25 debug Exp $ |
29 |
* |
* |
30 |
* Standard IDE controller. |
* Standard IDE controller. |
31 |
*/ |
*/ |
52 |
/* INT_DELAY=2 to be safe, 1 is faster but maybe buggy. */ |
/* INT_DELAY=2 to be safe, 1 is faster but maybe buggy. */ |
53 |
#define INT_DELAY 1 |
#define INT_DELAY 1 |
54 |
|
|
55 |
|
extern int quiet_mode; |
56 |
|
|
57 |
/* #define debug fatal */ |
/* #define debug fatal */ |
58 |
/* #define DATA_DEBUG */ |
/* #define DATA_DEBUG */ |
59 |
|
|
114 |
|
|
115 |
d->inbuf_head = (d->inbuf_head + 1) % WDC_INBUF_SIZE; |
d->inbuf_head = (d->inbuf_head + 1) % WDC_INBUF_SIZE; |
116 |
if (d->inbuf_head == d->inbuf_tail) |
if (d->inbuf_head == d->inbuf_tail) |
117 |
fatal("WARNING! wdc inbuf overrun\n"); |
fatal("[ wdc_addtoinbuf(): WARNING! wdc inbuf overrun ]\n"); |
118 |
} |
} |
119 |
|
|
120 |
|
|
128 |
int c = d->inbuf[d->inbuf_tail]; |
int c = d->inbuf[d->inbuf_tail]; |
129 |
|
|
130 |
if (d->inbuf_head == d->inbuf_tail) { |
if (d->inbuf_head == d->inbuf_tail) { |
131 |
fatal("WARNING! someone is reading too much from the " |
fatal("[ wdc: WARNING! someone is reading too much from the " |
132 |
"wdc inbuf!\n"); |
"wdc inbuf! ]\n"); |
133 |
return -1; |
return -1; |
134 |
} |
} |
135 |
|
|
143 |
*/ |
*/ |
144 |
static void wdc_initialize_identify_struct(struct cpu *cpu, struct wdc_data *d) |
static void wdc_initialize_identify_struct(struct cpu *cpu, struct wdc_data *d) |
145 |
{ |
{ |
146 |
uint64_t total_size, cyls; |
uint64_t total_size; |
147 |
|
int cyls, heads, sectors_per_track; |
148 |
|
|
149 |
total_size = diskimage_getsize(cpu->machine, d->drive + d->base_drive); |
total_size = diskimage_getsize(cpu->machine, d->drive + d->base_drive, |
150 |
|
DISKIMAGE_IDE); |
151 |
|
|
152 |
memset(d->identify_struct, 0, sizeof(d->identify_struct)); |
diskimage_getchs(cpu->machine, d->drive + d->base_drive, |
153 |
|
DISKIMAGE_IDE, &cyls, &heads, §ors_per_track); |
154 |
|
|
155 |
cyls = total_size / (63 * 16 * 512); |
memset(d->identify_struct, 0, sizeof(d->identify_struct)); |
|
if (cyls * 63*16*512 < total_size) |
|
|
cyls ++; |
|
156 |
|
|
157 |
/* Offsets are in 16-bit WORDS! High byte, then low. */ |
/* Offsets are in 16-bit WORDS! High byte, then low. */ |
158 |
|
|
165 |
d->identify_struct[2 * 1 + 1] = cyls & 255; |
d->identify_struct[2 * 1 + 1] = cyls & 255; |
166 |
|
|
167 |
/* 3: nr of heads */ |
/* 3: nr of heads */ |
168 |
d->identify_struct[2 * 3 + 0] = 0; |
d->identify_struct[2 * 3 + 0] = heads >> 8; |
169 |
d->identify_struct[2 * 3 + 1] = 16; |
d->identify_struct[2 * 3 + 1] = heads; |
170 |
|
|
171 |
/* 6: sectors per track */ |
/* 6: sectors per track */ |
172 |
d->identify_struct[2 * 6 + 0] = 0; |
d->identify_struct[2 * 6 + 0] = sectors_per_track >> 8; |
173 |
d->identify_struct[2 * 6 + 1] = 63; |
d->identify_struct[2 * 6 + 1] = sectors_per_track; |
174 |
|
|
175 |
/* 10-19: Serial number */ |
/* 10-19: Serial number */ |
176 |
memcpy(&d->identify_struct[2 * 10], "S/N 1234-5678 ", 20); |
memcpy(&d->identify_struct[2 * 10], "S/N 1234-5678 ", 20); |
209 |
{ |
{ |
210 |
int odata = 0; |
int odata = 0; |
211 |
|
|
212 |
if (diskimage_exist(cpu->machine, |
if (diskimage_exist(cpu->machine, d->drive + d->base_drive, |
213 |
d->drive + d->base_drive)) |
DISKIMAGE_IDE)) |
214 |
odata |= WDCS_DRDY; |
odata |= WDCS_DRDY; |
215 |
if (d->inbuf_head != d->inbuf_tail) |
if (d->inbuf_head != d->inbuf_tail) |
216 |
odata |= WDCS_DRQ; |
odata |= WDCS_DRQ; |
225 |
* |
* |
226 |
* NetBSD/cobalt seems to want it, but Linux on MobilePro does not. |
* NetBSD/cobalt seems to want it, but Linux on MobilePro does not. |
227 |
*/ |
*/ |
228 |
if (!diskimage_exist(cpu->machine, |
if (!diskimage_exist(cpu->machine, d->drive + d->base_drive, |
229 |
d->drive + d->base_drive)) |
DISKIMAGE_IDE)) |
230 |
odata = 0xff; |
odata = 0xff; |
231 |
#endif |
#endif |
232 |
|
|
272 |
{ |
{ |
273 |
struct wdc_data *d = extra; |
struct wdc_data *d = extra; |
274 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
275 |
int i; |
int i, cyls, heads, sectors_per_track; |
276 |
|
|
277 |
idata = memory_readmax64(cpu, data, len); |
idata = memory_readmax64(cpu, data, len); |
278 |
|
|
344 |
buf[i] = wdc_get_inbuf(d); |
buf[i] = wdc_get_inbuf(d); |
345 |
|
|
346 |
diskimage_access(cpu->machine, |
diskimage_access(cpu->machine, |
347 |
d->drive + d->base_drive, 1, |
d->drive + d->base_drive, DISKIMAGE_IDE, 1, |
348 |
d->write_offset, buf, 512 * count); |
d->write_offset, buf, 512 * count); |
349 |
free(buf); |
free(buf); |
350 |
|
|
433 |
if (writeflag==MEM_READ) { |
if (writeflag==MEM_READ) { |
434 |
odata = status_byte(d, cpu); |
odata = status_byte(d, cpu); |
435 |
#if 1 |
#if 1 |
436 |
debug("[ wdc: read from STATUS: 0x%02x ]\n", odata); |
if (!quiet_mode) |
437 |
|
debug("[ wdc: read from STATUS: 0x%02x ]\n", |
438 |
|
odata); |
439 |
#endif |
#endif |
440 |
|
|
441 |
cpu_interrupt_ack(cpu, d->irq_nr); |
cpu_interrupt_ack(cpu, d->irq_nr); |
446 |
|
|
447 |
/* TODO: Is this correct behaviour? */ |
/* TODO: Is this correct behaviour? */ |
448 |
if (!diskimage_exist(cpu->machine, |
if (!diskimage_exist(cpu->machine, |
449 |
d->drive + d->base_drive)) { |
d->drive + d->base_drive, DISKIMAGE_IDE)) { |
450 |
d->error |= WDCE_ABRT; |
d->error |= WDCE_ABRT; |
451 |
d->delayed_interrupt = INT_DELAY; |
d->delayed_interrupt = INT_DELAY; |
452 |
break; |
break; |
461 |
d->sector, d->seccnt); |
d->sector, d->seccnt); |
462 |
/* TODO: HAHA! This should be removed |
/* TODO: HAHA! This should be removed |
463 |
quickly */ |
quickly */ |
464 |
|
diskimage_getchs(cpu->machine, d->drive + |
465 |
|
d->base_drive, DISKIMAGE_IDE, &cyls, |
466 |
|
&heads, §ors_per_track); |
467 |
|
|
468 |
{ |
{ |
469 |
unsigned char buf[512*256]; |
unsigned char buf[512*256]; |
470 |
int cyl = d->cyl_hi * 256+ d->cyl_lo; |
int cyl = d->cyl_hi * 256+ d->cyl_lo; |
471 |
int count = d->seccnt? d->seccnt : 256; |
int count = d->seccnt? d->seccnt : 256; |
472 |
uint64_t offset = 512 * (d->sector - 1 |
uint64_t offset = 512 * (d->sector - 1 |
473 |
+ d->head * 63 + 16*63*cyl); |
+ d->head * sectors_per_track + |
474 |
|
heads*sectors_per_track*cyl); |
475 |
|
|
476 |
#if 0 |
#if 0 |
477 |
/* LBA: */ |
/* LBA: */ |
480 |
printf("WDC read from offset %lli\n", (long long)offset); |
printf("WDC read from offset %lli\n", (long long)offset); |
481 |
#endif |
#endif |
482 |
diskimage_access(cpu->machine, |
diskimage_access(cpu->machine, |
483 |
d->drive + d->base_drive, 0, |
d->drive + d->base_drive, |
484 |
|
DISKIMAGE_IDE, 0, |
485 |
offset, buf, 512 * count); |
offset, buf, 512 * count); |
486 |
/* TODO: result code */ |
/* TODO: result code */ |
487 |
for (i=0; i<512 * count; i++) |
for (i=0; i<512 * count; i++) |
496 |
d->sector, d->seccnt); |
d->sector, d->seccnt); |
497 |
/* TODO: HAHA! This should be removed |
/* TODO: HAHA! This should be removed |
498 |
quickly */ |
quickly */ |
499 |
|
diskimage_getchs(cpu->machine, d->drive + |
500 |
|
d->base_drive, DISKIMAGE_IDE, &cyls, |
501 |
|
&heads, §ors_per_track); |
502 |
{ |
{ |
503 |
int cyl = d->cyl_hi * 256+ d->cyl_lo; |
int cyl = d->cyl_hi * 256+ d->cyl_lo; |
504 |
int count = d->seccnt? d->seccnt : 256; |
int count = d->seccnt? d->seccnt : 256; |
505 |
uint64_t offset = 512 * (d->sector - 1 |
uint64_t offset = 512 * (d->sector - 1 |
506 |
+ d->head * 63 + 16*63*cyl); |
+ d->head * sectors_per_track + |
507 |
|
heads*sectors_per_track*cyl); |
508 |
|
|
509 |
#if 0 |
#if 0 |
510 |
/* LBA: */ |
/* LBA: */ |