/[gxemul]/upstream/0.3.6.1/src/devices/dev_wdc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.6.1/src/devices/dev_wdc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (show annotations)
Mon Oct 8 16:19:05 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 17791 byte(s)
0.3.6.1
1 /*
2 * Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: dev_wdc.c,v 1.39 2005/09/27 23:55:44 debug Exp $
29 *
30 * Standard "wdc" IDE controller.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "console.h"
38 #include "cpu.h"
39 #include "device.h"
40 #include "diskimage.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44
45 #include "wdcreg.h"
46
47 #define DEV_WDC_LENGTH 8
48 #define WDC_TICK_SHIFT 14
49 #define WDC_INBUF_SIZE (512*257)
50
51 /*
52 * INT_DELAY=2 to be safe, 1 is faster but maybe buggy. 0 is fastest.
53 *
54 * The only reason for this delay to exist is because (some versions of)
55 * NetBSD for hpcmips have interrupt problems. These problems are not only
56 * triggered inside the emulator, but also on real hardware. Using the
57 * delay is an ugly (but working) work-around.
58 */
59 #define INT_DELAY 1
60
61 extern int quiet_mode;
62
63 /* #define debug fatal */
64
65 struct wdc_data {
66 int irq_nr;
67 int base_drive;
68 int data_debug;
69
70 /* Cached values: */
71 int cyls[2];
72 int heads[2];
73 int sectors_per_track[2];
74
75 unsigned char identify_struct[512];
76
77 unsigned char inbuf[WDC_INBUF_SIZE];
78 int inbuf_head;
79 int inbuf_tail;
80
81 int delayed_interrupt;
82 int write_in_progress;
83 int write_count;
84 int64_t write_offset;
85
86 int error;
87 int precomp;
88 int seccnt;
89 int sector;
90 int cyl_lo;
91 int cyl_hi;
92 int sectorsize;
93 int lba;
94 int drive;
95 int head;
96 int cur_command;
97 };
98
99
100 /*
101 * dev_wdc_tick():
102 */
103 void dev_wdc_tick(struct cpu *cpu, void *extra)
104 {
105 struct wdc_data *d = extra;
106
107 if (d->delayed_interrupt) {
108 d->delayed_interrupt --;
109
110 if (d->delayed_interrupt == 0)
111 cpu_interrupt(cpu, d->irq_nr);
112 }
113 }
114
115
116 /*
117 * wdc_addtoinbuf():
118 *
119 * Write to the inbuf at its head, read at its tail.
120 */
121 static void wdc_addtoinbuf(struct wdc_data *d, int c)
122 {
123 d->inbuf[d->inbuf_head] = c;
124
125 d->inbuf_head = (d->inbuf_head + 1) % WDC_INBUF_SIZE;
126 if (d->inbuf_head == d->inbuf_tail)
127 fatal("[ wdc_addtoinbuf(): WARNING! wdc inbuf overrun ]\n");
128 }
129
130
131 /*
132 * wdc_get_inbuf():
133 *
134 * Read from the tail of inbuf.
135 */
136 static uint64_t wdc_get_inbuf(struct wdc_data *d)
137 {
138 int c = d->inbuf[d->inbuf_tail];
139
140 if (d->inbuf_head == d->inbuf_tail) {
141 fatal("[ wdc: WARNING! someone is reading too much from the "
142 "wdc inbuf! ]\n");
143 return -1;
144 }
145
146 d->inbuf_tail = (d->inbuf_tail + 1) % WDC_INBUF_SIZE;
147 return c;
148 }
149
150
151 /*
152 * wdc_initialize_identify_struct(d):
153 */
154 static void wdc_initialize_identify_struct(struct cpu *cpu, struct wdc_data *d)
155 {
156 uint64_t total_size;
157 char namebuf[40];
158
159 total_size = diskimage_getsize(cpu->machine, d->drive + d->base_drive,
160 DISKIMAGE_IDE);
161
162 memset(d->identify_struct, 0, sizeof(d->identify_struct));
163
164 /* Offsets are in 16-bit WORDS! High byte, then low. */
165
166 /* 0: general flags */
167 d->identify_struct[2 * 0 + 0] = 0;
168 d->identify_struct[2 * 0 + 1] = 1 << 6;
169
170 /* 1: nr of cylinders */
171 d->identify_struct[2 * 1 + 0] = (d->cyls[d->drive] >> 8);
172 d->identify_struct[2 * 1 + 1] = d->cyls[d->drive] & 255;
173
174 /* 3: nr of heads */
175 d->identify_struct[2 * 3 + 0] = d->heads[d->drive] >> 8;
176 d->identify_struct[2 * 3 + 1] = d->heads[d->drive];
177
178 /* 6: sectors per track */
179 d->identify_struct[2 * 6 + 0] = d->sectors_per_track[d->drive] >> 8;
180 d->identify_struct[2 * 6 + 1] = d->sectors_per_track[d->drive];
181
182 /* 10-19: Serial number */
183 memcpy(&d->identify_struct[2 * 10], "S/N 1234-5678 ", 20);
184
185 /* 23-26: Firmware version */
186 memcpy(&d->identify_struct[2 * 23], "VER 1.0 ", 8);
187
188 /* 27-46: Model number */
189 if (diskimage_getname(cpu->machine, d->drive + d->base_drive,
190 DISKIMAGE_IDE, namebuf, sizeof(namebuf))) {
191 int i;
192 for (i=0; i<sizeof(namebuf); i++)
193 if (namebuf[i] == 0) {
194 for (; i<sizeof(namebuf); i++)
195 namebuf[i] = ' ';
196 break;
197 }
198 memcpy(&d->identify_struct[2 * 27], namebuf, 40);
199 } else
200 memcpy(&d->identify_struct[2 * 27],
201 "Fake GXemul IDE disk ", 40);
202
203 /* 47: max sectors per multitransfer */
204 d->identify_struct[2 * 47 + 0] = 0x80;
205 d->identify_struct[2 * 47 + 1] = 1; /* 1 or 16? */
206
207 /* 57-58: current capacity in sectors */
208 d->identify_struct[2 * 57 + 0] = ((total_size / 512) >> 24) % 255;
209 d->identify_struct[2 * 57 + 1] = ((total_size / 512) >> 16) % 255;
210 d->identify_struct[2 * 58 + 0] = ((total_size / 512) >> 8) % 255;
211 d->identify_struct[2 * 58 + 1] = (total_size / 512) & 255;
212
213 /* 60-61: total nr of addresable sectors */
214 d->identify_struct[2 * 60 + 0] = ((total_size / 512) >> 24) % 255;
215 d->identify_struct[2 * 60 + 1] = ((total_size / 512) >> 16) % 255;
216 d->identify_struct[2 * 61 + 0] = ((total_size / 512) >> 8) % 255;
217 d->identify_struct[2 * 61 + 1] = (total_size / 512) & 255;
218
219 }
220
221
222 /*
223 * wdc__read():
224 */
225 void wdc__read(struct cpu *cpu, struct wdc_data *d)
226 {
227 unsigned char buf[512];
228 int i, cyl = d->cyl_hi * 256+ d->cyl_lo;
229 int count = d->seccnt? d->seccnt : 256;
230 uint64_t offset = 512 * (d->sector - 1
231 + d->head * d->sectors_per_track[d->drive] +
232 d->heads[d->drive] * d->sectors_per_track[d->drive] * cyl);
233
234 #if 0
235 /* LBA: */
236 if (d->lba)
237 offset = 512 * (((d->head & 0xf) << 24) + (cyl << 8)
238 + d->sector);
239 printf("WDC read from offset %lli\n", (long long)offset);
240 #endif
241
242 while (count > 0) {
243 diskimage_access(cpu->machine, d->drive + d->base_drive,
244 DISKIMAGE_IDE, 0, offset, buf, 512);
245 /* TODO: result code */
246 for (i=0; i<512; i++)
247 wdc_addtoinbuf(d, buf[i]);
248 offset += 512;
249 count --;
250 }
251
252 d->delayed_interrupt = INT_DELAY;
253 }
254
255
256 /*
257 * wdc__write():
258 */
259 void wdc__write(struct cpu *cpu, struct wdc_data *d)
260 {
261 int cyl = d->cyl_hi * 256+ d->cyl_lo;
262 int count = d->seccnt? d->seccnt : 256;
263 uint64_t offset = 512 * (d->sector - 1
264 + d->head * d->sectors_per_track[d->drive] +
265 d->heads[d->drive] * d->sectors_per_track[d->drive] * cyl);
266 #if 0
267 /* LBA: */
268 if (d->lba)
269 offset = 512 * (((d->head & 0xf) << 24) +
270 (cyl << 8) + d->sector);
271 printf("WDC write to offset %lli\n", (long long)offset);
272 #endif
273
274 d->write_in_progress = 1;
275 d->write_count = count;
276 d->write_offset = offset;
277
278 /* TODO: result code? */
279 }
280
281
282 /*
283 * status_byte():
284 *
285 * Return a reasonable status byte corresponding to the controller's current
286 * state.
287 */
288 static int status_byte(struct wdc_data *d, struct cpu *cpu)
289 {
290 int odata = 0;
291
292 /*
293 * Modern versions of OpenBSD wants WDCS_DSC. (Thanks to Alexander
294 * Yurchenko for noticing this.)
295 */
296 if (diskimage_exist(cpu->machine, d->drive + d->base_drive,
297 DISKIMAGE_IDE))
298 odata |= WDCS_DRDY | WDCS_DSC;
299 if (d->inbuf_head != d->inbuf_tail)
300 odata |= WDCS_DRQ;
301 if (d->write_in_progress)
302 odata |= WDCS_DRQ;
303 if (d->error)
304 odata |= WDCS_ERR;
305
306 return odata;
307 }
308
309
310 /*
311 * dev_wdc_altstatus_access():
312 */
313 int dev_wdc_altstatus_access(struct cpu *cpu, struct memory *mem,
314 uint64_t relative_addr, unsigned char *data, size_t len,
315 int writeflag, void *extra)
316 {
317 struct wdc_data *d = extra;
318 uint64_t idata = 0, odata = 0;
319
320 idata = memory_readmax64(cpu, data, len);
321
322 /* Same as the normal status byte? */
323 odata = status_byte(d, cpu);
324
325 if (writeflag==MEM_READ)
326 debug("[ wdc: read from ALTSTATUS: 0x%02x ]\n",
327 (int)odata);
328 else
329 debug("[ wdc: write to ALT. CTRL: 0x%02x ]\n",
330 (int)idata);
331
332 if (writeflag == MEM_READ)
333 memory_writemax64(cpu, data, len, odata);
334
335 return 1;
336 }
337
338
339 /*
340 * dev_wdc_access():
341 */
342 int dev_wdc_access(struct cpu *cpu, struct memory *mem,
343 uint64_t relative_addr, unsigned char *data, size_t len,
344 int writeflag, void *extra)
345 {
346 struct wdc_data *d = extra;
347 uint64_t idata = 0, odata = 0;
348 int i;
349
350 idata = memory_readmax64(cpu, data, len);
351
352 switch (relative_addr) {
353
354 case wd_data: /* 0: data */
355 if (writeflag==MEM_READ) {
356 odata = 0;
357
358 /* TODO: This is hardcoded for little-endian? */
359
360 odata += wdc_get_inbuf(d);
361 if (len >= 2)
362 odata += (wdc_get_inbuf(d) << 8);
363 if (len == 4) {
364 odata += (wdc_get_inbuf(d) << 16);
365 odata += (wdc_get_inbuf(d) << 24);
366 }
367
368 if (d->data_debug)
369 debug("[ wdc: read from DATA: 0x%04x ]\n",
370 (int)odata);
371 if (d->inbuf_tail != d->inbuf_head)
372 d->delayed_interrupt = INT_DELAY;
373 } else {
374 int inbuf_len;
375 if (d->data_debug)
376 debug("[ wdc: write to DATA (len=%i): "
377 "0x%08lx ]\n", (int)len, (long)idata);
378 if (!d->write_in_progress) {
379 fatal("[ wdc: write to DATA, but not "
380 "expecting any? (len=%i): 0x%08lx ]\n",
381 (int)len, (long)idata);
382 }
383
384 switch (len) {
385 case 4: wdc_addtoinbuf(d, idata & 0xff);
386 wdc_addtoinbuf(d, (idata >> 8) & 0xff);
387 wdc_addtoinbuf(d, (idata >> 16) & 0xff);
388 wdc_addtoinbuf(d, (idata >> 24) & 0xff);
389 break;
390 case 2: wdc_addtoinbuf(d, idata & 0xff);
391 wdc_addtoinbuf(d, (idata >> 8) & 0xff);
392 break;
393 case 1: wdc_addtoinbuf(d, idata); break;
394 default:fatal("wdc: unimplemented write len %i\n", len);
395 exit(1);
396 }
397
398 inbuf_len = d->inbuf_head - d->inbuf_tail;
399 while (inbuf_len < 0)
400 inbuf_len += WDC_INBUF_SIZE;
401
402 #if 0
403 if ((inbuf_len % (512 * d->write_count)) == 0) {
404 #else
405 if ((inbuf_len % 512) == 0) {
406 #endif
407 int count = 1; /* d->write_count; */
408 unsigned char *buf = malloc(count * 512);
409 if (buf == NULL) {
410 fprintf(stderr, "out of memory\n");
411 exit(1);
412 }
413
414 for (i=0; i<512 * count; i++)
415 buf[i] = wdc_get_inbuf(d);
416
417 diskimage_access(cpu->machine,
418 d->drive + d->base_drive, DISKIMAGE_IDE, 1,
419 d->write_offset, buf, 512 * count);
420 free(buf);
421
422 d->write_count --;
423 d->write_offset += 512;
424
425 d->delayed_interrupt = INT_DELAY;
426
427 if (d->write_count == 0)
428 d->write_in_progress = 0;
429 }
430 }
431 break;
432
433 case wd_error: /* 1: error (r), precomp (w) */
434 if (writeflag==MEM_READ) {
435 odata = d->error;
436 debug("[ wdc: read from ERROR: 0x%02x ]\n",
437 (int)odata);
438 /* TODO: is the error value cleared on read? */
439 d->error = 0;
440 } else {
441 d->precomp = idata;
442 debug("[ wdc: write to PRECOMP: 0x%02x ]\n",(int)idata);
443 }
444 break;
445
446 case wd_seccnt: /* 2: sector count */
447 if (writeflag==MEM_READ) {
448 odata = d->seccnt;
449 debug("[ wdc: read from SECCNT: 0x%02x ]\n",(int)odata);
450 } else {
451 d->seccnt = idata;
452 debug("[ wdc: write to SECCNT: 0x%02x ]\n", (int)idata);
453 }
454 break;
455
456 case wd_sector: /* 3: first sector */
457 if (writeflag==MEM_READ) {
458 odata = d->sector;
459 debug("[ wdc: read from SECTOR: 0x%02x ]\n",(int)odata);
460 } else {
461 d->sector = idata;
462 debug("[ wdc: write to SECTOR: 0x%02x ]\n", (int)idata);
463 }
464 break;
465
466 case wd_cyl_lo: /* 4: cylinder low */
467 if (writeflag==MEM_READ) {
468 odata = d->cyl_lo;
469 debug("[ wdc: read from CYL_LO: 0x%02x ]\n",(int)odata);
470 } else {
471 d->cyl_lo = idata;
472 debug("[ wdc: write to CYL_LO: 0x%02x ]\n", (int)idata);
473 }
474 break;
475
476 case wd_cyl_hi: /* 5: cylinder low */
477 if (writeflag==MEM_READ) {
478 odata = d->cyl_hi;
479 debug("[ wdc: read from CYL_HI: 0x%02x ]\n",(int)odata);
480 } else {
481 d->cyl_hi = idata;
482 debug("[ wdc: write to CYL_HI: 0x%02x ]\n", (int)idata);
483 }
484 break;
485
486 case wd_sdh: /* 6: sectorsize/drive/head */
487 if (writeflag==MEM_READ) {
488 odata = (d->sectorsize << 6) + (d->lba << 5) +
489 (d->drive << 4) + (d->head);
490 debug("[ wdc: read from SDH: 0x%02x (sectorsize %i,"
491 " lba=%i, drive %i, head %i) ]\n", (int)odata,
492 d->sectorsize, d->lba, d->drive, d->head);
493 } else {
494 d->sectorsize = (idata >> 6) & 3;
495 d->lba = (idata >> 5) & 1;
496 d->drive = (idata >> 4) & 1;
497 d->head = idata & 0xf;
498 debug("[ wdc: write to SDH: 0x%02x (sectorsize %i,"
499 " lba=%i, drive %i, head %i) ]\n", (int)idata,
500 d->sectorsize, d->lba, d->drive, d->head);
501 }
502 break;
503
504 case wd_command: /* 7: command or status */
505 if (writeflag==MEM_READ) {
506 odata = status_byte(d, cpu);
507 if (!quiet_mode)
508 debug("[ wdc: read from STATUS: 0x%02x ]\n",
509 (int)odata);
510 cpu_interrupt_ack(cpu, d->irq_nr);
511 d->delayed_interrupt = 0;
512 } else {
513 debug("[ wdc: write to COMMAND: 0x%02x ]\n",(int)idata);
514 d->cur_command = idata;
515
516 /* TODO: Is this correct behaviour? */
517 if (!diskimage_exist(cpu->machine,
518 d->drive + d->base_drive, DISKIMAGE_IDE)) {
519 d->error |= WDCE_ABRT;
520 d->delayed_interrupt = INT_DELAY;
521 break;
522 }
523
524 /* Handle the command: */
525 switch (d->cur_command) {
526
527 case WDCC_READ:
528 if (!quiet_mode)
529 debug("[ wdc: READ from drive %i, head"
530 " %i, cyl %i, sector %i, nsecs %i "
531 "]\n", d->drive, d->head,
532 d->cyl_hi*256+d->cyl_lo, d->sector,
533 d->seccnt);
534 wdc__read(cpu, d);
535 break;
536
537 case WDCC_WRITE:
538 if (!quiet_mode)
539 debug("[ wdc: WRITE to drive %i, head"
540 " %i, cyl %i, sector %i, nsecs %i"
541 " ]\n", d->drive, d->head,
542 d->cyl_hi*256+d->cyl_lo, d->sector,
543 d->seccnt);
544 wdc__write(cpu, d);
545 break;
546
547 case WDCC_IDP: /* Initialize drive parameters */
548 debug("[ wdc: IDP drive %i (TODO) ]\n",
549 d->drive);
550 /* TODO */
551 d->delayed_interrupt = INT_DELAY;
552 break;
553
554 case SET_FEATURES:
555 fatal("[ wdc: SET_FEATURES drive %i (TODO), "
556 "feature 0x%02x ]\n", d->drive, d->precomp);
557 /* TODO */
558 switch (d->precomp) {
559 case WDSF_SET_MODE:
560 fatal("[ wdc: WDSF_SET_MODE drive %i, "
561 "pio/dma flags 0x%02x ]\n",
562 d->drive, d->seccnt);
563 break;
564 default:
565 d->error |= WDCE_ABRT;
566 }
567 /* TODO: always interrupt? */
568 d->delayed_interrupt = INT_DELAY;
569 break;
570
571 case WDCC_RECAL:
572 debug("[ wdc: RECAL drive %i ]\n", d->drive);
573 d->delayed_interrupt = INT_DELAY;
574 break;
575
576 case WDCC_IDENTIFY:
577 debug("[ wdc: IDENTIFY drive %i ]\n", d->drive);
578 wdc_initialize_identify_struct(cpu, d);
579 /* The IDENTIFY data block is sent out
580 in low/high byte order: */
581 for (i=0; i<sizeof(d->identify_struct); i+=2) {
582 wdc_addtoinbuf(d, d->identify_struct
583 [i+1]);
584 wdc_addtoinbuf(d, d->identify_struct
585 [i+0]);
586 }
587 d->delayed_interrupt = INT_DELAY;
588 break;
589
590 case WDCC_IDLE_IMMED:
591 debug("[ wdc: IDLE_IMMED drive %i ]\n",
592 d->drive);
593 /* TODO: interrupt here? */
594 d->delayed_interrupt = INT_DELAY;
595 break;
596
597 /* Unsupported commands, without warning: */
598 case ATAPI_IDENTIFY_DEVICE:
599 case WDCC_SEC_SET_PASSWORD:
600 case WDCC_SEC_UNLOCK:
601 case WDCC_SEC_ERASE_PREPARE:
602 case WDCC_SEC_ERASE_UNIT:
603 case WDCC_SEC_FREEZE_LOCK:
604 case WDCC_SEC_DISABLE_PASSWORD:
605 d->error |= WDCE_ABRT;
606 break;
607
608 default:
609 /* TODO */
610 d->error |= WDCE_ABRT;
611
612 fatal("[ wdc: WARNING! Unimplemented command "
613 "0x%02x (drive %i, head %i, cyl %i, sector"
614 " %i, nsecs %i) ]\n", d->cur_command,
615 d->drive, d->head, d->cyl_hi*256+d->cyl_lo,
616 d->sector, d->seccnt);
617 }
618 }
619 break;
620
621 default:
622 if (writeflag==MEM_READ)
623 debug("[ wdc: read from 0x%02x ]\n",
624 (int)relative_addr);
625 else
626 debug("[ wdc: write to 0x%02x: 0x%02x ]\n",
627 (int)relative_addr, (int)idata);
628 }
629
630 if (writeflag == MEM_READ)
631 memory_writemax64(cpu, data, len, odata);
632
633 return 1;
634 }
635
636
637 /*
638 * devinit_wdc():
639 */
640 int devinit_wdc(struct devinit *devinit)
641 {
642 struct wdc_data *d;
643 uint64_t alt_status_addr;
644 int i;
645
646 d = malloc(sizeof(struct wdc_data));
647 if (d == NULL) {
648 fprintf(stderr, "out of memory\n");
649 exit(1);
650 }
651 memset(d, 0, sizeof(struct wdc_data));
652 d->irq_nr = devinit->irq_nr;
653
654 /* base_drive = 0 for the primary controller, 2 for the secondary. */
655 d->base_drive = 0;
656 if ((devinit->addr & 0xfff) == 0x170)
657 d->base_drive = 2;
658
659 alt_status_addr = devinit->addr + 0x206;
660
661 /* Special hack for pcic/hpcmips: TODO: Fix */
662 if (devinit->addr == 0x14000180)
663 alt_status_addr = 0x14000386;
664
665 /* Get disk geometries: */
666 for (i=0; i<2; i++)
667 if (diskimage_exist(devinit->machine, d->base_drive +i,
668 DISKIMAGE_IDE))
669 diskimage_getchs(devinit->machine, d->base_drive + i,
670 DISKIMAGE_IDE, &d->cyls[i], &d->heads[i],
671 &d->sectors_per_track[i]);
672
673 memory_device_register(devinit->machine->memory, "wdc_altstatus",
674 alt_status_addr, 2, dev_wdc_altstatus_access, d, MEM_DEFAULT, NULL);
675 memory_device_register(devinit->machine->memory, devinit->name,
676 devinit->addr, DEV_WDC_LENGTH, dev_wdc_access, d, MEM_DEFAULT,
677 NULL);
678
679 machine_add_tickfunction(devinit->machine, dev_wdc_tick,
680 d, WDC_TICK_SHIFT);
681
682 return 1;
683 }
684

  ViewVC Help
Powered by ViewVC 1.1.26