/[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 20 by dpavlin, Mon Oct 8 16:19:23 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.56 2005/11/23 23:31:36 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 66  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];
# Line 101  struct wdc_data { Line 103  struct wdc_data {
103          int             atapi_phase;          int             atapi_phase;
104          struct scsi_transfer *atapi_st;          struct scsi_transfer *atapi_st;
105          int             atapi_len;          int             atapi_len;
106          int             atapi_received;          size_t          atapi_received;
107    
108          unsigned char   identify_struct[512];          unsigned char   identify_struct[512];
109  };  };
# Line 129  void dev_wdc_tick(struct cpu *cpu, void Line 131  void dev_wdc_tick(struct cpu *cpu, void
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 211  static void wdc_initialize_identify_stru Line 230  static void wdc_initialize_identify_stru
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 368  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;
# Line 402  int dev_wdc_altstatus_access(struct cpu Line 419  int dev_wdc_altstatus_access(struct cpu
419   */   */
420  void wdc_command(struct cpu *cpu, struct wdc_data *d, int idata)  void wdc_command(struct cpu *cpu, struct wdc_data *d, int idata)
421  {  {
422          int i;          size_t i;
423    
424          d->cur_command = idata;          d->cur_command = idata;
425          d->atapi_cmd_in_progress = 0;          d->atapi_cmd_in_progress = 0;
# Line 518  void wdc_command(struct cpu *cpu, struct Line 535  void wdc_command(struct cpu *cpu, struct
535                  d->atapi_phase = PHASE_CMDOUT;                  d->atapi_phase = PHASE_CMDOUT;
536                  break;                  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:  */          /*  Unsupported commands, without warning:  */
546          case WDCC_SEC_SET_PASSWORD:          case WDCC_SEC_SET_PASSWORD:
547          case WDCC_SEC_UNLOCK:          case WDCC_SEC_UNLOCK:
# Line 541  void wdc_command(struct cpu *cpu, struct Line 565  void wdc_command(struct cpu *cpu, struct
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);
# Line 563  int dev_wdc_access(struct cpu *cpu, stru Line 590  int dev_wdc_access(struct cpu *cpu, stru
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);
   
                         odata += wdc_get_inbuf(d);  
594    
595                          if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {                          if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
596                                  if (len >= 2)                                  if (len >= 2)
# Line 584  int dev_wdc_access(struct cpu *cpu, stru Line 609  int dev_wdc_access(struct cpu *cpu, stru
609                          }                          }
610    
611                          if (d->data_debug) {                          if (d->data_debug) {
612                                  char *s = "0x%04llx ]\n";                                  char *s = "0x%04"PRIx64" ]\n";
613                                  if (len == 1)                                  if (len == 1)
614                                          s = "0x%02llx ]\n";                                          s = "0x%02"PRIx64" ]\n";
615                                  if (len == 4)                                  if (len == 4)
616                                          s = "0x%08llx ]\n";                                          s = "0x%08"PRIx64" ]\n";
617                                  if (len == 8)                                  if (len == 8)
618                                          s = "0x%016llx ]\n";                                          s = "0x%016"PRIx64" ]\n";
619                                  debug("[ wdc: read from DATA: ");                                  debug("[ wdc: read from DATA: ");
620                                  debug(s, (long long)odata);                                  debug(s, (uint64_t) odata);
621                          }                          }
622    
623                          if (d->atapi_cmd_in_progress) {                          if (d->atapi_cmd_in_progress) {
# Line 625  int dev_wdc_access(struct cpu *cpu, stru Line 650  int dev_wdc_access(struct cpu *cpu, stru
650                  } else {                  } else {
651                          int inbuf_len;                          int inbuf_len;
652                          if (d->data_debug) {                          if (d->data_debug) {
653                                  char *s = "0x%04llx ]\n";                                  char *s = "0x%04"PRIx64" ]\n";
654                                  if (len == 1)                                  if (len == 1)
655                                          s = "0x%02llx ]\n";                                          s = "0x%02"PRIx64" ]\n";
656                                  if (len == 4)                                  if (len == 4)
657                                          s = "0x%08llx ]\n";                                          s = "0x%08"PRIx64" ]\n";
658                                  if (len == 8)                                  if (len == 8)
659                                          s = "0x%016llx ]\n";                                          s = "0x%016"PRIx64" ]\n";
660                                  debug("[ wdc: write to DATA: ");                                  debug("[ wdc: write to DATA: ");
661                                  debug(s, (long long)idata);                                  debug(s, (uint64_t) idata);
662                          }                          }
663                          if (!d->write_in_progress &&                          if (!d->write_in_progress &&
664                              !d->atapi_cmd_in_progress) {                              !d->atapi_cmd_in_progress) {
# Line 745  int dev_wdc_access(struct cpu *cpu, stru Line 770  int dev_wdc_access(struct cpu *cpu, stru
770                              inbuf_len % 512 == 0) ) {                              inbuf_len % 512 == 0) ) {
771                                  int count = (d->write_in_progress ==                                  int count = (d->write_in_progress ==
772                                      WDCC_WRITEMULTI)? d->write_count : 1;                                      WDCC_WRITEMULTI)? d->write_count : 1;
773                                  unsigned char buf[512 * count];                                  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 768  int dev_wdc_access(struct cpu *cpu, stru Line 798  int dev_wdc_access(struct cpu *cpu, stru
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;
# Line 775  int dev_wdc_access(struct cpu *cpu, stru Line 807  int dev_wdc_access(struct cpu *cpu, stru
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 890  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    
925          if (cpu->machine->machine_type != MACHINE_HPCMIPS &&          if (cpu->machine->machine_type != MACHINE_HPCMIPS &&
926              cpu->machine->machine_type != MACHINE_EVBMIPS &&              cpu->machine->machine_type != MACHINE_EVBMIPS &&
927                cpu->machine->machine_type != MACHINE_ALGOR &&
928              cpu->machine->machine_type != MACHINE_BEBOX)              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 906  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 921  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;          d->data_debug = 1;
958            d->io_enabled = 1;
959    
960          d->inbuf = zeroed_alloc(WDC_INBUF_SIZE);          d->inbuf = zeroed_alloc(WDC_INBUF_SIZE);
961    
# Line 934  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 949  int devinit_wdc(struct devinit *devinit) Line 992  int devinit_wdc(struct devinit *devinit)
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, DM_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, DM_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              devinit->machine->machine_type != MACHINE_EVBMIPS)              devinit->machine->machine_type != MACHINE_EVBMIPS)
1000                  tick_shift += 1;                  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.20  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC 1.1.26