/[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 6 by dpavlin, Mon Oct 8 16:18:11 2007 UTC revision 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC
# Line 23  Line 23 
23   *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY   *  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   *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
  *    
26   *   *
27   *  $Id: dev_wdc.c,v 1.37 2005/05/27 07:29:25 debug Exp $   *
28   *     *  $Id: dev_wdc.c,v 1.39 2005/09/27 23:55:44 debug Exp $
29   *  Standard IDE controller.   *
30     *  Standard "wdc" IDE controller.
31   */   */
32    
33  #include <stdio.h>  #include <stdio.h>
# Line 35  Line 35 
35  #include <string.h>  #include <string.h>
36    
37  #include "console.h"  #include "console.h"
 #include "cop0.h"  
38  #include "cpu.h"  #include "cpu.h"
39  #include "devices.h"  #include "device.h"
40  #include "diskimage.h"  #include "diskimage.h"
41  #include "machine.h"  #include "machine.h"
42  #include "memory.h"  #include "memory.h"
# Line 45  Line 44 
44    
45  #include "wdcreg.h"  #include "wdcreg.h"
46    
47    #define DEV_WDC_LENGTH          8
48  #define WDC_TICK_SHIFT          14  #define WDC_TICK_SHIFT          14
49  #define WDC_INBUF_SIZE          (512*257)  #define WDC_INBUF_SIZE          (512*257)
50    
51  /*  INT_DELAY=2 to be safe, 1 is faster but maybe buggy.  */  /*
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  #define INT_DELAY               1
60    
61  extern int quiet_mode;  extern int quiet_mode;
62    
63  /*  #define debug fatal  */  /*  #define debug fatal  */
 /*  #define DATA_DEBUG  */  
64    
65  struct wdc_data {  struct wdc_data {
66          int             irq_nr;          int             irq_nr;
67          int             base_drive;          int             base_drive;
68            int             data_debug;
69    
70          int             delayed_interrupt;          /*  Cached values:  */
71            int             cyls[2];
72            int             heads[2];
73            int             sectors_per_track[2];
74    
75          unsigned char   identify_struct[512];          unsigned char   identify_struct[512];
76    
# Line 69  struct wdc_data { Line 78  struct wdc_data {
78          int             inbuf_head;          int             inbuf_head;
79          int             inbuf_tail;          int             inbuf_tail;
80    
81            int             delayed_interrupt;
82          int             write_in_progress;          int             write_in_progress;
83          int             write_count;          int             write_count;
84          int64_t         write_offset;          int64_t         write_offset;
# Line 144  static uint64_t wdc_get_inbuf(struct wdc Line 154  static uint64_t wdc_get_inbuf(struct wdc
154  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)
155  {  {
156          uint64_t total_size;          uint64_t total_size;
157          int cyls, heads, sectors_per_track;          char namebuf[40];
158    
159          total_size = diskimage_getsize(cpu->machine, d->drive + d->base_drive,          total_size = diskimage_getsize(cpu->machine, d->drive + d->base_drive,
160              DISKIMAGE_IDE);              DISKIMAGE_IDE);
161    
         diskimage_getchs(cpu->machine, d->drive + d->base_drive,  
             DISKIMAGE_IDE, &cyls, &heads, &sectors_per_track);  
   
162          memset(d->identify_struct, 0, sizeof(d->identify_struct));          memset(d->identify_struct, 0, sizeof(d->identify_struct));
163    
164          /*  Offsets are in 16-bit WORDS!  High byte, then low.  */          /*  Offsets are in 16-bit WORDS!  High byte, then low.  */
# Line 161  static void wdc_initialize_identify_stru Line 168  static void wdc_initialize_identify_stru
168          d->identify_struct[2 * 0 + 1] = 1 << 6;          d->identify_struct[2 * 0 + 1] = 1 << 6;
169    
170          /*  1: nr of cylinders  */          /*  1: nr of cylinders  */
171          d->identify_struct[2 * 1 + 0] = (cyls >> 8);          d->identify_struct[2 * 1 + 0] = (d->cyls[d->drive] >> 8);
172          d->identify_struct[2 * 1 + 1] = cyls & 255;          d->identify_struct[2 * 1 + 1] = d->cyls[d->drive] & 255;
173    
174          /*  3: nr of heads  */          /*  3: nr of heads  */
175          d->identify_struct[2 * 3 + 0] = heads >> 8;          d->identify_struct[2 * 3 + 0] = d->heads[d->drive] >> 8;
176          d->identify_struct[2 * 3 + 1] = heads;          d->identify_struct[2 * 3 + 1] = d->heads[d->drive];
177    
178          /*  6: sectors per track  */          /*  6: sectors per track  */
179          d->identify_struct[2 * 6 + 0] = sectors_per_track >> 8;          d->identify_struct[2 * 6 + 0] = d->sectors_per_track[d->drive] >> 8;
180          d->identify_struct[2 * 6 + 1] = sectors_per_track;          d->identify_struct[2 * 6 + 1] = d->sectors_per_track[d->drive];
181    
182          /*  10-19: Serial number  */          /*  10-19: Serial number  */
183          memcpy(&d->identify_struct[2 * 10], "S/N 1234-5678       ", 20);          memcpy(&d->identify_struct[2 * 10], "S/N 1234-5678       ", 20);
# Line 179  static void wdc_initialize_identify_stru Line 186  static void wdc_initialize_identify_stru
186          memcpy(&d->identify_struct[2 * 23], "VER 1.0 ", 8);          memcpy(&d->identify_struct[2 * 23], "VER 1.0 ", 8);
187    
188          /*  27-46: Model number  */          /*  27-46: Model number  */
189          memcpy(&d->identify_struct[2 * 27],          if (diskimage_getname(cpu->machine, d->drive + d->base_drive,
190              "Fake GXemul IDE disk                    ", 40);              DISKIMAGE_IDE, namebuf, sizeof(namebuf))) {
191          /*  TODO:  Use the diskimage's filename instead?  */                  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  */          /*  47: max sectors per multitransfer  */
204          d->identify_struct[2 * 47 + 0] = 0x80;          d->identify_struct[2 * 47 + 0] = 0x80;
# Line 203  static void wdc_initialize_identify_stru Line 220  static void wdc_initialize_identify_stru
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():   *  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)  static int status_byte(struct wdc_data *d, struct cpu *cpu)
289  {  {
290          int odata = 0;          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,          if (diskimage_exist(cpu->machine, d->drive + d->base_drive,
297              DISKIMAGE_IDE))              DISKIMAGE_IDE))
298                  odata |= WDCS_DRDY;                  odata |= WDCS_DRDY | WDCS_DSC;
299          if (d->inbuf_head != d->inbuf_tail)          if (d->inbuf_head != d->inbuf_tail)
300                  odata |= WDCS_DRQ;                  odata |= WDCS_DRQ;
301          if (d->write_in_progress)          if (d->write_in_progress)
# Line 219  static int status_byte(struct wdc_data * Line 303  static int status_byte(struct wdc_data *
303          if (d->error)          if (d->error)
304                  odata |= WDCS_ERR;                  odata |= WDCS_ERR;
305    
 #if 0  
         /*  
          *  TODO:  Is this correct behaviour?  
          *  
          *  NetBSD/cobalt seems to want it, but Linux on MobilePro does not.  
          */  
         if (!diskimage_exist(cpu->machine, d->drive + d->base_drive,  
             DISKIMAGE_IDE))  
                 odata = 0xff;  
 #endif  
   
306          return odata;          return odata;
307  }  }
308    
# Line 272  int dev_wdc_access(struct cpu *cpu, stru Line 345  int dev_wdc_access(struct cpu *cpu, stru
345  {  {
346          struct wdc_data *d = extra;          struct wdc_data *d = extra;
347          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
348          int i, cyls, heads, sectors_per_track;          int i;
349    
350          idata = memory_readmax64(cpu, data, len);          idata = memory_readmax64(cpu, data, len);
351    
# Line 292  int dev_wdc_access(struct cpu *cpu, stru Line 365  int dev_wdc_access(struct cpu *cpu, stru
365                                  odata += (wdc_get_inbuf(d) << 24);                                  odata += (wdc_get_inbuf(d) << 24);
366                          }                          }
367    
368  #ifdef DATA_DEBUG                          if (d->data_debug)
369                          debug("[ wdc: read from DATA: 0x%04x ]\n", odata);                                  debug("[ wdc: read from DATA: 0x%04x ]\n",
370  #endif                                      (int)odata);
   
371                          if (d->inbuf_tail != d->inbuf_head)                          if (d->inbuf_tail != d->inbuf_head)
372                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
   
373                  } else {                  } else {
374                          int inbuf_len;                          int inbuf_len;
375  #ifdef DATA_DEBUG                          if (d->data_debug)
376                          debug("[ wdc: write to DATA (len=%i): 0x%08lx ]\n",                                  debug("[ wdc: write to DATA (len=%i): "
377                              (int)len, (long)idata);                                      "0x%08lx ]\n", (int)len, (long)idata);
 #endif  
378                          if (!d->write_in_progress) {                          if (!d->write_in_progress) {
379                                  fatal("[ wdc: write to DATA, but not "                                  fatal("[ wdc: write to DATA, but not "
380                                      "expecting any? (len=%i): 0x%08lx ]\n",                                      "expecting any? (len=%i): 0x%08lx ]\n",
# Line 331  int dev_wdc_access(struct cpu *cpu, stru Line 401  int dev_wdc_access(struct cpu *cpu, stru
401    
402  #if 0  #if 0
403                          if ((inbuf_len % (512 * d->write_count)) == 0) {                          if ((inbuf_len % (512 * d->write_count)) == 0) {
404  #endif  #else
405                          if ((inbuf_len % 512) == 0) {                          if ((inbuf_len % 512) == 0) {
406    #endif
407                                  int count = 1;  /*  d->write_count;  */                                  int count = 1;  /*  d->write_count;  */
408                                  unsigned char *buf = malloc(count * 512);                                  unsigned char *buf = malloc(count * 512);
409                                  if (buf == NULL) {                                  if (buf == NULL) {
# Line 362  int dev_wdc_access(struct cpu *cpu, stru Line 433  int dev_wdc_access(struct cpu *cpu, stru
433          case wd_error:  /*  1: error (r), precomp (w)  */          case wd_error:  /*  1: error (r), precomp (w)  */
434                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
435                          odata = d->error;                          odata = d->error;
436                          debug("[ wdc: read from ERROR: 0x%02x ]\n", odata);                          debug("[ wdc: read from ERROR: 0x%02x ]\n",
437                                (int)odata);
438                          /*  TODO:  is the error value cleared on read?  */                          /*  TODO:  is the error value cleared on read?  */
439                          d->error = 0;                          d->error = 0;
440                  } else {                  } else {
441                          d->precomp = idata;                          d->precomp = idata;
442                          debug("[ wdc: write to PRECOMP: 0x%02x ]\n", idata);                          debug("[ wdc: write to PRECOMP: 0x%02x ]\n",(int)idata);
443                  }                  }
444                  break;                  break;
445    
446          case wd_seccnt: /*  2: sector count  */          case wd_seccnt: /*  2: sector count  */
447                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
448                          odata = d->seccnt;                          odata = d->seccnt;
449                          debug("[ wdc: read from SECCNT: 0x%02x ]\n", odata);                          debug("[ wdc: read from SECCNT: 0x%02x ]\n",(int)odata);
450                  } else {                  } else {
451                          d->seccnt = idata;                          d->seccnt = idata;
452                          debug("[ wdc: write to SECCNT: 0x%02x ]\n", idata);                          debug("[ wdc: write to SECCNT: 0x%02x ]\n", (int)idata);
453                  }                  }
454                  break;                  break;
455    
456          case wd_sector: /*  3: first sector  */          case wd_sector: /*  3: first sector  */
457                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
458                          odata = d->sector;                          odata = d->sector;
459                          debug("[ wdc: read from SECTOR: 0x%02x ]\n", odata);                          debug("[ wdc: read from SECTOR: 0x%02x ]\n",(int)odata);
460                  } else {                  } else {
461                          d->sector = idata;                          d->sector = idata;
462                          debug("[ wdc: write to SECTOR: 0x%02x ]\n", idata);                          debug("[ wdc: write to SECTOR: 0x%02x ]\n", (int)idata);
463                  }                  }
464                  break;                  break;
465    
466          case wd_cyl_lo: /*  4: cylinder low  */          case wd_cyl_lo: /*  4: cylinder low  */
467                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
468                          odata = d->cyl_lo;                          odata = d->cyl_lo;
469                          debug("[ wdc: read from CYL_LO: 0x%02x ]\n", odata);                          debug("[ wdc: read from CYL_LO: 0x%02x ]\n",(int)odata);
470                  } else {                  } else {
471                          d->cyl_lo = idata;                          d->cyl_lo = idata;
472                          debug("[ wdc: write to CYL_LO: 0x%02x ]\n", idata);                          debug("[ wdc: write to CYL_LO: 0x%02x ]\n", (int)idata);
473                  }                  }
474                  break;                  break;
475    
476          case wd_cyl_hi: /*  5: cylinder low  */          case wd_cyl_hi: /*  5: cylinder low  */
477                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
478                          odata = d->cyl_hi;                          odata = d->cyl_hi;
479                          debug("[ wdc: read from CYL_HI: 0x%02x ]\n", odata);                          debug("[ wdc: read from CYL_HI: 0x%02x ]\n",(int)odata);
480                  } else {                  } else {
481                          d->cyl_hi = idata;                          d->cyl_hi = idata;
482                          debug("[ wdc: write to CYL_HI: 0x%02x ]\n", idata);                          debug("[ wdc: write to CYL_HI: 0x%02x ]\n", (int)idata);
483                  }                  }
484                  break;                  break;
485    
# Line 432  int dev_wdc_access(struct cpu *cpu, stru Line 504  int dev_wdc_access(struct cpu *cpu, stru
504          case wd_command:        /*  7: command or status  */          case wd_command:        /*  7: command or status  */
505                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
506                          odata = status_byte(d, cpu);                          odata = status_byte(d, cpu);
 #if 1  
507                          if (!quiet_mode)                          if (!quiet_mode)
508                                  debug("[ wdc: read from STATUS: 0x%02x ]\n",                                  debug("[ wdc: read from STATUS: 0x%02x ]\n",
509                                      odata);                                      (int)odata);
 #endif  
   
510                          cpu_interrupt_ack(cpu, d->irq_nr);                          cpu_interrupt_ack(cpu, d->irq_nr);
511                          d->delayed_interrupt = 0;                          d->delayed_interrupt = 0;
512                  } else {                  } else {
513                          debug("[ wdc: write to COMMAND: 0x%02x ]\n", idata);                          debug("[ wdc: write to COMMAND: 0x%02x ]\n",(int)idata);
514                          d->cur_command = idata;                          d->cur_command = idata;
515    
516                          /*  TODO:  Is this correct behaviour?  */                          /*  TODO:  Is this correct behaviour?  */
# Line 454  int dev_wdc_access(struct cpu *cpu, stru Line 523  int dev_wdc_access(struct cpu *cpu, stru
523    
524                          /*  Handle the command:  */                          /*  Handle the command:  */
525                          switch (d->cur_command) {                          switch (d->cur_command) {
                         case WDCC_READ:  
                                 debug("[ wdc: READ from drive %i, head %i, "  
                                     "cylinder %i, sector %i, nsecs %i ]\n",  
                                     d->drive, d->head, d->cyl_hi*256+d->cyl_lo,  
                                     d->sector, d->seccnt);  
                                 /*  TODO:  HAHA! This should be removed  
                                     quickly  */  
                                 diskimage_getchs(cpu->machine, d->drive +  
                                     d->base_drive, DISKIMAGE_IDE, &cyls,  
                                     &heads, &sectors_per_track);  
   
                                 {  
                                         unsigned char buf[512*256];  
                                         int cyl = d->cyl_hi * 256+ d->cyl_lo;  
                                         int count = d->seccnt? d->seccnt : 256;  
                                         uint64_t offset = 512 * (d->sector - 1  
                                             + d->head * sectors_per_track +  
                                             heads*sectors_per_track*cyl);  
526    
527  #if 0                          case WDCC_READ:
528  /*  LBA:  */                                  if (!quiet_mode)
529  if (d->lba)                                          debug("[ wdc: READ from drive %i, head"
530          offset = 512 * (((d->head & 0xf) << 24) + (cyl << 8) + d->sector);                                              " %i, cyl %i, sector %i, nsecs %i "
531  printf("WDC read from offset %lli\n", (long long)offset);                                              "]\n", d->drive, d->head,
532  #endif                                              d->cyl_hi*256+d->cyl_lo, d->sector,
533                                          diskimage_access(cpu->machine,                                              d->seccnt);
534                                              d->drive + d->base_drive,                                  wdc__read(cpu, d);
                                             DISKIMAGE_IDE, 0,  
                                             offset, buf, 512 * count);  
                                         /*  TODO: result code  */  
                                         for (i=0; i<512 * count; i++)  
                                                 wdc_addtoinbuf(d, buf[i]);  
                                 }  
                                 d->delayed_interrupt = INT_DELAY;  
535                                  break;                                  break;
                         case WDCC_WRITE:  
                                 debug("[ wdc: WRITE to drive %i, head %i, "  
                                     "cylinder %i, sector %i, nsecs %i ]\n",  
                                     d->drive, d->head, d->cyl_hi*256+d->cyl_lo,  
                                     d->sector, d->seccnt);  
                                 /*  TODO:  HAHA! This should be removed  
                                     quickly  */  
                                 diskimage_getchs(cpu->machine, d->drive +  
                                     d->base_drive, DISKIMAGE_IDE, &cyls,  
                                     &heads, &sectors_per_track);  
                                 {  
                                         int cyl = d->cyl_hi * 256+ d->cyl_lo;  
                                         int count = d->seccnt? d->seccnt : 256;  
                                         uint64_t offset = 512 * (d->sector - 1  
                                             + d->head * sectors_per_track +  
                                             heads*sectors_per_track*cyl);  
   
 #if 0  
 /*  LBA:  */  
 if (d->lba)  
         offset = 512 * (((d->head & 0xf) << 24) + (cyl << 8) + d->sector);  
 printf("WDC write to offset %lli\n", (long long)offset);  
 #endif  
   
                                         d->write_in_progress = 1;  
                                         d->write_count = count;  
                                         d->write_offset = offset;  
536    
537                                          /*  TODO: result code  */                          case WDCC_WRITE:
538                                  }                                  if (!quiet_mode)
539  /*  TODO: Really interrupt here?  */                                          debug("[ wdc: WRITE to drive %i, head"
540  #if 0                                              " %i, cyl %i, sector %i, nsecs %i"
541                                  d->delayed_interrupt = INT_DELAY;                                              " ]\n", d->drive, d->head,
542  #endif                                              d->cyl_hi*256+d->cyl_lo, d->sector,
543                                                d->seccnt);
544                                    wdc__write(cpu, d);
545                                  break;                                  break;
546    
547                          case WDCC_IDP:  /*  Initialize drive parameters  */                          case WDCC_IDP:  /*  Initialize drive parameters  */
# Line 531  printf("WDC write to offset %lli\n", (lo Line 550  printf("WDC write to offset %lli\n", (lo
550                                  /*  TODO  */                                  /*  TODO  */
551                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
552                                  break;                                  break;
553    
554                          case SET_FEATURES:                          case SET_FEATURES:
555                                  fatal("[ wdc: SET_FEATURES drive %i (TODO), "                                  fatal("[ wdc: SET_FEATURES drive %i (TODO), "
556                                      "feature 0x%02x ]\n", d->drive, d->precomp);                                      "feature 0x%02x ]\n", d->drive, d->precomp);
# Line 547  printf("WDC write to offset %lli\n", (lo Line 567  printf("WDC write to offset %lli\n", (lo
567                                  /*  TODO: always interrupt?  */                                  /*  TODO: always interrupt?  */
568                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
569                                  break;                                  break;
570    
571                          case WDCC_RECAL:                          case WDCC_RECAL:
572                                  debug("[ wdc: RECAL drive %i ]\n", d->drive);                                  debug("[ wdc: RECAL drive %i ]\n", d->drive);
573                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
574                                  break;                                  break;
575    
576                          case WDCC_IDENTIFY:                          case WDCC_IDENTIFY:
577                                  debug("[ wdc: IDENTIFY drive %i ]\n", d->drive);                                  debug("[ wdc: IDENTIFY drive %i ]\n", d->drive);
578                                  wdc_initialize_identify_struct(cpu, d);                                  wdc_initialize_identify_struct(cpu, d);
# Line 564  printf("WDC write to offset %lli\n", (lo Line 586  printf("WDC write to offset %lli\n", (lo
586                                  }                                  }
587                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
588                                  break;                                  break;
589    
590                          case WDCC_IDLE_IMMED:                          case WDCC_IDLE_IMMED:
591                                  debug("[ wdc: IDLE_IMMED drive %i ]\n",                                  debug("[ wdc: IDLE_IMMED drive %i ]\n",
592                                      d->drive);                                      d->drive);
593                                  /*  TODO: interrupt here?  */                                  /*  TODO: interrupt here?  */
594                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
595                                  break;                                  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:                          default:
609                                  /*  TODO  */                                  /*  TODO  */
610                                  d->error |= WDCE_ABRT;                                  d->error |= WDCE_ABRT;
611    
612                                  fatal("[ wdc: unknown command 0x%02x ("                                  fatal("[ wdc: WARNING! Unimplemented command "
613                                      "drive %i, head %i, cylinder %i, sector %i,"                                      "0x%02x (drive %i, head %i, cyl %i, sector"
614                                      " nsecs %i) ]\n", d->cur_command, d->drive,                                      " %i, nsecs %i) ]\n", d->cur_command,
615                                      d->head, d->cyl_hi*256+d->cyl_lo,                                      d->drive, d->head, d->cyl_hi*256+d->cyl_lo,
616                                      d->sector, d->seccnt);                                      d->sector, d->seccnt);
                                 exit(1);  
617                          }                          }
618                  }                  }
619                  break;                  break;
# Line 601  printf("WDC write to offset %lli\n", (lo Line 635  printf("WDC write to offset %lli\n", (lo
635    
636    
637  /*  /*
638   *  dev_wdc_init():   *  devinit_wdc():
  *  
  *  base_drive should be 0 for the primary device, and 2 for the secondary.  
639   */   */
640  void dev_wdc_init(struct machine *machine, struct memory *mem,  int devinit_wdc(struct devinit *devinit)
         uint64_t baseaddr, int irq_nr, int base_drive)  
