/[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 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: dev_wdc.c,v 1.39 2005/09/27 23:55:44 debug Exp $   *  $Id: dev_wdc.c,v 1.44 2005/10/26 14:37:05 debug Exp $
29   *   *
30   *  Standard "wdc" IDE controller.   *  Standard "wdc" IDE controller.
31   */   */
# Line 34  Line 34 
34  #include <stdlib.h>  #include <stdlib.h>
35  #include <string.h>  #include <string.h>
36    
 #include "console.h"  
37  #include "cpu.h"  #include "cpu.h"
38  #include "device.h"  #include "device.h"
39  #include "diskimage.h"  #include "diskimage.h"
# Line 46  Line 45 
45    
46  #define DEV_WDC_LENGTH          8  #define DEV_WDC_LENGTH          8
47  #define WDC_TICK_SHIFT          14  #define WDC_TICK_SHIFT          14
48  #define WDC_INBUF_SIZE          (512*257)  #define WDC_MAX_SECTORS         512
49    #define WDC_INBUF_SIZE          (512*(WDC_MAX_SECTORS+1))
50    
51  /*  /*
52   *  INT_DELAY=2 to be safe, 1 is faster but maybe buggy. 0 is fastest.   *  INT_DELAY: This is an old hack which only exists because (some versions of)
53     *  NetBSD for hpcmips have interrupt problems. These problems are probably not
54     *  specific to GXemul, but are also triggered on real hardware.
55   *   *
56   *  The only reason for this delay to exist is because (some versions of)   *  See the following URL for more info:
57   *  NetBSD for hpcmips have interrupt problems. These problems are not only   *  http://mail-index.netbsd.org/port-hpcmips/2004/12/30/0003.html
  *  triggered inside the emulator, but also on real hardware. Using the  
  *  delay is an ugly (but working) work-around.  
58   */   */
59  #define INT_DELAY               1  #define INT_DELAY               1
60    
# Line 124  static void wdc_addtoinbuf(struct wdc_da Line 124  static void wdc_addtoinbuf(struct wdc_da
124    
125          d->inbuf_head = (d->inbuf_head + 1) % WDC_INBUF_SIZE;          d->inbuf_head = (d->inbuf_head + 1) % WDC_INBUF_SIZE;
126          if (d->inbuf_head == d->inbuf_tail)          if (d->inbuf_head == d->inbuf_tail)
127                  fatal("[ wdc_addtoinbuf(): WARNING! wdc inbuf overrun ]\n");                  fatal("[ wdc_addtoinbuf(): WARNING! wdc inbuf overrun!"
128                        " Increase WDC_MAX_SECTORS. ]\n");
129  }  }
130    
131    
# Line 224  static void wdc_initialize_identify_stru Line 225  static void wdc_initialize_identify_stru
225   */   */
226  void wdc__read(struct cpu *cpu, struct wdc_data *d)  void wdc__read(struct cpu *cpu, struct wdc_data *d)
227  {  {
228          unsigned char buf[512];          const int max_sectors_per_chunk = 64;
229            unsigned char buf[512 * max_sectors_per_chunk];
230          int i, cyl = d->cyl_hi * 256+ d->cyl_lo;          int i, cyl = d->cyl_hi * 256+ d->cyl_lo;
231          int count = d->seccnt? d->seccnt : 256;          int count = d->seccnt? d->seccnt : 256;
232          uint64_t offset = 512 * (d->sector - 1          uint64_t offset = 512 * (d->sector - 1
# Line 240  void wdc__read(struct cpu *cpu, struct w Line 242  void wdc__read(struct cpu *cpu, struct w
242  #endif  #endif
243    
244          while (count > 0) {          while (count > 0) {
245                  diskimage_access(cpu->machine, d->drive + d->base_drive,                  int to_read = count > max_sectors_per_chunk?
246                      DISKIMAGE_IDE, 0, offset, buf, 512);                      max_sectors_per_chunk : count;
247                  /*  TODO: result code  */  
248                  for (i=0; i<512; i++)                  /*  TODO: result code from the read?  */
249                          wdc_addtoinbuf(d, buf[i]);  
250                  offset += 512;                  if (d->inbuf_head + 512 * to_read <= WDC_INBUF_SIZE) {
251                  count --;                          diskimage_access(cpu->machine, d->drive + d->base_drive,
252                                DISKIMAGE_IDE, 0, offset,
253                                d->inbuf + d->inbuf_head, 512 * to_read);
254                            d->inbuf_head += 512 * to_read;
255                            if (d->inbuf_head == WDC_INBUF_SIZE)
256                                    d->inbuf_head = 0;
257                    } else {
258                            diskimage_access(cpu->machine, d->drive + d->base_drive,
259                                DISKIMAGE_IDE, 0, offset, buf, 512 * to_read);
260                            for (i=0; i<512 * to_read; i++)
261                                    wdc_addtoinbuf(d, buf[i]);
262                    }
263    
264                    offset += 512 * to_read;
265                    count -= to_read;
266          }          }
267    
268          d->delayed_interrupt = INT_DELAY;          d->delayed_interrupt = INT_DELAY;
# Line 317  int dev_wdc_altstatus_access(struct cpu Line 333  int dev_wdc_altstatus_access(struct cpu
333          struct wdc_data *d = extra;          struct wdc_data *d = extra;
334          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
335    
336          idata = memory_readmax64(cpu, data, len);          idata = data[0];
337    
338          /*  Same as the normal status byte?  */          /*  Same as the normal status byte?  */
339          odata = status_byte(d, cpu);          odata = status_byte(d, cpu);
# Line 330  int dev_wdc_altstatus_access(struct cpu Line 346  int dev_wdc_altstatus_access(struct cpu
346                      (int)idata);                      (int)idata);
347    
348          if (writeflag == MEM_READ)          if (writeflag == MEM_READ)
349                  memory_writemax64(cpu, data, len, odata);                  data[0] = odata;
350    
351          return 1;          return 1;
352  }  }
# Line 347  int dev_wdc_access(struct cpu *cpu, stru Line 363  int dev_wdc_access(struct cpu *cpu, stru
363          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
364          int i;          int i;
365    
366          idata = memory_readmax64(cpu, data, len);          if (writeflag == MEM_WRITE) {
367                    if (relative_addr == wd_data)
368                            idata = memory_readmax64(cpu, data, len);
369                    else
370                            idata = data[0];
371            }
372    
373          switch (relative_addr) {          switch (relative_addr) {
374    
375          case wd_data:   /*  0: data  */          case wd_data:   /*  0: data  */
376                  if (writeflag==MEM_READ) {                  if (writeflag == MEM_READ) {
377                          odata = 0;                          odata = 0;
378    
379                          /*  TODO: This is hardcoded for little-endian?  */                          /*  TODO: This is hardcoded for little-endian?  */
# Line 368  int dev_wdc_access(struct cpu *cpu, stru Line 389  int dev_wdc_access(struct cpu *cpu, stru
389                          if (d->data_debug)                          if (d->data_debug)
390                                  debug("[ wdc: read from DATA: 0x%04x ]\n",                                  debug("[ wdc: read from DATA: 0x%04x ]\n",
391                                      (int)odata);                                      (int)odata);
392    #if 0
393                          if (d->inbuf_tail != d->inbuf_head)                          if (d->inbuf_tail != d->inbuf_head)
394    #else
395                            if (d->inbuf_tail != d->inbuf_head &&
396                                ((d->inbuf_tail - d->inbuf_head) % 512) == 0)
397    #endif
398                                  d->delayed_interrupt = INT_DELAY;                                  d->delayed_interrupt = INT_DELAY;
399                  } else {                  } else {
400                          int inbuf_len;                          int inbuf_len;
# Line 405  int dev_wdc_access(struct cpu *cpu, stru Line 431  int dev_wdc_access(struct cpu *cpu, stru
431                          if ((inbuf_len % 512) == 0) {                          if ((inbuf_len % 512) == 0) {
432  #endif  #endif
433                                  int count = 1;  /*  d->write_count;  */                                  int count = 1;  /*  d->write_count;  */
434                                  unsigned char *buf = malloc(count * 512);                                  unsigned char buf[512 * count];
435                                  if (buf == NULL) {                                  unsigned char *b = buf;
                                         fprintf(stderr, "out of memory\n");  
                                         exit(1);  
                                 }  
436    
437                                  for (i=0; i<512 * count; i++)                                  if (d->inbuf_tail+512*count <= WDC_INBUF_SIZE) {
438                                          buf[i] = wdc_get_inbuf(d);                                          b = d->inbuf + d->inbuf_tail;
439                                            d->inbuf_tail = (d->inbuf_tail + 512
440                                                * count) % WDC_INBUF_SIZE;
441                                    } else {
442                                            for (i=0; i<512 * count; i++)
443                                                    buf[i] = wdc_get_inbuf(d);
444                                    }
445    
446                                  diskimage_access(cpu->machine,                                  diskimage_access(cpu->machine,
447                                      d->drive + d->base_drive, DISKIMAGE_IDE, 1,                                      d->drive + d->base_drive, DISKIMAGE_IDE, 1,
448                                      d->write_offset, buf, 512 * count);                                      d->write_offset, b, 512 * count);
                                 free(buf);  
449    
450                                  d->write_count --;                                  d->write_count --;
451                                  d->write_offset += 512;                                  d->write_offset += 512;
# Line 627  int dev_wdc_access(struct cpu *cpu, stru Line 655  int dev_wdc_access(struct cpu *cpu, stru
655                              (int)relative_addr, (int)idata);                              (int)relative_addr, (int)idata);
656          }          }
657    
658          if (writeflag == MEM_READ)          if (cpu->machine->machine_type != MACHINE_HPCMIPS)
659                  memory_writemax64(cpu, data, len, odata);                  dev_wdc_tick(cpu, extra);
660    
661            if (writeflag == MEM_READ) {
662                    if (relative_addr == wd_data)
663                            memory_writemax64(cpu, data, len, odata);
664                    else
665                            data[0] = odata;
666            }
667    
668          return 1;          return 1;
669  }  }
# Line 641  int devinit_wdc(struct devinit *devinit) Line 676  int devinit_wdc(struct devinit *devinit)
676  {  {
677          struct wdc_data *d;          struct wdc_data *d;
678          uint64_t alt_status_addr;          uint64_t alt_status_addr;
679          int i;          int i, tick_shift = WDC_TICK_SHIFT;
680    
681          d = malloc(sizeof(struct wdc_data));          d = malloc(sizeof(struct wdc_data));
682          if (d == NULL) {          if (d == NULL) {
# Line 676  int devinit_wdc(struct devinit *devinit) Line 711  int devinit_wdc(struct devinit *devinit)
711              devinit->addr, DEV_WDC_LENGTH, dev_wdc_access, d, MEM_DEFAULT,              devinit->addr, DEV_WDC_LENGTH, dev_wdc_access, d, MEM_DEFAULT,
712              NULL);              NULL);
713    
714            if (devinit->machine->machine_type != MACHINE_HPCMIPS)
715                    tick_shift += 2;
716    
717          machine_add_tickfunction(devinit->machine, dev_wdc_tick,          machine_add_tickfunction(devinit->machine, dev_wdc_tick,
718              d, WDC_TICK_SHIFT);              d, tick_shift);
719    
720          return 1;          return 1;
721  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26