/[gxemul]/trunk/src/devices/dev_asc.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_asc.c

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

revision 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  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_asc.c,v 1.70 2005/03/23 08:45:49 debug Exp $   *  $Id: dev_asc.c,v 1.86 2007/06/15 18:44:19 debug Exp $
29   *   *
30   *  'asc' SCSI controller for some DECstation/DECsystem models, and   *  COMMENT: NCR53C9X "ASC" SCSI controller
31   *  for PICA-61.   *
32     *  This is the SCSI controller used in some DECstation/DECsystem models and
33     *  the PICA-61 machine.
34   *   *
35   *  Supposed to support SCSI-1 and SCSI-2. I've not yet found any docs   *  Supposed to support SCSI-1 and SCSI-2. I've not yet found any docs
36   *  on NCR53C9X, so I'll try to implement this device from LSI53CF92A docs   *  on NCR53C9X, so I'll try to implement this device from LSI53CF92A docs
# Line 50  Line 52 
52   *  TODO:  This module needs a clean-up, and some testing to see that   *  TODO:  This module needs a clean-up, and some testing to see that
53   *         it works will all OSes that might use it (NetBSD, OpenBSD,   *         it works will all OSes that might use it (NetBSD, OpenBSD,
54   *         Ultrix, Linux, Mach, OSF/1, Sprite, ...)   *         Ultrix, Linux, Mach, OSF/1, Sprite, ...)
55     *
56     *         Running Linux/DECstation 2.4.26 with no scsi disks attached causes
57     *         a warning message to be printed by Linux. (Whether this is a bug,
58     *         is is the way it works on real hardware, I don't know.)
59   */   */
60    
61  #include <stdio.h>  #include <stdio.h>
# Line 71  Line 77 
77  /*  #define ASC_FULL_REGISTER_ACCESS_DEBUG  */  /*  #define ASC_FULL_REGISTER_ACCESS_DEBUG  */
78  /*  static int quiet_mode = 0;  */  /*  static int quiet_mode = 0;  */
79    
80    #define ASC_TICK_SHIFT          15
81    
82  extern int quiet_mode;  extern int quiet_mode;
83    
84    
# Line 90  extern int quiet_mode; Line 98  extern int quiet_mode;
98  /*  The controller's SCSI id:  */  /*  The controller's SCSI id:  */
99  #define ASC_SCSI_ID             7  #define ASC_SCSI_ID             7
100    
101    #define ASC_DMA_SIZE            (128*1024)
102    
103  struct asc_data {  struct asc_data {
104          int             mode;          int             mode;
105    
106          void            *turbochannel;          void            *turbochannel;
107          int             irq_nr;          struct interrupt irq;
108          int             irq_caused_last_time;          int             irq_asserted;
109    
110          /*  Current state and transfer:  */          /*  Current state and transfer:  */
111          int             cur_state;          int             cur_state;
# Line 118  struct asc_data { Line 128  struct asc_data {
128    
129          /*  Built-in DMA memory (for DECstation 5000/200):  */          /*  Built-in DMA memory (for DECstation 5000/200):  */
130          uint32_t        dma_address_reg;          uint32_t        dma_address_reg;
131          unsigned char   dma_address_reg_memory[4096];          unsigned char   *dma_address_reg_memory;
132                                  /*  NOTE: full page, for bintrans  */          unsigned char   *dma;
         unsigned char   dma[128 * 1024];  
133    
134          void            *dma_controller_data;          void            *dma_controller_data;
135          size_t          (*dma_controller)(void *dma_controller_data,          size_t          (*dma_controller)(void *dma_controller_data,
# Line 146  static int dev_asc_select(struct cpu *cp Line 155  static int dev_asc_select(struct cpu *cp
155          int to_id, int dmaflag, int n_messagebytes);          int to_id, int dmaflag, int n_messagebytes);
156    
157    
158  /*  DEVICE_TICK(asc)
  *  dev_asc_tick():  
  *  
  *  This function is called "every now and then" from the CPU  
  *  main loop.  
  */  
 void dev_asc_tick(struct cpu *cpu, void *extra)  
159  {  {
160          struct asc_data *d = extra;          struct asc_data *d = extra;
161            int new_assert = d->reg_ro[NCR_STAT] & NCRSTAT_INT;
162    
163            if (new_assert && !d->irq_asserted)
164                    INTERRUPT_ASSERT(d->irq);
165    
166          if (d->reg_ro[NCR_STAT] & NCRSTAT_INT)          d->irq_asserted = new_assert;
                 cpu_interrupt(cpu, d->irq_nr);  
167  }  }
168    
169    
# Line 306  fatal("TODO..............\n"); Line 312  fatal("TODO..............\n");
312                                  fatal("no incoming DMA data?\n");                                  fatal("no incoming DMA data?\n");
313                                  res = 0;                                  res = 0;
314                          } else {                          } else {
315                                  int len = d->xferp->data_in_len;                                  size_t len = d->xferp->data_in_len;
316                                  int len2 = d->reg_wo[NCR_TCL] +                                  size_t len2 = d->reg_wo[NCR_TCL] +
317                                      d->reg_wo[NCR_TCM] * 256;                                      d->reg_wo[NCR_TCM] * 256;
318                                  if (len2 == 0)                                  if (len2 == 0)
319                                          len2 = 65536;                                          len2 = 65536;
# Line 319  fatal("TODO..............\n"); Line 325  fatal("TODO..............\n");
325    
326                                  /*  TODO: check len2 in a similar way?  */                                  /*  TODO: check len2 in a similar way?  */
327                                  if (len + (d->dma_address_reg &                                  if (len + (d->dma_address_reg &
328                                      ((sizeof(d->dma)-1))) > sizeof(d->dma))                                      (ASC_DMA_SIZE-1)) > ASC_DMA_SIZE)
329                                          len = sizeof(d->dma) -                                          len = ASC_DMA_SIZE -
330                                              (d->dma_address_reg &                                              (d->dma_address_reg &
331                                              ((sizeof(d->dma)-1)));                                              (ASC_DMA_SIZE-1));
332    
333                                  if (len2 > len) {                                  if (len2 > len) {
334                                          memset(d->dma + (d->dma_address_reg &                                          memset(d->dma + (d->dma_address_reg &
335                                              ((sizeof(d->dma)-1))), 0, len2);                                              (ASC_DMA_SIZE-1)), 0, len2);
336                                          len2 = len;                                          len2 = len;
337                                  }                                  }
338    
# Line 352  fatal("TODO..............\n"); Line 358  fatal("TODO..............\n");
358                                              len2, 1);                                              len2, 1);
359                                  else                                  else
360                                          memcpy(d->dma + (d->dma_address_reg &                                          memcpy(d->dma + (d->dma_address_reg &
361                                              ((sizeof(d->dma)-1))),                                              (ASC_DMA_SIZE-1)),
362                                              d->xferp->data_in, len2);                                              d->xferp->data_in, len2);
363    
364                                  if (d->xferp->data_in_len > len2) {                                  if (d->xferp->data_in_len > len2) {
# Line 369  if (d->dma_controller != NULL) Line 375  if (d->dma_controller != NULL)
375                                              (int)len, (int)len2);  */                                              (int)len, (int)len2);  */
376    
377                                          d->xferp->data_in_len -= len2;                                          d->xferp->data_in_len -= len2;
378                                          n = malloc(d->xferp->data_in_len);                                          CHECK_ALLOCATION(n =
379                                          if (n == NULL) {                                              malloc(d->xferp->data_in_len));
                                                 fprintf(stderr, "out of memory"  
                                                     " in dev_asc\n");  
                                                 exit(1);  
                                         }  
380                                          memcpy(n, d->xferp->data_in + len2,                                          memcpy(n, d->xferp->data_in + len2,
381                                              d->xferp->data_in_len);                                              d->xferp->data_in_len);
382                                          free(d->xferp->data_in);                                          free(d->xferp->data_in);
# Line 439  fatal("TODO.......asdgasin\n"); Line 441  fatal("TODO.......asdgasin\n");
441                                  else                                  else
442                                          memcpy(d->xferp->data_out,                                          memcpy(d->xferp->data_out,
443                                              d->dma + (d->dma_address_reg &                                              d->dma + (d->dma_address_reg &
444                                              ((sizeof(d->dma)-1))), len2);                                              (ASC_DMA_SIZE-1)), len2);
445                                  d->xferp->data_out_offset = len2;                                  d->xferp->data_out_offset = len2;
446                          } else {                          } else {
447                                  /*  Continuing a multi-transfer:  */                                  /*  Continuing a multi-transfer:  */
# Line 453  fatal("TODO.......asdgasin\n"); Line 455  fatal("TODO.......asdgasin\n");
455                                          memcpy(d->xferp->data_out +                                          memcpy(d->xferp->data_out +
456                                              d->xferp->data_out_offset,                                              d->xferp->data_out_offset,
457                                              d->dma + (d->dma_address_reg &                                              d->dma + (d->dma_address_reg &
458                                              ((sizeof(d->dma)-1))), len2);                                              (ASC_DMA_SIZE-1)), len2);
459                                  d->xferp->data_out_offset += len2;                                  d->xferp->data_out_offset += len2;
460                          }                          }
461    
# Line 504  fatal("TODO.......asdgasin\n"); Line 506  fatal("TODO.......asdgasin\n");
506                          }                          }
507    
508                          newlen = oldlen + d->n_bytes_in_fifo;                          newlen = oldlen + d->n_bytes_in_fifo;
509                          d->xferp->msg_out = realloc(d->xferp->msg_out, newlen);                          CHECK_ALLOCATION(d->xferp->msg_out =
510                                realloc(d->xferp->msg_out, newlen));
511                          d->xferp->msg_out_len = newlen;                          d->xferp->msg_out_len = newlen;
                         if (d->xferp->msg_out == NULL) {  
                                 fprintf(stderr, "out of memory realloc'ing "  
                                     "msg_out\n");  
                                 exit(1);  
                         }  