641  {  {
642          struct wdc_data *d;          struct wdc_data *d;
643          uint64_t alt_status_addr;          uint64_t alt_status_addr;
644            int i;
645    
646          d = malloc(sizeof(struct wdc_data));          d = malloc(sizeof(struct wdc_data));
647          if (d == NULL) {          if (d == NULL) {
# Line 617  void dev_wdc_init(struct machine *machin Line 649  void dev_wdc_init(struct machine *machin
649                  exit(1);                  exit(1);
650          }          }
651          memset(d, 0, sizeof(struct wdc_data));          memset(d, 0, sizeof(struct wdc_data));
652          d->irq_nr     = irq_nr;          d->irq_nr = devinit->irq_nr;
653          d->base_drive = base_drive;  
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 = baseaddr + 0x206;          alt_status_addr = devinit->addr + 0x206;
660    
661          /*  Special hack for pcic/hpcmips:  TODO: Fix  */          /*  Special hack for pcic/hpcmips:  TODO: Fix  */
662          if (baseaddr == 0x14000180)          if (devinit->addr == 0x14000180)
663                  alt_status_addr = 0x14000386;                  alt_status_addr = 0x14000386;
664    
665          memory_device_register(mem, "wdc_altstatus", alt_status_addr, 2,          /*  Get disk geometries:  */
666              dev_wdc_altstatus_access, d, MEM_DEFAULT, NULL);          for (i=0; i<2; i++)
667          memory_device_register(mem, "wdc", baseaddr, DEV_WDC_LENGTH,                  if (diskimage_exist(devinit->machine, d->base_drive +i,
668              dev_wdc_access, d, MEM_DEFAULT, NULL);                      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(machine, dev_wdc_tick,          machine_add_tickfunction(devinit->machine, dev_wdc_tick,
680              d, WDC_TICK_SHIFT);              d, WDC_TICK_SHIFT);
681    
682            return 1;
683  }  }
684    

Legend:
Removed from v.6  
changed lines
  Added in v.14

  ViewVC Help
Powered by ViewVC 1.1.26