/[gxemul]/trunk/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

Diff of /trunk/src/devices/dev_wdc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2004-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2004-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: dev_wdc.c,v 1.44 2005/10/26 14:37:05 debug Exp $   *  $Id: dev_wdc.c,v 1.68 2006/08/14 17:45:47 debug Exp $
29   *   *
30   *  Standard "wdc" IDE controller.   *  Standard "wdc" IDE controller.
31   */   */
# Line 55  Line 55 
55   *   *
56   *  See the following URL for more info:   *  See the following URL for more info:
57   *  http://mail-index.netbsd.org/port-hpcmips/2004/12/30/0003.html   *  http://mail-index.netbsd.org/port-hpcmips/2004/12/30/0003.html
58     *
59     *  NetBSD/malta also bugs out if wdc interrupts come too quickly. Hm.
60   */   */
61  #define INT_DELAY               1  #define INT_DELAY               1
62    
# Line 64  extern int quiet_mode; Line 66  extern int quiet_mode;
66    
67  struct wdc_data {  struct wdc_data {
68          int             irq_nr;          int             irq_nr;
69            int             addr_mult;
70          int             base_drive;          int             base_drive;
71          int             data_debug;          int             data_debug;
72            int             io_enabled;
73    
74          /*  Cached values:  */          /*  Cached values:  */
75          int             cyls[2];          int             cyls[2];
76          int             heads[2];          int             heads[2];
77          int             sectors_per_track[2];          int             sectors_per_track[2];
78    
79          unsigned char   identify_struct[512];          unsigned char   *inbuf;
   
         unsigned char   inbuf[WDC_INBUF_SIZE];  
80          int             inbuf_head;          int             inbuf_head;
81          int             inbuf_tail;          int             inbuf_tail;
82    
83          int             delayed_interrupt;          int             delayed_interrupt;
84            int             int_asserted;
85    
86          int             write_in_progress;          int             write_in_progress;
87          int             write_count;          int             write_count;
88          int64_t         write_offset;          int64_t         write_offset;
# Line 94  struct wdc_data { Line 98  struct wdc_data {
98          int             drive;          int             drive;
99          int             head;          int             head;
100          int             cur_command;          int             cur_command;
101    
102            int             atapi_cmd_in_progress;
103            int             atapi_phase;
104            struct scsi_transfer *atapi_st;
105            int             atapi_len;
106            size_t          atapi_received;
107    
108            unsigned char   identify_struct[512];
109  };  };
110    
111    
112    #define COMMAND_RESET   0x100
113    
114    
115  /*  /*
116   *  dev_wdc_tick():   *  dev_wdc_tick():
117   */   */
118  void dev_wdc_tick(struct cpu *cpu, void *extra)  void dev_wdc_tick(struct cpu *cpu, void *extra)
119  {  {
120          struct wdc_data *d = extra;          struct wdc_data *d = extra;
121            int old_di = d->delayed_interrupt;
122    
123          if (d->delayed_interrupt) {          if (d->delayed_interrupt)
124                  d->delayed_interrupt --;                  d->delayed_interrupt --;
125    
126                  if (d->delayed_interrupt == 0)          if (old_di == 1 || d->int_asserted) {
127                          cpu_interrupt(cpu, d->irq_nr);                  cpu_interrupt(cpu, d->irq_nr);
128                    d->int_asserted = 1;
129          }          }
130  }  }
131    
132    
133  /*  /*
134     *  wdc_set_io_enabled():
135     *
136     *  Set io_enabled to zero to disable the I/O registers temporarily (e.g.
137     *  used by PCI code in NetBSD to detect whether multiple controllers collide
138     *  in I/O space).
139     *
140     *  Return value is old contents of the io_enabled variable.
141     */
142    int wdc_set_io_enabled(struct wdc_data *d, int io_enabled)
143    {
144            int old = d->io_enabled;
145            d->io_enabled = io_enabled;
146            return old;
147    }
148    
149    
150    /*
151   *  wdc_addtoinbuf():   *  wdc_addtoinbuf():
152   *   *
153   *  Write to the inbuf at its head, read at its tail.   *  Write to the inbuf at its head, read at its tail.
# Line 150  static uint64_t wdc_get_inbuf(struct wdc Line 184  static uint64_t wdc_get_inbuf(struct wdc
184    
185    
186  /*  /*
187   *  wdc_initialize_identify_struct(d):   *  wdc_initialize_identify_struct():
188   */   */
189  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)
190  {  {
191          uint64_t total_size;          uint64_t total_size;
192            int flags, cdrom = 0;
193          char namebuf[40];          char namebuf[40];
194    
195          total_size = diskimage_getsize(cpu->machine, d->drive + d->base_drive,          total_size = diskimage_getsize(cpu->machine, d->drive + d->base_drive,
196              DISKIMAGE_IDE);              DISKIMAGE_IDE);
197            if (diskimage_is_a_cdrom(cpu->machine, d->drive + d->base_drive,
198                DISKIMAGE_IDE))
199                    cdrom = 1;
200    
201          memset(d->identify_struct, 0, sizeof(d->identify_struct));          memset(d->identify_struct, 0, sizeof(d->identify_struct));
202    
203          /*  Offsets are in 16-bit WORDS!  High byte, then low.  */          /*  Offsets are in 16-bit WORDS!  High byte, then low.  */
204    
205          /*  0: general flags  */          /*  0: general flags  */
206          d->identify_struct[2 * 0 + 0] = 0;          flags = 1 << 6; /*  Fixed  */
207          d->identify_struct[2 * 0 + 1] = 1 << 6;          if (cdrom)
208                    flags = 0x8580;         /*  ATAPI, CDROM, removable  */
209            d->identify_struct[2 * 0 + 0] = flags >> 8;
210            d->identify_struct[2 * 0 + 1] = flags;
211    
212          /*  1: nr of cylinders  */          /*  1: nr of cylinders  */
213          d->identify_struct[2 * 1 + 0] = (d->cyls[d->drive] >> 8);          d->identify_struct[2 * 1 + 0] = d->cyls[d->drive] >> 8;
214          d->identify_struct[2 * 1 + 1] = d->cyls[d->drive] & 255;          d->identify_struct[2 * 1 + 1] = d->cyls[d->drive];
215    
216          /*  3: nr of heads  */          /*  3: nr of heads  */
217          d->identify_struct[2 * 3 + 0] = d->heads[d->drive] >> 8;          d->identify_struct[2 * 3 + 0] = d->heads[d->drive] >> 8;
# Line 181  static void wdc_initialize_identify_stru Line 222  static void wdc_initialize_identify_stru
222          d->identify_struct[2 * 6 + 1] = d->sectors_per_track[d->drive];          d->identify_struct[2 * 6 + 1] = d->sectors_per_track[d->drive];
223    
224          /*  10-19: Serial number  */          /*  10-19: Serial number  */
225          memcpy(&d->identify_struct[2 * 10], "S/N 1234-5678       ", 20);          memcpy(&d->identify_struct[2 * 10], "#0                  ", 20);
226    
227          /*  23-26: Firmware version  */          /*  23-26: Firmware version  */
228          memcpy(&d->identify_struct[2 * 23], "VER 1.0 ", 8);          memcpy(&d->identify_struct[2 * 23], "1.0     ", 8);
229    
230          /*  27-46: Model number  */          /*  27-46: Model number  */
231          if (diskimage_getname(cpu->machine, d->drive + d->base_drive,          if (diskimage_getname(cpu->machine, d->drive + d->base_drive,
232              DISKIMAGE_IDE, namebuf, sizeof(namebuf))) {              DISKIMAGE_IDE, namebuf, sizeof(namebuf))) {
233                  int i;                  size_t i;
234                  for (i=0; i<sizeof(namebuf); i++)                  for (i=0; i<sizeof(namebuf); i++)
235                          if (namebuf[i] == 0) {                          if (namebuf[i] == 0) {
236                                  for (; i<sizeof(namebuf); i++)                                  for (; i<sizeof(namebuf); i++)
# Line 203  static void wdc_initialize_identify_stru Line 244  static void wdc_initialize_identify_stru
244    
245          /*  47: max sectors per multitransfer  */          /*  47: max sectors per multitransfer  */
246          d->identify_struct[2 * 47 + 0] = 0x80;          d->identify_struct[2 * 47 + 0] = 0x80;
247          d->identify_struct[2 * 47 + 1] = 1;     /*  1 or 16?  */          d->identify_struct[2 * 47 + 1] = 128;
248    
249            /*  49: capabilities:  */
250            /*  (0x200 = LBA, 0x100 = DMA support.)  */
251            d->identify_struct[2 * 49 + 0] = 0;
252            d->identify_struct[2 * 49 + 1] = 0;
253    
254            /*  51: PIO timing mode.  */
255            d->identify_struct[2 * 51 + 0] = 0x00;  /*  ?  */
256            d->identify_struct[2 * 51 + 1] = 0x00;
257    
258            /*  53: 0x02 = fields 64-70 valid, 0x01 = fields 54-58 valid  */
259            d->identify_struct[2 * 53 + 0] = 0x00;
260            d->identify_struct[2 * 53 + 1] = 0x02;
261    
262          /*  57-58: current capacity in sectors  */          /*  57-58: current capacity in sectors  */
263          d->identify_struct[2 * 57 + 0] = ((total_size / 512) >> 24) % 255;          d->identify_struct[2 * 57 + 0] = ((total_size / 512) >> 24) % 255;
# Line 211  static void wdc_initialize_identify_stru Line 265  static void wdc_initialize_identify_stru
265          d->identify_struct[2 * 58 + 0] = ((total_size / 512) >> 8) % 255;          d->identify_struct[2 * 58 + 0] = ((total_size / 512) >> 8) % 255;
266          d->identify_struct[2 * 58 + 1] = (total_size / 512) & 255;          d->identify_struct[2 * 58 + 1] = (total_size / 512) & 255;
267    
268          /*  60-61: total nr of addresable sectors  */          /*  60-61: total nr of addressable sectors  */
269          d->identify_struct[2 * 60 + 0] = ((total_size / 512) >> 24) % 255;          d->identify_struct[2 * 60 + 0] = ((total_size / 512) >> 24) % 255;
270          d->identify_struct[2 * 60 + 1] = ((total_size / 512) >> 16) % 255;          d->identify_struct[2 * 60 + 1] = ((total_size / 512) >> 16) % 255;
271          d->identify_struct[2 * 61 + 0] = ((total_size / 512) >> 8) % 255;          d->identify_struct[2 * 61 + 0] = ((total_size / 512) >> 8) % 255;
272          d->identify_struct[2 * 61 + 1] = (total_size / 512) & 255;          d->identify_struct[2 * 61 + 1] = (total_size / 512) & 255;
273    
274            /*  64: Advanced PIO mode support. 0x02 = mode4, 0x01 = mode3  */
275            d->identify_struct[2 * 64 + 0] = 0x00;
276            d->identify_struct[2 * 64 + 1] = 0x03;
277    
278            /*  67, 68: PIO timing  */
279            d->identify_struct[2 * 67 + 0] = 0;
280            d->identify_struct[2 * 67 + 1] = 120;
281            d->identify_struct[2 * 68 + 0] = 0;
282            d->identify_struct[2 * 68 + 1] = 120;
283  }  }
284    
285    
# Line 225  static void wdc_initialize_identify_stru Line 288  static void wdc_initialize_identify_stru
288   */   */
289  void wdc__read(struct cpu *cpu, struct wdc_data *d)  void wdc__read(struct cpu *cpu, struct wdc_data *d)
290  {  {
291          const int max_sectors_per_chunk = 64;  #define MAX_SECTORS_PER_CHUNK   64
292          unsigned char buf[512 * max_sectors_per_chunk];          const int max_sectors_per_chunk = MAX_SECTORS_PER_CHUNK;
293            unsigned char buf[512 * MAX_SECTORS_PER_CHUNK];
294          int i, cyl = d->cyl_hi * 256+ d->cyl_lo;          int i, cyl = d->cyl_hi * 256+ d->cyl_lo;
295          int count = d->seccnt? d->seccnt : 256;          int count = d->seccnt? d->seccnt : 256;
296          uint64_t offset = 512 * (d->sector - 1          uint64_t offset = 512 * (d->sector - 1
# Line 287  void wdc__write(struct cpu *cpu, struct Line 351  void wdc__write(struct cpu *cpu, struct
351          printf("WDC write to offset %lli\n", (long long)offset);          printf("WDC write to offset %lli\n", (long long)offset);
352  #endif  #endif
353    
354          d->write_in_progress = 1;          d->write_in_progress = d->cur_command;
355          d->write_count = count;          d->write_count = count;
356          d->write_offset = offset;          d->write_offset = offset;
357    
# Line 304  void wdc__write(struct cpu *cpu, struct Line 368  void wdc__write(struct cpu *cpu, struct
368  static int status_byte(struct wdc_data *d, struct cpu *cpu)  static int status_byte(struct wdc_data *d, struct cpu *cpu)
369  {  {
370          int odata = 0;          int odata = 0;
   
         /*  
          *  Modern versions of OpenBSD wants WDCS_DSC. (Thanks to Alexander  
          *  Yurchenko for noticing this.)  
          */  
371          if (diskimage_exist(cpu->machine, d->drive + d->base_drive,          if (diskimage_exist(cpu->machine, d->drive + d->base_drive,
372              DISKIMAGE_IDE))              DISKIMAGE_IDE))
373                  odata |= WDCS_DRDY | WDCS_DSC;                  odata |= WDCS_DRDY | WDCS_DSC;
# Line 318  static int status_byte(struct wdc_data * Line 377  static int status_byte(struct wdc_data *
377                  odata |= WDCS_DRQ;                  odata |= WDCS_DRQ;
378          if (d->error)          if (d->error)
379                  odata |= WDCS_ERR;                  odata |= WDCS_ERR;
380            if (d->atapi_cmd_in_progress && (d->atapi_phase & WDCS_DRQ)) {
381                    odata |= WDCS_DRQ;
382            }
383          return odata;          return odata;
384  }  }
385    
# Line 326  static int status_byte(struct wdc_data * Line 387  static int status_byte(struct wdc_data *
387  /*  /*
388   *  dev_wdc_altstatus_access():   *  dev_wdc_altstatus_access():
389   */   */
390  int dev_wdc_altstatus_access(struct cpu *cpu, struct memory *mem,  DEVICE_ACCESS(wdc_altstatus)
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
391  {  {
392          struct wdc_data *d = extra;          struct wdc_data *d = extra;
393          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
394    
395          idata = data[0];          idata = data[0];
396    
397          /*  Same as the normal status byte?  */          /*  Same as the normal status byte:  */
398          odata = status_byte(d, cpu);          odata = status_byte(d, cpu);
399    
400          if (writeflag==MEM_READ)          if (writeflag==MEM_READ)
401                  debug("[ wdc: read from ALTSTATUS: 0x%02x ]\n",                  debug("[ wdc: read from ALTSTATUS: 0x%02x ]\n",
402                      (int)odata);                      (int)odata);
403          else          else {
404                  debug("[ wdc: write to ALT. CTRL: 0x%02x ]\n",                  debug("[ wdc: write to ALT. CTRL: 0x%02x ]\n",
405                      (int)idata);                      (int)idata);
406                    if (idata & WDCTL_4BIT)
407                            d->cur_command = COMMAND_RESET;
408            }
409    
410          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
411                  data[0] = odata;                  data[0] = odata;
# Line 353  int dev_wdc_altstatus_access(struct cpu Line 415  int dev_wdc_altstatus_access(struct cpu
415    
416    
417  /*  /*
418     *  wdc_command():
419     */
420    void wdc_command(struct cpu *cpu, struct wdc_data *d, int idata)
421    {
422            size_t i;
423    
424            d->cur_command = idata;
425            d->atapi_cmd_in_progress = 0;
426            d->error = 0;
427    
428            /*
429             *  Disk images that do not exist return an ABORT error.  This also
430             *  happens with CDROM images with the WDCC_IDENTIFY command; CDROM
431             *  images must be detected with ATAPI_IDENTIFY_DEVICE instead.
432             *
433             *  TODO:  Is this correct/good behaviour?
434             */
435            if (!diskimage_exist(cpu->machine, d->drive + d->base_drive,
436                DISKIMAGE_IDE)) {
437                    debug("[ wdc: command 0x%02x drive %i, but no disk image ]\n",
438                        d->cur_command, d->drive + d->base_drive);
439                    d->error |= WDCE_ABRT;
440                    d->delayed_interrupt = INT_DELAY;
441                    return;
442            }
443            if (diskimage_is_a_cdrom(cpu->machine, d->drive + d->base_drive,
444                DISKIMAGE_IDE) && d->cur_command == WDCC_IDENTIFY) {
445                    debug("[ wdc: IDENTIFY drive %i, but it is an ATAPI "
446                        "drive ]\n", d->drive + d->base_drive);
447                    d->error |= WDCE_ABRT;
448                    d->delayed_interrupt = INT_DELAY;
449                    return;
450            }
451    
452            /*  Handle the command:  */
453            switch (d->cur_command) {
454    
455            case WDCC_READ:
456            case WDCC_READMULTI:
457                    if (!quiet_mode)
458                            debug("[ wdc: READ from drive %i, head %i, cyl %i, "
459                                "sector %i, nsecs %i ]\n", d->drive, d->head,
460                                d->cyl_hi*256+d->cyl_lo, d->sector, d->seccnt);
461                    wdc__read(cpu, d);
462                    break;
463    
464            case WDCC_WRITE:
465            case WDCC_WRITEMULTI:
466                    if (!quiet_mode)
467                            debug("[ wdc: WRITE to drive %i, head %i, cyl %i, "
468                                "sector %i, nsecs %i ]\n", d->drive, d->head,
469                                d->cyl_hi*256+d->cyl_lo, d->sector, d->seccnt);
470                    wdc__write(cpu, d);
471                    break;
472    
473            case WDCC_IDP:  /*  Initialize drive parameters  */
474                    debug("[ wdc: IDP drive %i (TODO) ]\n", d->drive);
475                    /*  TODO  */
476                    d->delayed_interrupt = INT_DELAY;
477                    break;
478    
479            case SET_FEATURES:
480                    debug("[ wdc: SET_FEATURES drive %i (TODO), feature 0x%02x ]\n",
481                        d->drive, d->precomp);
482                    /*  TODO  */
483                    switch (d->precomp) {
484                    case WDSF_SET_MODE:
485                            debug("[ wdc: WDSF_SET_MODE drive %i, pio/dma flags "
486                                "0x%02x ]\n", d->drive, d->seccnt);
487                            break;
488                    default:d->error |= WDCE_ABRT;
489                    }
490                    /*  TODO: always interrupt?  */
491                    d->delayed_interrupt = INT_DELAY;
492                    break;
493    
494            case WDCC_RECAL:
495                    debug("[ wdc: RECAL drive %i ]\n", d->drive);
496                    d->delayed_interrupt = INT_DELAY;
497                    break;
498    
499            case WDCC_IDENTIFY:
500            case ATAPI_IDENTIFY_DEVICE:
501                    debug("[ wdc: %sIDENTIFY drive %i ]\n", d->cur_command ==
502                        ATAPI_IDENTIFY_DEVICE? "ATAPI " : "", d->drive);
503                    wdc_initialize_identify_struct(cpu, d);
504                    /*  The IDENTIFY data is sent out in low/high byte order:  */
505                    for (i=0; i<sizeof(d->identify_struct); i+=2) {
506                            wdc_addtoinbuf(d, d->identify_struct[i+1]);
507                            wdc_addtoinbuf(d, d->identify_struct[i+0]);
508                    }
509                    d->delayed_interrupt = INT_DELAY;
510                    break;
511    
512            case WDCC_IDLE_IMMED:
513                    debug("[ wdc: IDLE_IMMED drive %i ]\n", d->drive);
514                    /*  TODO: interrupt here?  */
515                    d->delayed_interrupt = INT_DELAY;
516                    break;
517    
518            case WDCC_SETMULTI:
519                    debug("[ wdc: SETMULTI drive %i ]\n", d->drive);
520                    /*  TODO: interrupt here?  */
521                    d->delayed_interrupt = INT_DELAY;
522                    break;
523    
524            case ATAPI_SOFT_RESET:
525                    debug("[ wdc: ATAPI_SOFT_RESET drive %i ]\n", d->drive);
526                    /*  TODO: interrupt here?  */
527                    d->delayed_interrupt = INT_DELAY;
528                    break;
529    
530            case ATAPI_PKT_CMD:
531                    debug("[ wdc: ATAPI_PKT_CMD drive %i ]\n", d->drive);
532                    /*  TODO: interrupt here?  */
533                    /*  d->delayed_interrupt = INT_DELAY;  */
534                    d->atapi_cmd_in_progress = 1;
535                    d->atapi_phase = PHASE_CMDOUT;
536                    break;
537    
538            case WDCC_DIAGNOSE:
539                    debug("[ wdc: WDCC_DIAGNOSE drive %i: TODO ]\n", d->drive);
540                    /*  TODO: interrupt here?  */
541                    d->delayed_interrupt = INT_DELAY;
542                    d->error = 1;           /*  No error?  */
543                    break;
544    
545            /*  Unsupported commands, without warning:  */
546            case WDCC_SEC_SET_PASSWORD:
547            case WDCC_SEC_UNLOCK:
548            case WDCC_SEC_ERASE_PREPARE:
549            case WDCC_SEC_ERASE_UNIT:
550            case WDCC_SEC_FREEZE_LOCK:
551            case WDCC_SEC_DISABLE_PASSWORD:
552                    d->error |= WDCE_ABRT;
553                    break;
554    
555            default:/*  TODO  */
556                    d->error |= WDCE_ABRT;
557                    fatal("[ wdc: WARNING! Unimplemented command 0x%02x (drive %i,"
558                        " head %i, cyl %i, sector %i, nsecs %i) ]\n",
559                        d->cur_command, d->drive, d->head, d->cyl_hi*256+d->cyl_lo,
560                        d->sector, d->seccnt);
561            }
562    }
563    
564    
565    /*
566   *  dev_wdc_access():   *  dev_wdc_access():
567   */   */
568  int dev_wdc_access(struct cpu *cpu, struct memory *mem,  DEVICE_ACCESS(wdc)
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
569  {  {
570          struct wdc_data *d = extra;          struct wdc_data *d = extra;
571          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
572          int i;          int i;
573    
574            relative_addr /= d->addr_mult;
575    
576            if (!d->io_enabled)
577                    goto ret;
578    
579          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
580                  if (relative_addr == wd_data)                  if (relative_addr == wd_data)
581                          idata = memory_readmax64(cpu, data, len);                          idata = memory_readmax64(cpu, data, len);
582                  else                  else {
583                            if (len != 1)
584                                    fatal("[ wdc: WARNING! non-8-bit access! ]\n");
585                          idata = data[0];                          idata = data[0];
586                    }
587          }          }
588    
589          switch (relative_addr) {          switch (relative_addr) {
590    
591          case wd_data:   /*  0: data  */          case wd_data:   /*  0: data  */
592                  if (writeflag == MEM_READ) {                  if (writeflag == MEM_READ) {
593                          odata = 0;                          odata = wdc_get_inbuf(d);
594    
595                          /*  TODO: This is hardcoded for little-endian?  */                          if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
596                                    if (len >= 2)
597                                            odata += (wdc_get_inbuf(d) << 8);
598                                    if (len == 4) {
599                                            odata += (wdc_get_inbuf(d) << 16);
600                                            odata += (wdc_get_inbuf(d) << 24);
601                                    }
602                            } else {
603                                    if (len >= 2)
604                                            odata = (odata << 8) + wdc_get_inbuf(d);
605                                    if (len == 4) {
606                                            odata = (odata << 8) + wdc_get_inbuf(d);
607                                            odata = (odata << 8) + wdc_get_inbuf(d);
608                                    }
609                            }
610    
611                          odata += wdc_get_inbuf(d);                          if (d->data_debug) {
612                          if (len >= 2)                                  char *s = "0x%04"PRIx64" ]\n";
613                                  odata += (wdc_get_inbuf(d) << 8);                                  if (len == 1)
614                          if (len == 4) {                                          s = "0x%02"PRIx64" ]\n";
615                                  odata += (wdc_get_inbuf(d) << 16);                                  if (len == 4)
616                                  odata += (wdc_get_inbuf(d) << 24);                                          s = "0x%08"PRIx64" ]\n";
617                                    if (len == 8)
618                                            s = "0x%016"PRIx64" ]\n";
619                                    debug("[ wdc: read from DATA: ");
620                                    debug(s, (uint64_t) odata);
621                          }                          }
622    
623                          if (d->data_debug)                          if (d->atapi_cmd_in_progress) {
624                                  debug("[ wdc: read from DATA: 0x%04x ]\n",                                  d->atapi_len -= len;
625                                      (int)odata);                                  d->atapi_received += len;
626                                    if (d->atapi_len == 0) {
627                                            if (d->atapi_received < d->atapi_st->
628                                                data_in_len) {
629                                                    d->atapi_phase = PHASE_DATAIN;
630                                                    d->atapi_len = d->atapi_st->
631                                                        data_in_len -
632                                                        d->atapi_received;
633                                                    if (d->atapi_len > 32768)
634                                                            d->atapi_len = 0;
635                                            } else
636                                                    d->atapi_phase =
637                                                        PHASE_COMPLETED;
638                                            d->delayed_interrupt = INT_DELAY;
639                                    }
640                            } else {
641  #if 0  #if 0
642                          if (d->inbuf_tail != d->inbuf_head)                                  if (d->inbuf_tail != d->inbuf_head)
643  #else  #else
644                          if (d->inbuf_tail != d->inbuf_head &&                                  if (d->inbuf_tail != d->inbuf_head &&
645                              ((d->inbuf_tail - d->inbuf_head) % 512) == 0)                                      ((d->inbuf_tail - d->inbuf_head) % 512)
646                                        == 0)
647  #endif  #endif
648                                  d->delayed_interrupt = INT_DELAY;                                          d->delayed_interrupt = INT_DELAY;
649                            }
650                  } else {                  } else {
651                          int inbuf_len;                          int inbuf_len;
652                          if (d->data_debug)                          if (d->data_debug) {
653                                  debug("[ wdc: write to DATA (len=%i): "                                  char *s = "0x%04"PRIx64" ]\n";
654                                      "0x%08lx ]\n", (int)len, (long)idata);                                  if (len == 1)
655                          if (!d->write_in_progress) {                                          s = "0x%02"PRIx64" ]\n";
656                                    if (len == 4)
657                                            s = "0x%08"PRIx64" ]\n";
658                                    if (len == 8)
659                                            s = "0x%016"PRIx64" ]\n";
660                                    debug("[ wdc: write to DATA: ");
661                                    debug(s, (uint64_t) idata);
662                            }
663                            if (!d->write_in_progress &&
664                                !d->atapi_cmd_in_progress) {
665                                  fatal("[ wdc: write to DATA, but not "                                  fatal("[ wdc: write to DATA, but not "
666                                      "expecting any? (len=%i): 0x%08lx ]\n",                                      "expecting any? (len=%i): 0x%08lx ]\n",
667                                      (int)len, (long)idata);                                      (int)len, (long)idata);
668                          }                          }
669    
670                          switch (len) {                          if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
671                          case 4: wdc_addtoinbuf(d, idata & 0xff);                                  switch (len) {
672                                  wdc_addtoinbuf(d, (idata >> 8) & 0xff);                                  case 4: wdc_addtoinbuf(d, idata & 0xff);
673                                  wdc_addtoinbuf(d, (idata >> 16) & 0xff);                                          wdc_addtoinbuf(d, (idata >> 8) & 0xff);
674                                  wdc_addtoinbuf(d, (idata >> 24) & 0xff);                                          wdc_addtoinbuf(d, (idata >> 16) & 0xff);
675                                  break;                                          wdc_addtoinbuf(d, (idata >> 24) & 0xff);
676                          case 2: wdc_addtoinbuf(d, idata & 0xff);                                          break;
677                                  wdc_addtoinbuf(d, (idata >> 8) & 0xff);                                  case 2: wdc_addtoinbuf(d, idata & 0xff);
678                                  break;                                          wdc_addtoinbuf(d, (idata >> 8) & 0xff);
679                          case 1: wdc_addtoinbuf(d, idata); break;                                          break;
680                          default:fatal("wdc: unimplemented write len %i\n", len);                                  case 1: wdc_addtoinbuf(d, idata); break;
681                                  exit(1);                                  default:fatal("wdc: unimplemented write "
682                                                "len %i\n", len);
683                                            exit(1);
684                                    }
685                            } else {
686                                    switch (len) {
687                                    case 4: wdc_addtoinbuf(d, (idata >> 24) & 0xff);
688                                            wdc_addtoinbuf(d, (idata >> 16) & 0xff);
689                                            wdc_addtoinbuf(d, (idata >> 8) & 0xff);
690                                            wdc_addtoinbuf(d, idata & 0xff);
691                                            break;
692                                    case 2: wdc_addtoinbuf(d, (idata >> 8) & 0xff);
693                                            wdc_addtoinbuf(d, idata & 0xff);
694                                            break;
695                                    case 1: wdc_addtoinbuf(d, idata); break;
696                                    default:fatal("wdc: unimplemented write "
697                                                "len %i\n", len);
698                                            exit(1);
699                                    }
700                          }                          }
701    
702                          inbuf_len = d->inbuf_head - d->inbuf_tail;                          inbuf_len = d->inbuf_head - d->inbuf_tail;
703                          while (inbuf_len < 0)                          while (inbuf_len < 0)
704                                  inbuf_len += WDC_INBUF_SIZE;                                  inbuf_len += WDC_INBUF_SIZE;
705    
706  #if 0                          if (d->atapi_cmd_in_progress && inbuf_len == 12) {
707                          if ((inbuf_len % (512 * d->write_count)) == 0) {                                  unsigned char *scsi_cmd = malloc(12);
708  #else                                  int x = 0, res;
709                          if ((inbuf_len % 512) == 0) {  
710  #endif                                  if (d->atapi_st != NULL)
711                                  int count = 1;  /*  d->write_count;  */                                          scsi_transfer_free(d->atapi_st);
712                                  unsigned char buf[512 * count];                                  d->atapi_st = scsi_transfer_alloc();
713    
714                                    debug("[ wdc: ATAPI command ]\n");
715    
716                                    while (inbuf_len > 0) {
717                                            scsi_cmd[x++] = wdc_get_inbuf(d);
718                                            inbuf_len --;
719                                    }
720    
721                                    d->atapi_st->cmd = scsi_cmd;
722                                    d->atapi_st->cmd_len = 12;
723    
724                                    if (scsi_cmd[0] == SCSIBLOCKCMD_READ_CAPACITY
725                                        || scsi_cmd[0] == SCSICMD_READ_10
726                                        || scsi_cmd[0] == SCSICMD_MODE_SENSE10)
727                                            d->atapi_st->cmd_len = 10;
728    
729                                    res = diskimage_scsicommand(cpu,
730                                        d->drive + d->base_drive, DISKIMAGE_IDE,
731                                        d->atapi_st);
732    
733                                    if (res == 0) {
734                                            fatal("WDC: ATAPI scsi error?\n");
735                                            exit(1);
736                                    }
737    
738                                    d->atapi_len = 0;
739                                    d->atapi_received = 0;
740    
741                                    if (res == 1) {
742                                            if (d->atapi_st->data_in != NULL) {
743                                                    int i;
744                                                    d->atapi_phase = PHASE_DATAIN;
745                                                    d->atapi_len = d->atapi_st->
746                                                        data_in_len;
747                                                    for (i=0; i<d->atapi_len; i++)
748                                                            wdc_addtoinbuf(d,
749                                                                d->atapi_st->
750                                                                data_in[i]);
751                                                    if (d->atapi_len > 32768)
752                                                            d->atapi_len = 32768;
753                                            } else {
754                                                    d->atapi_phase =
755                                                        PHASE_COMPLETED;
756                                            }
757                                    } else {
758                                            fatal("wdc atapi Dataout? TODO\n");
759                                            d->atapi_phase = PHASE_DATAOUT;
760                                            exit(1);
761                                    }
762    
763                                    d->delayed_interrupt = INT_DELAY;
764                            }
765    
766                            if (( d->write_in_progress == WDCC_WRITEMULTI &&
767                                inbuf_len % (512 * d->write_count) == 0)
768                                ||
769                                ( d->write_in_progress == WDCC_WRITE &&
770                                inbuf_len % 512 == 0) ) {
771                                    int count = (d->write_in_progress ==
772                                        WDCC_WRITEMULTI)? d->write_count : 1;
773                                    unsigned char *buf = malloc(512 * count);
774                                  unsigned char *b = buf;                                  unsigned char *b = buf;
775    
776                                    if (buf == NULL) {
777                                            fprintf(stderr, "out of memory\n");
778                                            exit(1);
779                                    }
780    
781                                  if (d->inbuf_tail+512*count <= WDC_INBUF_SIZE) {                                  if (d->inbuf_tail+512*count <= WDC_INBUF_SIZE) {
782                                          b = d->inbuf + d->inbuf_tail;                                          b = d->inbuf + d->inbuf_tail;
783                                          d->inbuf_tail = (d->inbuf_tail + 512                                          d->inbuf_tail = (d->inbuf_tail + 512
# Line 447  int dev_wdc_access(struct cpu *cpu, stru Line 791  int dev_wdc_access(struct cpu *cpu, stru
791                                      d->drive + d->base_drive, DISKIMAGE_IDE, 1,                                      d->drive + d->base_drive, DISKIMAGE_IDE, 1,
792                                      d->write_offset, b, 512 * count);                                      d->write_offset, b, 512 * count);
793    
794                                  d->write_count --;                                  d->write_count -= count;
795                                  d->write_offset += 512;                                  d->write_offset += 512 * count;
796    
797                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
798    
799                                  if (d->write_count == 0)                                  if (d->write_count == 0)
800                                          d->write_in_progress = 0;                                          d->write_in_progress = 0;
801    
802                                    free(buf);
803                          }                          }
804                  }                  }
805                  break;                  break;
806    
807          case wd_error:  /*  1: error (r), precomp (w)  */          case wd_error:  /*  1: error (r), precomp (w)  */
808                  if (writeflag==MEM_READ) {                  if (writeflag == MEM_READ) {
809                          odata = d->error;                          odata = d->error;
810                          debug("[ wdc: read from ERROR: 0x%02x ]\n",                          debug("[ wdc: read from ERROR: 0x%02x ]\n", (int)odata);
                             (int)odata);  
811                          /*  TODO:  is the error value cleared on read?  */                          /*  TODO:  is the error value cleared on read?  */
812                          d->error = 0;                          d->error = 0;
813                  } else {                  } else {
# Line 471  int dev_wdc_access(struct cpu *cpu, stru Line 816  int dev_wdc_access(struct cpu *cpu, stru
816                  }                  }
817                  break;                  break;
818    
819          case wd_seccnt: /*  2: sector count  */          case wd_seccnt: /*  2: sector count (or "ireason" for ATAPI)  */
820                  if (writeflag==MEM_READ) {                  if (writeflag == MEM_READ) {
821                          odata = d->seccnt;                          odata = d->seccnt;
822                            if (d->atapi_cmd_in_progress) {
823                                    odata = d->atapi_phase & (WDCI_CMD | WDCI_IN);
824                            }
825                          debug("[ wdc: read from SECCNT: 0x%02x ]\n",(int)odata);                          debug("[ wdc: read from SECCNT: 0x%02x ]\n",(int)odata);
826                  } else {                  } else {
827                          d->seccnt = idata;                          d->seccnt = idata;
# Line 482  int dev_wdc_access(struct cpu *cpu, stru Line 830  int dev_wdc_access(struct cpu *cpu, stru
830                  break;                  break;
831    
832          case wd_sector: /*  3: first sector  */          case wd_sector: /*  3: first sector  */
833                  if (writeflag==MEM_READ) {                  if (writeflag == MEM_READ) {
834                          odata = d->sector;                          odata = d->sector;
835                          debug("[ wdc: read from SECTOR: 0x%02x ]\n",(int)odata);                          debug("[ wdc: read from SECTOR: 0x%02x ]\n",(int)odata);
836                  } else {                  } else {
# Line 492  int dev_wdc_access(struct cpu *cpu, stru Line 840  int dev_wdc_access(struct cpu *cpu, stru
840                  break;                  break;
841    
842          case wd_cyl_lo: /*  4: cylinder low  */          case wd_cyl_lo: /*  4: cylinder low  */
843                  if (writeflag==MEM_READ) {                  if (writeflag == MEM_READ) {
844                          odata = d->cyl_lo;                          odata = d->cyl_lo;
845                            if (d->cur_command == COMMAND_RESET &&
846                                diskimage_is_a_cdrom(cpu->machine,
847                                d->drive + d->base_drive, DISKIMAGE_IDE))
848                                    odata = 0x14;
849                            if (d->atapi_cmd_in_progress) {
850                                    int x = d->atapi_len;
851                                    if (x > 32768)
852                                            x = 32768;
853                                    odata = x & 255;
854                            }
855                          debug("[ wdc: read from CYL_LO: 0x%02x ]\n",(int)odata);                          debug("[ wdc: read from CYL_LO: 0x%02x ]\n",(int)odata);
856                  } else {                  } else {
857                          d->cyl_lo = idata;                          d->cyl_lo = idata;
# Line 501  int dev_wdc_access(struct cpu *cpu, stru Line 859  int dev_wdc_access(struct cpu *cpu, stru
859                  }                  }
860                  break;                  break;
861    
862          case wd_cyl_hi: /*  5: cylinder low  */          case wd_cyl_hi: /*  5: cylinder high  */
863                  if (writeflag==MEM_READ) {                  if (writeflag == MEM_READ) {
864                          odata = d->cyl_hi;                          odata = d->cyl_hi;
865                            if (d->cur_command == COMMAND_RESET &&
866                                diskimage_is_a_cdrom(cpu->machine,
867                                d->drive + d->base_drive, DISKIMAGE_IDE))
868                                    odata = 0xeb;
869                            if (d->atapi_cmd_in_progress) {
870                                    int x = d->atapi_len;
871                                    if (x > 32768)
872                                            x = 32768;
873                                    odata = (x >> 8) & 255;
874                            }
875                          debug("[ wdc: read from CYL_HI: 0x%02x ]\n",(int)odata);                          debug("[ wdc: read from CYL_HI: 0x%02x ]\n",(int)odata);
876                  } else {                  } else {
877                          d->cyl_hi = idata;                          d->cyl_hi = idata;
# Line 536  int dev_wdc_access(struct cpu *cpu, stru Line 904  int dev_wdc_access(struct cpu *cpu, stru
904                                  debug("[ wdc: read from STATUS: 0x%02x ]\n",                                  debug("[ wdc: read from STATUS: 0x%02x ]\n",
905                                      (int)odata);                                      (int)odata);
906                          cpu_interrupt_ack(cpu, d->irq_nr);                          cpu_interrupt_ack(cpu, d->irq_nr);
907                            d->int_asserted = 0;
908                          d->delayed_interrupt = 0;                          d->delayed_interrupt = 0;
909                  } else {                  } else {
910                          debug("[ wdc: write to COMMAND: 0x%02x ]\n",(int)idata);                          debug("[ wdc: write to COMMAND: 0x%02x ]\n",(int)idata);
911                          d->cur_command = idata;                          wdc_command(cpu, d, idata);
   
                         /*  TODO:  Is this correct behaviour?  */  
                         if (!diskimage_exist(cpu->machine,  
                             d->drive + d->base_drive, DISKIMAGE_IDE)) {  
                                 d->error |= WDCE_ABRT;  
                                 d->delayed_interrupt = INT_DELAY;  
                                 break;  
                         }  
   
                         /*  Handle the command:  */  
                         switch (d->cur_command) {  
   
                         case WDCC_READ:  
                                 if (!quiet_mode)  
                                         debug("[ wdc: READ from drive %i, head"  
                                             " %i, cyl %i, sector %i, nsecs %i "  
                                             "]\n", d->drive, d->head,  
                                             d->cyl_hi*256+d->cyl_lo, d->sector,  
                                             d->seccnt);  
                                 wdc__read(cpu, d);  
                                 break;  
   
                         case WDCC_WRITE:  
                                 if (!quiet_mode)  
                                         debug("[ wdc: WRITE to drive %i, head"  
                                             " %i, cyl %i, sector %i, nsecs %i"  
                                             " ]\n", d->drive, d->head,  
                                             d->cyl_hi*256+d->cyl_lo, d->sector,  
                                             d->seccnt);  
                                 wdc__write(cpu, d);  
                                 break;  
   
                         case WDCC_IDP:  /*  Initialize drive parameters  */  
                                 debug("[ wdc: IDP drive %i (TODO) ]\n",  
                                     d->drive);  
                                 /*  TODO  */  
                                 d->delayed_interrupt = INT_DELAY;  
                                 break;  
   
                         case SET_FEATURES:  
                                 fatal("[ wdc: SET_FEATURES drive %i (TODO), "  
                                     "feature 0x%02x ]\n", d->drive, d->precomp);  
                                 /*  TODO  */  
                                 switch (d->precomp) {  
                                 case WDSF_SET_MODE:  
                                         fatal("[ wdc: WDSF_SET_MODE drive %i, "  
                                             "pio/dma flags 0x%02x ]\n",  
                                             d->drive, d->seccnt);  
                                         break;  
                                 default:  
                                         d->error |= WDCE_ABRT;  
                                 }  
                                 /*  TODO: always interrupt?  */  
                                 d->delayed_interrupt = INT_DELAY;  
                                 break;  
   
                         case WDCC_RECAL:  
                                 debug("[ wdc: RECAL drive %i ]\n", d->drive);  
                                 d->delayed_interrupt = INT_DELAY;  
                                 break;  
   
                         case WDCC_IDENTIFY:  
                                 debug("[ wdc: IDENTIFY drive %i ]\n", d->drive);  
                                 wdc_initialize_identify_struct(cpu, d);  
                                 /*  The IDENTIFY data block is sent out  
                                     in low/high byte order:  */  
                                 for (i=0; i<sizeof(d->identify_struct); i+=2) {  
                                         wdc_addtoinbuf(d, d->identify_struct  
                                             [i+1]);  
                                         wdc_addtoinbuf(d, d->identify_struct  
                                             [i+0]);  
                                 }  
                                 d->delayed_interrupt = INT_DELAY;  
                                 break;  
   
                         case WDCC_IDLE_IMMED:  
                                 debug("[ wdc: IDLE_IMMED drive %i ]\n",  
                                     d->drive);  
                                 /*  TODO: interrupt here?  */  
                                 d->delayed_interrupt = INT_DELAY;  
                                 break;  
   
                         /*  Unsupported commands, without warning:  */  
                         case ATAPI_IDENTIFY_DEVICE:  
                         case WDCC_SEC_SET_PASSWORD:  
                         case WDCC_SEC_UNLOCK:  
                         case WDCC_SEC_ERASE_PREPARE:  
                         case WDCC_SEC_ERASE_UNIT:  
                         case WDCC_SEC_FREEZE_LOCK:  
                         case WDCC_SEC_DISABLE_PASSWORD:  
                                 d->error |= WDCE_ABRT;  
                                 break;  
   
                         default:  
                                 /*  TODO  */  
                                 d->error |= WDCE_ABRT;  
   
                                 fatal("[ wdc: WARNING! Unimplemented command "  
                                     "0x%02x (drive %i, head %i, cyl %i, sector"  
                                     " %i, nsecs %i) ]\n", d->cur_command,  
                                     d->drive, d->head, d->cyl_hi*256+d->cyl_lo,  
                                     d->sector, d->seccnt);  
                         }  
912                  }                  }
913                  break;                  break;
914    
# Line 655  int dev_wdc_access(struct cpu *cpu, stru Line 921  int dev_wdc_access(struct cpu *cpu, stru
921                              (int)relative_addr, (int)idata);                              (int)relative_addr, (int)idata);
922          }          }
923    
924          if (cpu->machine->machine_type != MACHINE_HPCMIPS)  
925            if (cpu->machine->machine_type != MACHINE_HPCMIPS &&
926                cpu->machine->machine_type != MACHINE_EVBMIPS &&
927                cpu->machine->machine_type != MACHINE_ALGOR &&
928                cpu->machine->machine_type != MACHINE_BEBOX)
929                  dev_wdc_tick(cpu, extra);                  dev_wdc_tick(cpu, extra);
930    
931    ret:
932          if (writeflag == MEM_READ) {          if (writeflag == MEM_READ) {
933                  if (relative_addr == wd_data)                  if (relative_addr == wd_data)
934                          memory_writemax64(cpu, data, len, odata);                          memory_writemax64(cpu, data, len, odata);
# Line 669  int dev_wdc_access(struct cpu *cpu, stru Line 940  int dev_wdc_access(struct cpu *cpu, stru
940  }  }
941    
942    
943  /*  DEVINIT(wdc)
  *  devinit_wdc():  
  */  
 int devinit_wdc(struct devinit *devinit)  
944  {  {
945          struct wdc_data *d;          struct wdc_data *d;
946          uint64_t alt_status_addr;          uint64_t alt_status_addr;
# Line 684  int devinit_wdc(struct devinit *devinit) Line 952  int devinit_wdc(struct devinit *devinit)
952                  exit(1);                  exit(1);
953          }          }
954          memset(d, 0, sizeof(struct wdc_data));          memset(d, 0, sizeof(struct wdc_data));
955          d->irq_nr = devinit->irq_nr;          d->irq_nr     = devinit->irq_nr;
956            d->addr_mult  = devinit->addr_mult;
957            d->data_debug = 1;
958            d->io_enabled = 1;
959    
960            d->inbuf = zeroed_alloc(WDC_INBUF_SIZE);
961    
962          /*  base_drive = 0 for the primary controller, 2 for the secondary.  */          /*  base_drive = 0 for the primary controller, 2 for the secondary.  */
963          d->base_drive = 0;          d->base_drive = 0;
# Line 693  int devinit_wdc(struct devinit *devinit) Line 966  int devinit_wdc(struct devinit *devinit)
966    
967          alt_status_addr = devinit->addr + 0x206;          alt_status_addr = devinit->addr + 0x206;
968    
969          /*  Special hack for pcic/hpcmips:  TODO: Fix  */          /*  Special hacks for individual machines:  */
970          if (devinit->addr == 0x14000180)          switch (devinit->machine->machine_type) {
971                  alt_status_addr = 0x14000386;          case MACHINE_MACPPC:
972                    alt_status_addr = devinit->addr + 0x160;
973                    break;
974            case MACHINE_HPCMIPS:
975                    /*  TODO: Fix  */
976                    if (devinit->addr == 0x14000180)
977                            alt_status_addr = 0x14000386;
978                    break;
979            case MACHINE_IQ80321:
980                    alt_status_addr = devinit->addr + 0x402;
981                    break;
982            }
983    
984          /*  Get disk geometries:  */          /*  Get disk geometries:  */
985          for (i=0; i<2; i++)          for (i=0; i<2; i++)
# Line 706  int devinit_wdc(struct devinit *devinit) Line 990  int devinit_wdc(struct devinit *devinit)
990                              &d->sectors_per_track[i]);                              &d->sectors_per_track[i]);
991    
992          memory_device_register(devinit->machine->memory, "wdc_altstatus",          memory_device_register(devinit->machine->memory, "wdc_altstatus",
993              alt_status_addr, 2, dev_wdc_altstatus_access, d, MEM_DEFAULT, NULL);              alt_status_addr, 2, dev_wdc_altstatus_access, d, DM_DEFAULT, NULL);
994          memory_device_register(devinit->machine->memory, devinit->name,          memory_device_register(devinit->machine->memory, devinit->name,
995              devinit->addr, DEV_WDC_LENGTH, dev_wdc_access, d, MEM_DEFAULT,              devinit->addr, DEV_WDC_LENGTH * devinit->addr_mult, dev_wdc_access,
996              NULL);              d, DM_DEFAULT, NULL);
997    
998          if (devinit->machine->machine_type != MACHINE_HPCMIPS)          if (devinit->machine->machine_type != MACHINE_HPCMIPS &&
999                  tick_shift += 2;              devinit->machine->machine_type != MACHINE_EVBMIPS)
1000                    tick_shift += 1;
1001    
1002          machine_add_tickfunction(devinit->machine, dev_wdc_tick,          machine_add_tickfunction(devinit->machine, dev_wdc_tick,
1003              d, tick_shift);              d, tick_shift, 0.0);
1004    
1005            devinit->return_ptr = d;
1006    
1007          return 1;          return 1;
1008  }  }

Legend:
Removed from v.18  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC 1.1.26