Annotation of previous/src/esp.c, revision 1.1.1.1

1.1       root        1: /* Emulation of NCR53C90(A)
                      2:  Includes informations from QEMU-NeXT
                      3:  */
                      4: 
                      5: #include "ioMem.h"
                      6: #include "ioMemTables.h"
                      7: #include "m68000.h"
                      8: #include "configuration.h"
                      9: #include "esp.h"
                     10: #include "sysReg.h"
                     11: #include "dma.h"
                     12: #include "scsi.h"
                     13: 
                     14: #define LOG_SCSI_LEVEL LOG_DEBUG
                     15: 
                     16: 
                     17: #define IO_SEG_MASK    0x1FFFF
                     18: 
                     19: typedef enum {
                     20:     DISCONNECTED,
                     21:     RESELECTABLE,
                     22:     SELECTING,
                     23:     INITIATOR,
                     24:     DISABLINGSEL,
                     25:     COMPLETING,
                     26:     DMAING,
                     27:     ACCEPTINGMSG,
                     28:     SENDINGMSG,
                     29:     PADDING,
                     30:     GETTINGMSG,
                     31:     GETTINGLUN,
                     32:     IGNOREILLCMD
                     33: } SCSI_STATE;
                     34: 
                     35: SCSI_STATE state;
                     36: 
                     37: /* SCSI DMA Command/Status Registers */
                     38: Uint8 csr_value0;
                     39: Uint8 csr_value1;
                     40: 
                     41: /* ESP Registers */
                     42: Uint8 readtranscountl;
                     43: Uint8 readtranscounth;
                     44: Uint8 writetranscountl;
                     45: Uint8 writetranscounth;
                     46: Uint8 fifo;
                     47: Uint8 command;
                     48: Uint8 status;
                     49: Uint8 selectbusid;
                     50: Uint8 intstatus;
                     51: Uint8 selecttimeout;
                     52: Uint8 seqstep;
                     53: Uint8 syncperiod;
                     54: Uint8 fifoflags;
                     55: Uint8 syncoffset;
                     56: Uint8 configuration;
                     57: Uint8 clockconv;
                     58: Uint8 esptest;
                     59: 
                     60: /* ESP Status Variables */
                     61: Uint8 irq_status;
                     62: Uint8 mode_dma;
                     63: 
                     64: /* ESP FIFO */
                     65: #define ESP_FIFO_SIZE 16
                     66: Uint8 esp_fifo[ESP_FIFO_SIZE];
                     67: Uint8 fifo_read_ptr;
                     68: Uint8 fifo_write_ptr;
                     69: 
                     70: /* Command buffer */
                     71: #define SCSI_CMD_BUF_SIZE 16
                     72: Uint8 commandbuf[SCSI_CMD_BUF_SIZE];
                     73: int command_len;
                     74: 
                     75: 
                     76: /* Experimental */
                     77: 
                     78: //Uint32 dma;
                     79: Uint32 do_cmdvar;
                     80: Uint32 dma_counter;
                     81: Uint32 data_len;
                     82: Uint32 dma_left;
                     83: Uint32 cmdlen;
                     84: Uint32 async_len;
                     85: Uint8 *async_buf;
                     86: int dma_enabled = 1;
                     87: void (*dma_cb);
                     88: 
                     89: static bool no_target=false;
                     90: static int bus_id_command=0;
                     91: 
                     92: 
                     93: void SCSI_CSR0_Read(void) {
                     94:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = csr_value0;
                     95:        Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                     96: }
                     97: 
                     98: void SCSI_CSR0_Write(void) {
                     99:     Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA control write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    100:     csr_value0 = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    101:         
                    102:     if ((csr_value0 & 0x04) == 0x04) {
                    103:         Log_Printf(LOG_SCSI_LEVEL, "flush FIFO\n");
                    104:     }
                    105:     if ((csr_value0 & 0x01) == 0x01) {
                    106:         Log_Printf(LOG_SCSI_LEVEL, "scsi chip is WD33C92\n");
                    107:     } else {
                    108:         Log_Printf(LOG_SCSI_LEVEL, "scsi chip is NCR53C90\n");
                    109:     }
                    110:     if ((csr_value0 & 0x02) == 0x02) {
                    111:         Log_Printf(LOG_SCSI_LEVEL, "reset scsi chip\n");
                    112:         esp_reset_hard();
                    113:     }
                    114:     if ((csr_value0 & 0x08) == 0x08) {
                    115:         Log_Printf(LOG_SCSI_LEVEL, "dma from scsi to mem\n");
                    116:     }
                    117:     if ((csr_value0 & 0x10) == 0x10) {
                    118:         // set_interrupt(INT_SCSI_DMA, SET_INT);
                    119:         // esp_raise_irq(); 
                    120:         Log_Printf(LOG_SCSI_LEVEL, "mode DMA\n");
                    121:     }else{
                    122:         // set_interrupt(INT_SCSI_DMA, RELEASE_INT);
                    123:         //esp_lower_irq();
                    124:         Log_Printf(LOG_SCSI_LEVEL, "mode PIO\n");
                    125:     }
                    126:     if ((csr_value0 & 0x20) == 0x20) {
                    127:         Log_Printf(LOG_SCSI_LEVEL, "interrupt enable");
                    128:     }
                    129:     switch (csr_value0 & 0xC0) {
                    130:         case 0x00:
                    131:             Log_Printf(LOG_SCSI_LEVEL, "10 MHz clock\n");
                    132:             break;
                    133:         case 0x40:
                    134:             Log_Printf(LOG_SCSI_LEVEL, "12.5 MHz clock\n");
                    135:             break;
                    136:         case 0xC0:
                    137:             Log_Printf(LOG_SCSI_LEVEL, "16.6 MHz clock\n");
                    138:             break;
                    139:         case 0x80:
                    140:             Log_Printf(LOG_SCSI_LEVEL, "20 MHz clock\n");
                    141:             break;
                    142:         default:
                    143:             break;
                    144:     }
                    145: }
                    146: 
                    147: void SCSI_CSR1_Read(void) {
                    148:     
                    149:     /*
                    150:      * dma fifo status register
                    151:      */
                    152: #define        S5RDMAS_STATE           0xc0    /* DMA/SCSI bank state */
                    153: #define        S5RDMAS_D0S0            0x00    /* DMA rdy for bank 0, SCSI in bank 0 */
                    154: #define        S5RDMAS_D0S1            0x40    /* DMA req for bank 0, SCSI in bank 1 */
                    155: #define        S5RDMAS_D1S1            0x80    /* DMA rdy for bank 1, SCSI in bank 1 */
                    156: #define        S5RDMAS_D1S0            0xc0    /* DMA req for bank 1, SCSI in bank 0 */
                    157: #define        S5RDMAS_OUTFIFOMASK     0x38    /* output fifo byte (INVERTED) */
                    158: #define        S5RDMAS_INFIFOMASK      0x07    /* input fifo byte (INVERTED) */
                    159:     
                    160: #define        S5RDMA_FIFOALIGNMENT    4       /* mass storage chip buffer size */
                    161: 
                    162:     
                    163:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x80;
                    164:        Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA FIFO status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    165: }
                    166: 
                    167: void SCSI_CSR1_Write(void) {
                    168:        Log_Printf(LOG_SCSI_LEVEL,"SCSI DMA FIFO status write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    169:     csr_value1 = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    170: }
                    171: 
                    172: 
                    173: /* ESP Registers */
                    174: 
                    175: void SCSI_TransCountL_Read(void) { // 0x02014000
                    176:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=readtranscountl;
                    177:        Log_Printf(LOG_SCSI_LEVEL,"ESP TransCountL read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    178: }
                    179: 
                    180: void SCSI_TransCountL_Write(void) {
                    181:     writetranscountl=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    182:        Log_Printf(LOG_SCSI_LEVEL,"ESP TransCountL write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    183: }
                    184: 
                    185: void SCSI_TransCountH_Read(void) { // 0x02014001
                    186:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=readtranscounth;
                    187:        Log_Printf(LOG_SCSI_LEVEL,"ESP TransCoundH read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    188: }
                    189: 
                    190: void SCSI_TransCountH_Write(void) {
                    191:     writetranscounth=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    192:        Log_Printf(LOG_SCSI_LEVEL,"ESP TransCountH write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    193: }
                    194: 
                    195: void SCSI_FIFO_Read(void) { // 0x02014002
                    196:     if ((fifo_write_ptr - fifo_read_ptr) > 0) {
                    197:         IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = esp_fifo[fifo_read_ptr];
                    198:         Log_Printf(LOG_SCSI_LEVEL,"ESP FIFO read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    199:         Log_Printf(LOG_WARN,"ESP FIFO Read, size = %i, val=%02x", fifo_write_ptr - fifo_read_ptr, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
                    200:         fifo_read_ptr++;
                    201:         fifoflags = fifoflags - 1;
                    202: //        esp_raise_irq();
                    203:     } else {
                    204:         IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
                    205:         Log_Printf(LOG_WARN, "ESP FIFO is empty!\n");
                    206:     } 
                    207: }
                    208: 
                    209: void SCSI_FIFO_Write(void) {
                    210:     esp_fifo[fifo_write_ptr] = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    211:     fifo_write_ptr++;
                    212:     fifoflags = fifoflags + 1;
                    213:     Log_Printf(LOG_SCSI_LEVEL,"ESP FIFO write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    214:     
                    215:     if (fifo_write_ptr > (ESP_FIFO_SIZE - 1)) {
                    216:         Log_Printf(LOG_SCSI_LEVEL, "ESP FIFO overflow! Resetting FIFO!\n");
                    217:         esp_flush_fifo();
                    218:     }
                    219:     Log_Printf(LOG_SCSI_LEVEL,"ESP FIFO size = %i", fifo_write_ptr - fifo_read_ptr);
                    220: }
                    221: 
                    222: void SCSI_Command_Read(void) { // 0x02014003
                    223:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=command;
                    224:        Log_Printf(LOG_SCSI_LEVEL,"ESP Command read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    225: }
                    226: 
                    227: void SCSI_Command_Write(void) {
                    228:     command=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    229:        Log_Printf(LOG_SCSI_LEVEL,"ESP Command write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    230:     
                    231:     if (command & CMD_DMA) {
                    232:         readtranscountl = writetranscountl;
                    233:         readtranscounth = writetranscounth;
                    234:         status &= ~STAT_TC;
                    235:         mode_dma = 1;
                    236:     } else {
                    237:         mode_dma = 0;
                    238:     }
                    239:     
                    240:     if ((command & CMD_CMD) != CMD_NOP)
                    241:        status = (status&STAT_MASK)|STAT_CD;
                    242:     
                    243:     switch (command & CMD_CMD) {
                    244:             /* Miscellaneous */
                    245:         case CMD_NOP:
                    246:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: NOP\n");
                    247:            // status = (status&STAT_MASK)|STAT_ST;
                    248:             break;
                    249:         case CMD_FLUSH:
                    250:             Log_Printf(LOG_SCSI_LEVEL,"ESP Command: flush FIFO\n");
                    251:             esp_flush_fifo();
                    252:            status = (status&STAT_MASK)|STAT_ST;
                    253:             break;
                    254:         case CMD_RESET:
                    255:             Log_Printf(LOG_SCSI_LEVEL,"ESP Command: reset chip\n");
                    256:             esp_reset_hard();
                    257:             break;
                    258:         case CMD_BUSRESET:
                    259:             //Reset all Devices on SCSI bus
                    260:             Log_Printf(LOG_WARN, "ESP Command: reset SCSI bus\n");
                    261:             esp_reset_soft();
                    262:             if (!(configuration & CFG1_RESREPT)) {
                    263:                 intstatus = INTR_RST;
                    264:                 status = (status&STAT_MASK)|STAT_MI;
                    265:                seqstep = 0;
                    266:                 Log_Printf(LOG_SCSI_LEVEL,"Bus Reset raising IRQ configuration=%x\n",configuration);
                    267:                 //esp_raise_irq(); // temporary disabled for experiment! moved to read config reg.
                    268:             } else 
                    269:                 Log_Printf(LOG_SCSI_LEVEL,"Bus Reset not interrupting configuration=%x\n",configuration);
                    270:             break;
                    271:             /* Disconnected */
                    272:         case CMD_SEL:
                    273:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: select without ATN sequence\n");
                    274:            //abort();
                    275:             handle_satn(); // enabled for experiment!
                    276:             break;
                    277:         case CMD_SELATN:
                    278:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: select with ATN sequence\n");
                    279:             handle_satn();
                    280:             break;
                    281:         case CMD_SELATNS:
                    282:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: select with ATN and stop sequence\n");
                    283:            abort();
                    284:             break;
                    285:         case CMD_ENSEL:
                    286:             Log_Printf(LOG_WARN, "ESP Command: enable selection/reselection no_target=%x intstatus=%x status=%x seqstep=%x",
                    287:                        no_target,intstatus,status,seqstep);
                    288:             if (no_target) {
                    289:                 Log_Printf(LOG_SCSI_LEVEL, "ESP retry timeout");
                    290:                 intstatus = INTR_RESEL;
                    291:                seqstep = SEQ_SELTIMEOUT;
                    292:             } else {
                    293:                 Log_Printf(LOG_WARN, "Reselect: target %i, lun %i\n", SCSIcommand.target, SCSIcommand.lun);
                    294:                 status = (status&STAT_MASK)|STAT_MI;
                    295:                 intstatus = INTR_RESEL|INTR_FC;
                    296:                 esp_fifo[0] = (1<<SCSIcommand.target); // target bit
                    297:                 esp_fifo[1] = 0x80|(SCSIcommand.lun&0x07); // identify message (identifymask|(lun&lun_mask))
                    298:                 fifoflags = 2;
                    299:                 fifo_write_ptr = 2;
                    300:                 fifo_read_ptr = 0;
                    301: //                esp_raise_irq();
                    302:             }
                    303:             break;
                    304:         case CMD_DISSEL:
                    305:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: disable selection/reselection\n");
                    306:             intstatus = INTR_FC;
                    307:             esp_raise_irq();
                    308:             break;
                    309:             /* Initiator */
                    310:         case CMD_TI:
                    311:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: transfer information\n");
                    312:             handle_ti();
                    313:            esp_raise_irq();
                    314:             break;
                    315:         case CMD_ICCS:
                    316:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: initiator command complete sequence\n");
                    317:             write_response();
                    318:             intstatus = INTR_FC;
                    319:             status = (status&STAT_MASK)|STAT_MI;
                    320:             esp_raise_irq();
                    321:             break;
                    322:         case CMD_MSGACC:
                    323:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: message accepted\n");
                    324:             status = (status&STAT_MASK)|STAT_ST;          
                    325:             intstatus = INTR_BS;
                    326:             seqstep = SEQ_0;
                    327:             fifoflags = 0x00;
                    328:             esp_raise_irq();
                    329:             break;            
                    330:         case CMD_PAD:
                    331:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: transfer pad\n");
                    332:             status = STAT_TC | STAT_DI;
                    333:             intstatus = INTR_FC;
                    334:             seqstep = SEQ_0;
                    335:             esp_raise_irq();
                    336:             break;
                    337:         case CMD_SATN:
                    338:             Log_Printf(LOG_SCSI_LEVEL, "ESP Command: set ATN\n");
                    339:             break;
                    340:             /* Target */
                    341:         case CMD_SEMSG:
                    342:         case CMD_SESTAT:
                    343:         case CMD_SEDAT:
                    344:         case CMD_DISSEQ:
                    345:         case CMD_TERMSEQ:
                    346:         case CMD_TCCS:
                    347:         case CMD_RMSGSEQ:
                    348:         case CMD_RCOMM:
                    349:         case CMD_RDATA:
                    350:         case CMD_RCSEQ:
                    351: 
                    352:             status = (status&STAT_MASK)|STAT_ST;          
                    353:             intstatus = INTR_ILL;
                    354:             seqstep = SEQ_0;
                    355:             fifoflags = 0x00;
                    356:             esp_raise_irq();
                    357:             Log_Printf(LOG_WARN, "ESP Command: Target commands not supported!\n");
                    358:             break;
                    359:         case CMD_DIS:
                    360: 
                    361: 
                    362:             Log_Printf(LOG_WARN, "ESP Command: DISCONNECT !\n");
                    363:             status = (status&STAT_MASK)|STAT_ST;          
                    364:             intstatus = INTR_DC; 
                    365:             seqstep = SEQ_0;
                    366:             break;
                    367: 
                    368:             
                    369:         default:
                    370:             Log_Printf(LOG_WARN, "ESP Command: Illegal command!\n");
                    371:             intstatus |= INTR_ILL;
                    372:             break;
                    373:     }
                    374: }
                    375: 
                    376: void SCSI_Status_Read(void) { // 0x02014004
                    377:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=status;
                    378:        Log_Printf(LOG_SCSI_LEVEL,"ESP Status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    379: }
                    380: 
                    381: void SCSI_SelectBusID_Write(void) {
                    382:     selectbusid=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    383:        Log_Printf(LOG_SCSI_LEVEL,"ESP SelectBusID write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    384:        no_target=false;
                    385: }
                    386: 
                    387: void SCSI_IntStatus_Read(void) { // 0x02014005
                    388:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=intstatus;
                    389:     Log_Printf(LOG_SCSI_LEVEL,"ESP IntStatus read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    390:     
                    391:     if (irq_status == 1) {
                    392:             intstatus = 0x00;
                    393:             status &= ~(STAT_VGC | STAT_PE | STAT_GE );
                    394:             seqstep = SEQ_0;
                    395:             esp_lower_irq();
                    396:     }
                    397: }
                    398: 
                    399: void SCSI_SelectTimeout_Write(void) {
                    400:     selecttimeout=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    401:        Log_Printf(LOG_SCSI_LEVEL,"ESP SelectTimeout write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    402: }
                    403: 
                    404: void SCSI_SeqStep_Read(void) { // 0x02014006
                    405:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=seqstep;
                    406:        Log_Printf(LOG_SCSI_LEVEL,"ESP SeqStep read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    407: }
                    408: 
                    409: void SCSI_SyncPeriod_Write(void) {
                    410:     syncperiod=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    411:        Log_Printf(LOG_SCSI_LEVEL,"ESP SyncPeriod write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    412: }
                    413: 
                    414: void SCSI_FIFOflags_Read(void) { // 0x02014007
                    415:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=fifoflags;
                    416:        Log_Printf(LOG_WARN,"ESP FIFOflags read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    417: }
                    418: 
                    419: void SCSI_SyncOffset_Write(void) {
                    420:     syncoffset=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    421:        Log_Printf(LOG_SCSI_LEVEL,"ESP SyncOffset write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    422: }
                    423: 
                    424: void SCSI_Configuration_Read(void) { // 0x02014008
                    425:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=configuration;
                    426:        Log_Printf(LOG_SCSI_LEVEL,"ESP Configuration read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    427:     esp_raise_irq(); // experimental!
                    428: }
                    429: 
                    430: void SCSI_Configuration_Write(void) {
                    431:     configuration=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    432:        Log_Printf(LOG_SCSI_LEVEL,"ESP Configuration write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    433: }
                    434: 
                    435: void SCSI_ClockConv_Write(void) { // 0x02014009
                    436:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=clockconv;
                    437:        Log_Printf(LOG_SCSI_LEVEL,"ESP ClockConv write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    438: }
                    439: 
                    440: void SCSI_Test_Write(void) { // 0x0201400a
                    441:     esptest=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
                    442:        Log_Printf(LOG_SCSI_LEVEL,"ESP Test write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
                    443: }
                    444: 
                    445: /* System reads this register to check if we use old or new SCSI controller.
                    446:  * Return 0 to report old chip. */
                    447: void SCSI_Conf2_Read(void) { // 0x0201400b
                    448:     if (ConfigureParams.System.nSCSI == NCR53C90)
                    449:         IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = 0x00;
                    450: }
                    451: 
                    452: 
                    453: /* Functions */
                    454: 
                    455: void esp_reset_hard(void) {
                    456:     Log_Printf(LOG_WARN, "ESP hard reset\n");
                    457:     /* hard reset */
                    458:     clockconv = 0x02;
                    459:     configuration &= ~0xF8; // clear chip test mode, parity enable, parity test, scsi request/int disable, slow cable mode
                    460:     syncperiod = 0x05;
                    461:     syncoffset = 0x00;
                    462:     intstatus = 0x00;
                    463:     status &= ~(STAT_VGC | STAT_PE | STAT_GE); // need valid group code bit? clear transfer complete aka valid group code, parity error, gross error
                    464:     esp_flush_fifo();
                    465:     esp_lower_irq();
                    466:     esp_reset_soft();
                    467: }
                    468: 
                    469: void esp_reset_soft(void) {
                    470:     status &= ~STAT_TC; // clear transfer count zero
                    471:     
                    472:     /* incomplete, need to work on everything below this point */
                    473:     
                    474:     dma_cb = NULL; // clear DMA interface - how to do this?
                    475:     mode_dma = 0;
                    476:     readtranscountl = 0x00;
                    477:     readtranscounth = 0x00;
                    478:     writetranscountl = 0x00;
                    479:     writetranscounth = 0x00;
                    480: 
                    481:     seqstep = 0x00;
                    482: 
                    483:     command = 0x00;
                    484:     selectbusid = 0x00;
                    485:     selecttimeout= 0x00;
                    486:     fifoflags = 0x00;
                    487:     esptest = 0x00;
                    488: }
                    489: 
                    490: void esp_raise_irq(void) {
                    491:     if(!(status & STAT_INT)) {
                    492:         status |= STAT_INT;
                    493:         irq_status = 1;
                    494:         
                    495:         set_interrupt(INT_SCSI, SET_INT);
                    496:         
                    497:         //Log_Printf(LOG_SCSI_LEVEL, "Raise IRQ\n");
                    498:         char s[16];
                    499:         switch (state) {
                    500:             case DISCONNECTED: sprintf(s, "disconntected"); break;
                    501:             case RESELECTABLE: sprintf(s, "reselectable"); break;
                    502:             case SELECTING: sprintf(s, "selecting"); break;
                    503:             case INITIATOR: sprintf(s, "initiator"); break;
                    504:             case DISABLINGSEL: sprintf(s, "diablingsel"); break;
                    505:             case COMPLETING: sprintf(s, "completing"); break;
                    506:             case DMAING: sprintf(s, "dmaing"); break;
                    507:             case ACCEPTINGMSG: sprintf(s, "acceptingmsg"); break;
                    508:             case SENDINGMSG: sprintf(s, "sendingmsg"); break;
                    509:             case PADDING: sprintf(s, "padding"); break;
                    510:             case GETTINGMSG: sprintf(s, "gettingmsg"); break;
                    511:             case GETTINGLUN: sprintf(s, "gettinglun"); break;
                    512:             case IGNOREILLCMD: sprintf(s, "ignoreillcmd"); break;
                    513:             default: sprintf(s, "unknown"); break;
                    514:         }
                    515: //        Log_Printf(LOG_WARN, "Raise IRQ: state: %s\n", s);
                    516:         Log_Printf(LOG_WARN, "Raise IRQ:");
                    517:         switch (status&STAT_MI) {
                    518:             case STAT_DO: sprintf(s, "data out"); break;
                    519:             case STAT_DI: sprintf(s, "data in"); break;
                    520:             case STAT_CD: sprintf(s, "command"); break;
                    521:             case STAT_ST: sprintf(s, "status"); break;
                    522:             case STAT_MI: sprintf(s, "msg in"); break;
                    523:             case STAT_MO: sprintf(s, "msg out"); break;
                    524:             default: sprintf(s, "unknown"); break;
                    525:         }
                    526:         Log_Printf(LOG_WARN, "Status: %02x (phase: %s, %s%s)\n", status, s,
                    527:                    status&STAT_TC?"transfer complete":"",
                    528:                    status&STAT_INT?", interrupt":"");
                    529:         Log_Printf(LOG_WARN, "Sequence Step: %02x\n", seqstep);
                    530:         Log_Printf(LOG_WARN, "Interrupt Status: %02x (%s%s%s%s%s%s%s%s)\n", intstatus,
                    531:                    intstatus&INTR_RST?"bus reset, ":"",
                    532:                    intstatus&INTR_BS?"bus service, ":"",
                    533:                    intstatus&INTR_DC?"disconnected, ":"",
                    534:                    intstatus&INTR_FC?"function compl, ":"",
                    535:                    intstatus&INTR_ILL?"illegal comm, ":"",
                    536:                    intstatus&INTR_RESEL?"reselected, ":"",
                    537:                    intstatus&INTR_SEL?"selected, ":"",
                    538:                    intstatus&INTR_SELATN?"selected w ATN":"");
                    539:     }
                    540: }
                    541: 
                    542: void esp_lower_irq(void) {
                    543:     if (status & STAT_INT) {
                    544:         status &= ~STAT_INT;
                    545:         irq_status = 0;
                    546:         
                    547:         set_interrupt(INT_SCSI, RELEASE_INT);
                    548:         
                    549:         Log_Printf(LOG_SCSI_LEVEL, "Lower IRQ\n");
                    550:     }
                    551: }
                    552: 
                    553: void esp_flush_fifo(void) {
                    554:     fifo_read_ptr = 0;
                    555:     fifo_write_ptr = 0;
                    556:     esp_fifo[0] = 0;
                    557:     fifoflags &= 0xE0;
                    558: }
                    559: 
                    560: Uint32 get_cmd (void) {
                    561:     
                    562:     if(mode_dma == 1) {
                    563:         command_len = readtranscountl | (readtranscounth << 8);
                    564:         //dma_memory_read(command_len);
                    565:         memcpy(commandbuf, dma_read_buffer, command_len);
                    566:     } else {
                    567:         command_len = fifo_write_ptr - fifo_read_ptr;
                    568:         memcpy(commandbuf, esp_fifo, command_len);
                    569:         
                    570:         esp_flush_fifo();
                    571:     }
                    572:     Log_Printf(LOG_SCSI_LEVEL, "get_cmd: len %i", command_len);
                    573:     
                    574:     return command_len;
                    575: }
                    576: 
                    577: void do_cmd(void) {
                    578:     Uint8 busid = selectbusid;
                    579:     do_busid_cmd(busid);
                    580: }
                    581: 
                    582: void handle_satn(void) {
                    583:     Uint8 scsi_command_group;
                    584:     
                    585:     get_cmd(); // make get_cmd void function?
                    586:     // clear valid command status
                    587:     status &= ~STAT_VGC;
                    588: 
                    589:     /* Decode command to determine the command group and thus the
                    590:      * length of the incoming command. Set "valid group code" bit
                    591:      * in status register if the group is 0, 1, 5, 6, or 7 (group
                    592:      * 2 is also valid on NCR53C90A).
                    593:      */
                    594:     scsi_command_group = (commandbuf[1] & 0xE0) >> 5;
                    595:     if(scsi_command_group < 3 || scsi_command_group > 4) {
                    596:         if(ConfigureParams.System.nSCSI == NCR53C90 && scsi_command_group == 2) {
                    597:             Log_Printf(LOG_WARN, "Invalid command group %i on NCR53C90\n", scsi_command_group);
                    598:         } else {
                    599:             status |= STAT_VGC;
                    600:         }
                    601:     } else {
                    602:         Log_Printf(LOG_WARN, "Invalid command group %i on NCR53C90A\n", scsi_command_group);
                    603:     }
                    604: 
                    605:     if (command_len != 0)
                    606:         do_cmd();
                    607: }
                    608: 
                    609: void do_busid_cmd(Uint8 busid) {
                    610:     int lun,lun2;
                    611:     int target = busid & BUSID_DID;
                    612:     Log_Printf(LOG_SCSI_LEVEL, "do_busid_cmd: busid $%02x",busid);
                    613: 
                    614:     lun = (commandbuf[0]&0x07);
                    615:     
                    616:     scsi_command_analyzer(commandbuf, command_len, target,lun);
                    617:     data_len = SCSIcommand.transfer_data_len;
                    618: 
                    619:     if ((target >= ESP_MAX_DEVS) || (SCSIcommand.timeout==true)) { // experimental
                    620:     Log_Printf(LOG_SCSI_LEVEL, "No target found !! Target %d Lun %d raise irq %s at %d",target,lun,__FILE__,__LINE__);
                    621:         intstatus = INTR_DC;
                    622:         seqstep = 0x00;//SEQ_SELTIMEOUT;
                    623:         status = (status&STAT_MASK)|STAT_MI; // seems weird... http://permalink.gmane.org/gmane.os.netbsd.ports.next68k/305
                    624:         no_target=true;
                    625:         esp_raise_irq();
                    626:        return;
                    627:     }
                    628: 
                    629:     if (SCSIcommand.nodevice==true) { // experimental
                    630:     Log_Printf(LOG_SCSI_LEVEL, "No device found !! Target %d Lun %d raise irq %s at %d",target,lun,__FILE__,__LINE__);
                    631:        
                    632:         status = (status&STAT_MASK)|STAT_ST;
                    633:         intstatus = INTR_BS|INTR_FC;//INTR_DC;
                    634:         seqstep = SEQ_CD;//SEQ_SELTIMEOUT;
                    635:         esp_raise_irq();
                    636:         return;
                    637:     }
                    638:     
                    639:     status = (status&STAT_MASK)| STAT_ST;
                    640: 
                    641:     if (data_len != 0) {
                    642:         Log_Printf(LOG_SCSI_LEVEL, "executing command\n");
                    643:         status = STAT_TC;
                    644:         
                    645:         dma_left = 0;
                    646:         dma_counter = 0;
                    647:         
                    648:         if(SCSIcommand.transferdirection_todevice == 0) {
                    649:             Log_Printf(LOG_SCSI_LEVEL, "DATA IN\n");
                    650:             status = (status&STAT_MASK)| STAT_DI;
                    651:         } else {
                    652:             Log_Printf(LOG_SCSI_LEVEL, "DATA OUT\n");
                    653:             status = (status&STAT_MASK)| STAT_DO;
                    654:         }
                    655:     esp_transfer_data();
                    656:     }
                    657:     
                    658:     intstatus = INTR_BS | INTR_FC;
                    659:     seqstep = SEQ_CD;
                    660:     
                    661:     esp_raise_irq();   
                    662: }
                    663: 
                    664: 
                    665: void esp_transfer_data(void) {
                    666:     Log_Printf(LOG_SCSI_LEVEL, "transfer %d/%d\n", dma_left, data_len);
                    667:     
                    668: //    async_len = len;
                    669: //    async_buf = scsi_req_get_buf(req);
                    670:     if(dma_left) {
                    671:         esp_do_dma();
                    672:     } else if(dma_counter != 0 && data_len <= 0) {
                    673:         esp_dma_done();
                    674:     }
                    675: }
                    676: 
                    677: 
                    678: void esp_do_dma(void) {
                    679:     
                    680:     Log_Printf(LOG_SCSI_LEVEL, "call esp_do_dma\n");
                    681: 
                    682:     Uint32 len;
                    683:     int to_device;
                    684:     
                    685:     Uint32 dma_translen; // experimental
                    686:     dma_translen = readtranscountl | (readtranscounth << 8); // experimental
                    687:     Log_Printf(LOG_SCSI_LEVEL, "call dma_write\n"); // experimental
                    688:     dma_memory_write(dma_write_buffer, dma_translen, CHANNEL_SCSI);//experimental !!
                    689: 
                    690:     
                    691:     to_device = SCSIcommand.transferdirection_todevice;
                    692:     
                    693:     len = dma_left;
                    694:     
                    695:     if(do_cmdvar){
                    696:         abort();
                    697:     }
                    698:     if(async_len == 0) {
                    699: 
                    700:     }
                    701:     if(len > async_len) {
                    702:         len = async_len;
                    703:     }
                    704:     if(to_device) {
                    705: //        dma_memory_read(async_buf, len);
                    706:     } else { 
                    707: //        dma_memory_write(async_buf, len);
                    708:     }
                    709:     
                    710:     dma_left -= len;
                    711:     async_buf += len;
                    712:     async_len -= len;
                    713:     
                    714:     if(to_device)
                    715:         data_len += len;
                    716:     else
                    717:         data_len -= len;
                    718:     
                    719:     if(async_len == 0) {
                    720: //        scsi_req_continue(current_req);
                    721:         
                    722:         if (to_device || dma_left != 0 || (fifo_write_ptr - fifo_read_ptr) == 0) {
                    723: //            return;
                    724:         }
                    725:     }
                    726:     esp_dma_done();
                    727: }
                    728: 
                    729: void esp_dma_done(void) {
                    730:     Log_Printf(LOG_SCSI_LEVEL, "call esp_dma_done\n");
                    731:     status = (status&STAT_MASK)|STAT_ST;
                    732:     status |= STAT_TC;
                    733:     intstatus = INTR_BS;
                    734:     seqstep = 0;
                    735:     fifoflags = 0;
                    736:     readtranscountl = 0;
                    737:     readtranscounth = 0;
                    738: }
                    739: 
                    740: 
                    741: // transfer information
                    742: void handle_ti(void){
                    743:     Uint32 dma_len, min_len;
                    744:     
                    745:     dma_len = readtranscountl | (readtranscounth << 8);
                    746:     
                    747:     if(dma_len == 0) {
                    748:         dma_len = 0x10000;
                    749:     }
                    750:     
                    751:     dma_counter = dma_len;
                    752:     
                    753:     if(do_cmdvar)
                    754:         min_len = (dma_len < 32) ? dma_len : 32;
                    755:     else
                    756:         min_len = (dma_len > data_len) ? dma_len : data_len;
                    757:     Log_Printf(LOG_SCSI_LEVEL, "Transfer Information len %d\n", min_len);
                    758:     
                    759:     if(mode_dma) {
                    760:         dma_left = min_len;
                    761:         status &= ~STAT_TC;
                    762:         esp_do_dma();
                    763:     }else if(do_cmdvar){
                    764:         Log_Printf(LOG_SCSI_LEVEL, "Command len: %i\n",cmdlen);
                    765:         data_len = 0;
                    766:         cmdlen = 0;
                    767:         do_cmdvar = 0;
                    768:         do_cmd();
                    769:         return;
                    770:     }
                    771: }
                    772: 
                    773: void esp_command_complete (void) {
                    774:     Log_Printf(LOG_SCSI_LEVEL, "SCSI Command complete\n");
                    775:     if (data_len != 0)
                    776:         Log_Printf(LOG_SCSI_LEVEL, "SCSI Command completed unexpectedly\n");
                    777:     data_len = 0;
                    778:     dma_left = 0;
                    779:     async_len = 0;
                    780:     
                    781: //    if(status) {
                    782: //        Log_Printf(LOG_SCSI_LEVEL, "Command failed\n");
                    783: //    }
                    784: //  status = status; return status, not status register!!
                    785:     status = STAT_ST;
                    786:     seqstep = SEQ_0;
                    787:     if(mode_dma)    
                    788:        esp_dma_done();
                    789: }
                    790: 
                    791: void write_response(void) {
                    792:     Log_Printf(LOG_SCSI_LEVEL, "Transfer status: $%02x\n", SCSIcommand.returnCode);
                    793:     esp_fifo[0] = SCSIcommand.returnCode; // status
                    794:     esp_fifo[1] = 0x00; // message
                    795:     
                    796:     if(mode_dma == 1) {
                    797:         dma_memory_write(esp_fifo, 2, CHANNEL_SCSI);
                    798:         status = (status & STAT_MASK) | STAT_TC | STAT_ST;
                    799:         intstatus = INTR_BS | INTR_FC;
                    800:         seqstep = SEQ_CD;
                    801:     } else {
                    802:         status = (status & STAT_MASK) | STAT_ST;
                    803:         fifo_read_ptr = 0;
                    804:         fifo_write_ptr = 2;
                    805:         fifoflags = (fifoflags & 0xE0) | 2;
                    806:     }
                    807: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.