512    
513                          i = oldlen;                          i = oldlen;
514                          while (d->fifo_in != d->fifo_out) {                          while (d->fifo_in != d->fifo_out) {
# Line 563  fatal("TODO.......asdgasin\n"); Line 561  fatal("TODO.......asdgasin\n");
561    
562          /*  Redo the command if data was just sent using DATA_OUT:  */          /*  Redo the command if data was just sent using DATA_OUT:  */
563          if (d->cur_phase == PHASE_DATA_OUT) {          if (d->cur_phase == PHASE_DATA_OUT) {
564                  res = diskimage_scsicommand(cpu,                  res = diskimage_scsicommand(cpu, d->reg_wo[NCR_SELID] & 7,
565                      d->reg_wo[NCR_SELID] & 7, d->xferp);                      DISKIMAGE_SCSI, d->xferp);
566          }          }
567    
568          if (all_done) {          if (all_done) {
# Line 705  static int dev_asc_select(struct cpu *cp Line 703  static int dev_asc_select(struct cpu *cp
703    
704                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
705                          int ofs = d->dma_address_reg + i;                          int ofs = d->dma_address_reg + i;
706                          ch = d->dma[ofs & (sizeof(d->dma)-1)];                          ch = d->dma[ofs & (ASC_DMA_SIZE-1)];
707                          d->xferp->cmd[i] = ch;                          d->xferp->cmd[i] = ch;
708                          if (!quiet_mode)                          if (!quiet_mode)
709                                  debug("%02x ", ch);                                  debug("%02x ", ch);
# Line 720  static int dev_asc_select(struct cpu *cp Line 718  static int dev_asc_select(struct cpu *cp
718          /*          /*
719           *  Call the SCSI device to perform the command:           *  Call the SCSI device to perform the command:
720           */           */
721          ok = diskimage_scsicommand(cpu, to_id, d->xferp);          ok = diskimage_scsicommand(cpu, to_id, DISKIMAGE_SCSI, d->xferp);
722    
723    
724          /*  Cause an interrupt:  */          /*  Cause an interrupt:  */
# Line 745  static int dev_asc_select(struct cpu *cp Line 743  static int dev_asc_select(struct cpu *cp
743  }  }
744    
745    
746  /*  DEVICE_ACCESS(asc_address_reg)
  *  dev_asc_address_reg_access():  
  */  
 int dev_asc_address_reg_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
747  {  {
748          struct asc_data *d = extra;          struct asc_data *d = extra;
749    
# Line 767  int dev_asc_address_reg_access(struct cp Line 760  int dev_asc_address_reg_access(struct cp
760  }  }
761    
762    
763  /*  DEVICE_ACCESS(asc_dma)
  *  dev_asc_dma_access():  
  */  
 int dev_asc_dma_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
764  {  {
765          struct asc_data *d = extra;          struct asc_data *d = extra;
766    
# Line 810  int dev_asc_dma_access(struct cpu *cpu, Line 798  int dev_asc_dma_access(struct cpu *cpu,
798  }  }
799    
800    
801  /*  DEVICE_ACCESS(asc)
  *  dev_asc_access():  
  */  
 int dev_asc_access(struct cpu *cpu, struct memory *mem,  
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
802  {  {
803          int regnr;          int regnr;
804          struct asc_data *d = extra;          struct asc_data *d = extra;
# Line 823  int dev_asc_access(struct cpu *cpu, stru Line 806  int dev_asc_access(struct cpu *cpu, stru
806          int n_messagebytes = 0;          int n_messagebytes = 0;
807          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
808    
809            if (writeflag == MEM_WRITE)
810          idata = memory_readmax64(cpu, data, len);                  idata = memory_readmax64(cpu, data, len);
811    
812  #if 0  #if 0
813          /*  Debug stuff useful when trying to make dev_asc compatible          /*  Debug stuff useful when trying to make dev_asc compatible
# Line 1072  int dev_asc_access(struct cpu *cpu, stru Line 1055  int dev_asc_access(struct cpu *cpu, stru
1055                          /*  TODO: not just disk, but some generic                          /*  TODO: not just disk, but some generic
1056                              SCSI device  */                              SCSI device  */
1057                          target_exists = diskimage_exist(cpu->machine,                          target_exists = diskimage_exist(cpu->machine,
1058                              d->reg_wo[NCR_SELID] & 7);                              d->reg_wo[NCR_SELID] & 7, DISKIMAGE_SCSI);
1059    
1060                          if (target_exists) {                          if (target_exists) {
1061                                  /*                                  /*
# Line 1211  break; Line 1194  break;
1194                          d->reg_ro[NCR_STAT] = PHASE_COMMAND;                          d->reg_ro[NCR_STAT] = PHASE_COMMAND;
1195                  }                  }
1196    
1197                  cpu_interrupt_ack(cpu, d->irq_nr);                  INTERRUPT_DEASSERT(d->irq);
1198                    d->irq_asserted = 0;
1199          }          }
1200    
1201          if (regnr == NCR_CFG1) {          if (regnr == NCR_CFG1) {
# Line 1241  break; Line 1225  break;
1225   *  Register an 'asc' device.   *  Register an 'asc' device.
1226   */   */
1227  void dev_asc_init(struct machine *machine, struct memory *mem,  void dev_asc_init(struct machine *machine, struct memory *mem,
1228          uint64_t baseaddr, int irq_nr, void *turbochannel,          uint64_t baseaddr, char *irq_path, void *turbochannel, int mode,
         int mode,  
1229          size_t (*dma_controller)(void *dma_controller_data,          size_t (*dma_controller)(void *dma_controller_data,
1230                  unsigned char *data, size_t len, int writeflag),                  unsigned char *data, size_t len, int writeflag),
1231          void *dma_controller_data)          void *dma_controller_data)
1232  {  {
1233          struct asc_data *d;          struct asc_data *d;
1234    
1235          d = malloc(sizeof(struct asc_data));          CHECK_ALLOCATION(d = malloc(sizeof(struct asc_data)));
         if (d == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
1236          memset(d, 0, sizeof(struct asc_data));          memset(d, 0, sizeof(struct asc_data));
1237          d->irq_nr       = irq_nr;  
1238            INTERRUPT_CONNECT(irq_path, d->irq);
1239          d->turbochannel = turbochannel;          d->turbochannel = turbochannel;
1240          d->mode         = mode;          d->mode         = mode;
1241    
1242          d->reg_ro[NCR_CFG3] = NCRF9XCFG3_CDB;          d->reg_ro[NCR_CFG3] = NCRF9XCFG3_CDB;
1243    
1244            CHECK_ALLOCATION(d->dma_address_reg_memory =
1245                malloc(machine->arch_pagesize));
1246            memset(d->dma_address_reg_memory, 0, machine->arch_pagesize);
1247    
1248            CHECK_ALLOCATION(d->dma = malloc(ASC_DMA_SIZE));
1249            memset(d->dma, 0, ASC_DMA_SIZE);
1250    
1251          d->dma_controller      = dma_controller;          d->dma_controller      = dma_controller;
1252          d->dma_controller_data = dma_controller_data;          d->dma_controller_data = dma_controller_data;
1253    
1254          memory_device_register(mem, "asc", baseaddr,          memory_device_register(mem, "asc", baseaddr,
1255              mode == DEV_ASC_PICA?              mode == DEV_ASC_PICA? DEV_ASC_PICA_LENGTH : DEV_ASC_DEC_LENGTH,
1256                  DEV_ASC_PICA_LENGTH : DEV_ASC_DEC_LENGTH,              dev_asc_access, d, DM_DEFAULT, NULL);
             dev_asc_access, d, MEM_DEFAULT, NULL);  
1257    
1258          if (mode == DEV_ASC_DEC) {          if (mode == DEV_ASC_DEC) {
1259                  memory_device_register(mem, "asc_dma_address_reg",                  memory_device_register(mem, "asc_dma_address_reg",
1260                      baseaddr + 0x40000, 4096, dev_asc_address_reg_access, d,                      baseaddr + 0x40000, 4096, dev_asc_address_reg_access, d,
1261                      MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK,                      DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK,
1262                      d->dma_address_reg_memory);                      (unsigned char *)&d->dma_address_reg_memory[0]);
1263                  memory_device_register(mem, "asc_dma", baseaddr + 0x80000,                  memory_device_register(mem, "asc_dma", baseaddr + 0x80000,
1264                      128*1024, dev_asc_dma_access, d,                      ASC_DMA_SIZE, dev_asc_dma_access, d,
1265                      MEM_BINTRANS_OK | MEM_BINTRANS_WRITE_OK, d->dma);                      DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK, d->dma);
1266          }          }
1267    
1268          machine_add_tickfunction(machine, dev_asc_tick, d, 15);          machine_add_tickfunction(machine, dev_asc_tick, d, ASC_TICK_SHIFT);
1269  }  }
1270    

Legend:
Removed from v.4  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26