Annotation of previous_trunk/src/esp.c, revision 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_ESPDMA_LEVEL    LOG_DEBUG   /* Print debugging messages for ESP DMA registers */
        !            15: #define LOG_ESPCMD_LEVEL    LOG_DEBUG   /* Print debugging messages for ESP commands */
        !            16: #define LOG_ESPREG_LEVEL    LOG_DEBUG   /* Print debugging messages for ESP registers */
        !            17: #define LOG_ESPFIFO_LEVEL   LOG_DEBUG   /* Print debugging messages for ESP FIFO */
        !            18: 
        !            19: 
        !            20: #define IO_SEG_MASK    0x1FFFF
        !            21: 
        !            22: typedef enum {
        !            23:     DISCONNECTED,
        !            24:     INITIATOR,
        !            25:     TARGET
        !            26: } SCSI_STATE;
        !            27: 
        !            28: SCSI_STATE esp_state;
        !            29: 
        !            30: 
        !            31: /* ESP FIFO */
        !            32: #define ESP_FIFO_SIZE 16
        !            33: Uint8 esp_fifo_read(void);
        !            34: void esp_fifo_write(Uint8 val);
        !            35: void esp_fifo_clear(void);
        !            36: 
        !            37: /* ESP Command Register */
        !            38: Uint8 esp_cmd_state;
        !            39: #define ESP_CMD_INPROGRESS  0x01
        !            40: #define ESP_CMD_WAITING     0x02
        !            41: void esp_start_command(Uint8 cmd);
        !            42: void esp_finish_command(void);
        !            43: void esp_command_clear(void);
        !            44: void esp_command_write(Uint8 cmd);
        !            45: 
        !            46: /* ESP Registers */
        !            47: Uint8 writetranscountl;
        !            48: Uint8 writetranscounth;
        !            49: Uint8 fifo[ESP_FIFO_SIZE];
        !            50: Uint8 command[2];
        !            51: Uint8 status;
        !            52: Uint8 selectbusid;
        !            53: Uint8 intstatus;
        !            54: Uint8 selecttimeout;
        !            55: Uint8 seqstep;
        !            56: Uint8 syncperiod;
        !            57: Uint8 fifoflags;
        !            58: Uint8 syncoffset;
        !            59: Uint8 configuration;
        !            60: Uint8 clockconv;
        !            61: Uint8 esptest;
        !            62: 
        !            63: Uint32 esp_counter;
        !            64: 
        !            65: 
        !            66: /* Command Register */
        !            67: #define CMD_DMA      0x80
        !            68: #define CMD_CMD      0x7f
        !            69: 
        !            70: #define CMD_TYP_MASK 0x70
        !            71: #define CMD_TYP_MSC  0x00
        !            72: #define CMD_TYP_TGT  0x20
        !            73: #define CMD_TYP_INR  0x10
        !            74: #define CMD_TYP_DIS  0x40
        !            75: 
        !            76: /* Miscellaneous Commands */
        !            77: #define CMD_NOP      0x00
        !            78: #define CMD_FLUSH    0x01
        !            79: #define CMD_RESET    0x02
        !            80: #define CMD_BUSRESET 0x03
        !            81: /* Initiator Commands */
        !            82: #define CMD_TI       0x10
        !            83: #define CMD_ICCS     0x11
        !            84: #define CMD_MSGACC   0x12
        !            85: #define CMD_PAD      0x18
        !            86: #define CMD_SATN     0x1a
        !            87: /* Disconnected Commands */
        !            88: #define CMD_RESEL    0x40
        !            89: #define CMD_SEL      0x41
        !            90: #define CMD_SELATN   0x42
        !            91: #define CMD_SELATNS  0x43
        !            92: #define CMD_ENSEL    0x44
        !            93: #define CMD_DISSEL   0x45
        !            94: /* Target Commands */
        !            95: #define CMD_SEMSG    0x20
        !            96: #define CMD_SESTAT   0x21
        !            97: #define CMD_SEDAT    0x22
        !            98: #define CMD_DISSEQ   0x23
        !            99: #define CMD_TERMSEQ  0x24
        !           100: #define CMD_TCCS     0x25
        !           101: #define CMD_DIS      0x27
        !           102: #define CMD_RMSGSEQ  0x28
        !           103: #define CMD_RCOMM    0x29
        !           104: #define CMD_RDATA    0x2A
        !           105: #define CMD_RCSEQ    0x2B
        !           106: 
        !           107: /* Status Register */
        !           108: #define STAT_MASK    0xF8
        !           109: #define STAT_PHASE   0x07
        !           110: 
        !           111: #define STAT_VGC     0x08
        !           112: #define STAT_TC      0x10
        !           113: #define STAT_PE      0x20
        !           114: #define STAT_GE      0x40
        !           115: #define STAT_INT     0x80
        !           116: 
        !           117: /* Bus ID Register */
        !           118: #define BUSID_DID    0x07
        !           119: 
        !           120: /* Interrupt Status Register */
        !           121: #define INTR_SEL     0x01
        !           122: #define INTR_SELATN  0x02
        !           123: #define INTR_RESEL   0x04
        !           124: #define INTR_FC      0x08
        !           125: #define INTR_BS      0x10
        !           126: #define INTR_DC      0x20
        !           127: #define INTR_ILL     0x40
        !           128: #define INTR_RST     0x80
        !           129: 
        !           130: /* Sequence Step Register */
        !           131: #define SEQ_0        0x00
        !           132: #define SEQ_SELTIMEOUT 0x02
        !           133: #define SEQ_CD       0x04
        !           134: 
        !           135: /* Configuration Register */
        !           136: #define CFG1_RESREPT 0x40
        !           137: 
        !           138: 
        !           139: /* ESP Status Variables */
        !           140: Uint8 mode_dma;
        !           141: 
        !           142: /* Experimental */
        !           143: #define ESP_CLOCK_FREQ  20      /* ESP is clocked at 20 MHz */
        !           144: #define ESP_DELAY       100     /* Standard wait time for ESP interrupt (except bus reset and selection timeout) */
        !           145: 
        !           146: 
        !           147: /* ESP DMA control and status registers */
        !           148: 
        !           149: void ESP_DMA_CTRL_Read(void) {
        !           150:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = esp_dma.control;
        !           151:        Log_Printf(LOG_ESPDMA_LEVEL,"ESP DMA control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           152: }
        !           153: 
        !           154: void ESP_DMA_CTRL_Write(void) {
        !           155:     Log_Printf(LOG_ESPDMA_LEVEL,"ESP DMA control write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           156:     esp_dma.control = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           157:         
        !           158:     if (esp_dma.control&ESPCTRL_FLUSH) {
        !           159:         Log_Printf(LOG_ESPDMA_LEVEL, "flush DMA buffer\n");
        !           160:                if (ConfigureParams.System.bTurbo) {
        !           161:                        tdma_flush_buffer(0);
        !           162:                } else {
        !           163:                        dma_esp_flush_buffer();
        !           164:                }
        !           165:     }
        !           166:     if (esp_dma.control&ESPCTRL_CHIP_TYPE) {
        !           167:         Log_Printf(LOG_ESPDMA_LEVEL, "SCSI controller is WD33C92\n");
        !           168:     } else {
        !           169:         Log_Printf(LOG_ESPDMA_LEVEL, "SCSI controller is NCR53C90\n");
        !           170:     }
        !           171:     if (esp_dma.control&ESPCTRL_RESET) {
        !           172:         Log_Printf(LOG_ESPDMA_LEVEL, "reset SCSI controller\n");
        !           173:         esp_reset_hard();
        !           174:     }
        !           175:     if (esp_dma.control&ESPCTRL_DMA_READ) {
        !           176:         Log_Printf(LOG_ESPDMA_LEVEL, "DMA from SCSI to mem\n");
        !           177:     } else {
        !           178:         Log_Printf(LOG_ESPDMA_LEVEL, "DMA from mem to SCSI\n");
        !           179:     }
        !           180:     if (esp_dma.control&ESPCTRL_MODE_DMA) {
        !           181:         Log_Printf(LOG_ESPDMA_LEVEL, "mode DMA\n");
        !           182:     } else {
        !           183:         Log_Printf(LOG_ESPDMA_LEVEL, "mode PIO\n");
        !           184:     }
        !           185:     if (esp_dma.control&ESPCTRL_ENABLE_INT) {
        !           186:         Log_Printf(LOG_ESPDMA_LEVEL, "Enable ESP interrupt");
        !           187:         if (status&STAT_INT) {
        !           188:             set_interrupt(INT_SCSI, SET_INT);
        !           189:         }
        !           190:     } else {
        !           191:         Log_Printf(LOG_ESPDMA_LEVEL, "Block ESP interrupt");
        !           192:         set_interrupt(INT_SCSI, RELEASE_INT);
        !           193:     }
        !           194:     switch (esp_dma.control&ESPCTRL_CLKMASK) {
        !           195:         case ESPCTRL_CLK10MHz:
        !           196:             Log_Printf(LOG_ESPDMA_LEVEL, "10 MHz clock\n");
        !           197:             break;
        !           198:         case ESPCTRL_CLK12MHz:
        !           199:             Log_Printf(LOG_ESPDMA_LEVEL, "12.5 MHz clock\n");
        !           200:             break;
        !           201:         case ESPCTRL_CLK16MHz:
        !           202:             Log_Printf(LOG_ESPDMA_LEVEL, "16.6 MHz clock\n");
        !           203:             break;
        !           204:         case ESPCTRL_CLK20MHz:
        !           205:             Log_Printf(LOG_ESPDMA_LEVEL, "20 MHz clock\n");
        !           206:             break;
        !           207:         default:
        !           208:             break;
        !           209:     }
        !           210: }
        !           211: 
        !           212: void ESP_DMA_FIFO_STAT_Read(void) {
        !           213:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = esp_dma.status;
        !           214:        Log_Printf(LOG_ESPDMA_LEVEL,"ESP DMA FIFO status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           215: }
        !           216: 
        !           217: void ESP_DMA_FIFO_STAT_Write(void) {
        !           218:        Log_Printf(LOG_ESPDMA_LEVEL,"ESP DMA FIFO status write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           219:     esp_dma.status = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           220: }
        !           221: 
        !           222: void ESP_DMA_set_status(void) { /* this is just a guess */
        !           223:     if ((esp_dma.status&ESPSTAT_STATE_MASK) == ESPSTAT_STATE_D0S1) {
        !           224:         //Log_Printf(LOG_WARN,"DMA in buffer 0, SCSI in buffer 1\n");
        !           225:         esp_dma.status = (esp_dma.status&~ESPSTAT_STATE_MASK)|ESPSTAT_STATE_D1S0;
        !           226:     } else {
        !           227:         //Log_Printf(LOG_WARN,"DMA in buffer 1, SCSI in buffer 0\n");
        !           228:         esp_dma.status = (esp_dma.status&~ESPSTAT_STATE_MASK)|ESPSTAT_STATE_D0S1;
        !           229:     }
        !           230: }
        !           231: 
        !           232: /* ESP Registers */
        !           233: 
        !           234: void ESP_TransCountL_Read(void) { // 0x02014000
        !           235:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=esp_counter&0xFF;
        !           236:        Log_Printf(LOG_ESPREG_LEVEL,"ESP TransCountL read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           237: }
        !           238: 
        !           239: void ESP_TransCountL_Write(void) {
        !           240:     writetranscountl=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           241:        Log_Printf(LOG_ESPREG_LEVEL,"ESP TransCountL write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           242: }
        !           243: 
        !           244: void ESP_TransCountH_Read(void) { // 0x02014001
        !           245:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=(esp_counter>>8)&0xFF;
        !           246:        Log_Printf(LOG_ESPREG_LEVEL,"ESP TransCoundH read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           247: }
        !           248: 
        !           249: void ESP_TransCountH_Write(void) {
        !           250:     writetranscounth=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           251:        Log_Printf(LOG_ESPREG_LEVEL,"ESP TransCountH write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           252: }
        !           253: 
        !           254: void ESP_FIFO_Read(void) { // 0x02014002
        !           255:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = esp_fifo_read();
        !           256:     Log_Printf(LOG_ESPREG_LEVEL,"ESP FIFO read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           257: }
        !           258: 
        !           259: void ESP_FIFO_Write(void) {
        !           260:     esp_fifo_write(IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
        !           261:     Log_Printf(LOG_ESPREG_LEVEL,"ESP FIFO write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           262: }
        !           263: 
        !           264: void ESP_Command_Read(void) { // 0x02014003
        !           265:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=command[0];
        !           266:        Log_Printf(LOG_ESPREG_LEVEL,"ESP Command read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           267: }
        !           268: 
        !           269: void ESP_Command_Write(void) {
        !           270:     esp_command_write(IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
        !           271:        Log_Printf(LOG_ESPREG_LEVEL,"ESP Command write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           272: }
        !           273: 
        !           274: void ESP_Status_Read(void) { // 0x02014004
        !           275:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=(status&STAT_MASK)|(SCSIbus.phase&STAT_PHASE);
        !           276:        Log_Printf(LOG_ESPREG_LEVEL,"ESP Status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           277: }
        !           278: 
        !           279: void ESP_SelectBusID_Write(void) {
        !           280:     selectbusid=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           281:        Log_Printf(LOG_ESPREG_LEVEL,"ESP SelectBusID write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           282: }
        !           283: 
        !           284: void ESP_IntStatus_Read(void) { // 0x02014005
        !           285:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=intstatus;
        !           286:     Log_Printf(LOG_ESPREG_LEVEL,"ESP IntStatus read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           287:     
        !           288:     if (status&STAT_INT) {
        !           289:             intstatus = 0x00;
        !           290:             status &= ~(STAT_VGC | STAT_PE | STAT_GE);
        !           291:             //seqstep = 0x00; /* FIXME: Is the data sheet really wrong with this? */
        !           292:             esp_lower_irq();
        !           293:     }
        !           294: }
        !           295: 
        !           296: void ESP_SelectTimeout_Write(void) {
        !           297:     selecttimeout=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           298:        Log_Printf(LOG_ESPREG_LEVEL,"ESP SelectTimeout write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           299: }
        !           300: 
        !           301: void ESP_SeqStep_Read(void) { // 0x02014006
        !           302:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=seqstep;
        !           303:        Log_Printf(LOG_ESPREG_LEVEL,"ESP SeqStep read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           304: }
        !           305: 
        !           306: void ESP_SyncPeriod_Write(void) {
        !           307:     syncperiod=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           308:        Log_Printf(LOG_ESPREG_LEVEL,"ESP SyncPeriod write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           309: }
        !           310: 
        !           311: void ESP_FIFOflags_Read(void) { // 0x02014007
        !           312:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=fifoflags;
        !           313:        Log_Printf(LOG_ESPREG_LEVEL,"ESP FIFOflags read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           314: }
        !           315: 
        !           316: void ESP_SyncOffset_Write(void) {
        !           317:     syncoffset=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           318:        Log_Printf(LOG_ESPREG_LEVEL,"ESP SyncOffset write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           319: }
        !           320: 
        !           321: void ESP_Configuration_Read(void) { // 0x02014008
        !           322:     IoMem[IoAccessCurrentAddress & IO_SEG_MASK]=configuration;
        !           323:        Log_Printf(LOG_ESPREG_LEVEL,"ESP Configuration read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           324: }
        !           325: 
        !           326: void ESP_Configuration_Write(void) {
        !           327:     configuration=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           328:        Log_Printf(LOG_ESPREG_LEVEL,"ESP Configuration write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           329: }
        !           330: 
        !           331: void ESP_ClockConv_Write(void) { // 0x02014009
        !           332:     clockconv=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           333:        Log_Printf(LOG_ESPREG_LEVEL,"ESP ClockConv write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           334: }
        !           335: 
        !           336: void ESP_Test_Write(void) { // 0x0201400a
        !           337:     esptest=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
        !           338:        Log_Printf(LOG_ESPREG_LEVEL,"ESP Test write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           339: }
        !           340: 
        !           341: /* System reads this register to check if we use old or new SCSI controller.
        !           342:  * Return 0 to report old chip. */
        !           343: void ESP_Conf2_Read(void) { // 0x0201400b
        !           344:     if (ConfigureParams.System.nSCSI == NCR53C90)
        !           345:         IoMem[IoAccessCurrentAddress&IO_SEG_MASK] = 0x00;
        !           346:     Log_Printf(LOG_ESPREG_LEVEL,"ESP Configuration2 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
        !           347: }
        !           348: 
        !           349: 
        !           350: /* Helper functions */
        !           351: 
        !           352: /* Functions for reading and writing ESP FIFO */
        !           353: Uint8 esp_fifo_read(void) {
        !           354:     int i;
        !           355:     Uint8 val;
        !           356:     
        !           357:     if (fifoflags > 0) {
        !           358:         val = fifo[0];
        !           359:         for (i=0; i<(ESP_FIFO_SIZE-1); i++)
        !           360:             fifo[i]=fifo[i+1];
        !           361:         fifo[ESP_FIFO_SIZE-1] = 0x00;
        !           362:         fifoflags--;
        !           363:         Log_Printf(LOG_ESPFIFO_LEVEL,"ESP FIFO: Reading byte, val=%02x, size = %i", val, fifoflags);
        !           364:     } else {
        !           365:         val = 0x00;
        !           366:         Log_Printf(LOG_WARN, "ESP FIFO read: FIFO is empty!\n");
        !           367:     }
        !           368:     return val;
        !           369: }
        !           370: 
        !           371: void esp_fifo_write(Uint8 val) {
        !           372:     if (fifoflags==ESP_FIFO_SIZE) {
        !           373:         Log_Printf(LOG_WARN, "ESP FIFO write: FIFO overflow! Top of FIFO overwritten\n");
        !           374:         fifo[fifoflags-1] = val;
        !           375:         status |= STAT_GE;
        !           376:     } else {
        !           377:         fifoflags++;
        !           378:         fifo[fifoflags-1] = val;
        !           379:         Log_Printf(LOG_ESPFIFO_LEVEL,"ESP FIFO: Writing byte %i, val=%02x", fifoflags-1, fifo[fifoflags-1]);
        !           380:     }
        !           381: }
        !           382: 
        !           383: void esp_fifo_clear(void) {
        !           384:     int i;
        !           385:     for (i=0; i<ESP_FIFO_SIZE; i++) {
        !           386:         fifo[i] = 0;
        !           387:     }
        !           388:     fifoflags &= 0xE0;
        !           389: }
        !           390: 
        !           391: /* Functions for handling dual ranked command register */
        !           392: void esp_command_write(Uint8 cmd) {
        !           393:     if ((command[1]&CMD_CMD)==CMD_RESET && (cmd&CMD_CMD)!=CMD_NOP) {
        !           394:         Log_Printf(LOG_WARN, "ESP command write: Chip reset in command register, not executing command.\n");
        !           395:     } else {
        !           396:         command[1] = cmd;
        !           397:         
        !           398:         if (esp_cmd_state&ESP_CMD_WAITING) {
        !           399:             Log_Printf(LOG_WARN, "ESP command write: Error! Top of command register overwritten.\n");
        !           400:             status |= STAT_GE;
        !           401:         }
        !           402:     }
        !           403:     
        !           404:     if ((command[1]&CMD_CMD)==CMD_RESET || (command[1]&CMD_CMD)==CMD_BUSRESET) {
        !           405:         esp_start_command(command[1]);
        !           406:         return;
        !           407:     }
        !           408:     
        !           409:     if (esp_cmd_state&ESP_CMD_INPROGRESS) {
        !           410:         esp_cmd_state |= ESP_CMD_WAITING;
        !           411:     } else {
        !           412:         command[0] = command[1];
        !           413:         command[1] = 0x00;
        !           414:         esp_start_command(command[0]);
        !           415:     }
        !           416: }
        !           417: 
        !           418: void esp_command_clear(void) {
        !           419:     command[0] = 0x00;
        !           420:     if ((command[1]&CMD_CMD)!=CMD_RESET) {
        !           421:         command[1] = 0x00;
        !           422:         esp_cmd_state &= ~ESP_CMD_WAITING;
        !           423:     }
        !           424: }
        !           425: 
        !           426: void esp_finish_command(void) {
        !           427:     esp_cmd_state &= ~ESP_CMD_INPROGRESS;
        !           428:     if (esp_cmd_state&ESP_CMD_WAITING) {
        !           429:         command[0] = command[1];
        !           430:         command[1] = 0x00;
        !           431:         esp_cmd_state &= ~ESP_CMD_WAITING;
        !           432:         esp_start_command(command[0]);
        !           433:     }
        !           434: }
        !           435: 
        !           436: void esp_start_command(Uint8 cmd) {
        !           437:     esp_cmd_state |= ESP_CMD_INPROGRESS;
        !           438:     
        !           439:     /* Check if command is valid for actual state */
        !           440:     if ((cmd&CMD_TYP_MASK)!=CMD_TYP_MSC) {
        !           441:         if ((esp_state==TARGET && !(cmd&CMD_TYP_TGT)) ||
        !           442:             (esp_state==INITIATOR && !(cmd&CMD_TYP_INR)) ||
        !           443:             (esp_state==DISCONNECTED && !(cmd&CMD_TYP_DIS))) {
        !           444:             Log_Printf(LOG_WARN, "ESP Command: Illegal command for actual ESP state ($%02X)!\n",cmd);
        !           445:             esp_command_clear();
        !           446:             intstatus |= INTR_ILL;
        !           447:             CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           448:             return;
        !           449:         }
        !           450:     }
        !           451:     
        !           452:     /* Check if the command is a DMA command */
        !           453:     if (cmd & CMD_DMA) {
        !           454:         /* Load the internal counter on every DMA command, do not decrement actual registers! */
        !           455:         esp_counter = writetranscountl | (writetranscounth << 8);
        !           456:         if (esp_counter == 0) { /* 0 means maximum value */
        !           457:             esp_counter = 0x10000;
        !           458:         }
        !           459:         status &= ~STAT_TC;
        !           460:         mode_dma = 1;
        !           461:     } else {
        !           462:         mode_dma = 0;
        !           463:     }
        !           464:     
        !           465:     switch (cmd & CMD_CMD) {
        !           466:             /* Miscellaneous */
        !           467:         case CMD_NOP:
        !           468:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: NOP\n");
        !           469:             esp_finish_command();
        !           470:             break;
        !           471:         case CMD_FLUSH:
        !           472:             Log_Printf(LOG_ESPCMD_LEVEL,"ESP Command: flush FIFO\n");
        !           473:             esp_flush_fifo();
        !           474:             break;
        !           475:         case CMD_RESET:
        !           476:             Log_Printf(LOG_ESPCMD_LEVEL,"ESP Command: reset chip\n");
        !           477:             esp_reset_hard();
        !           478:             break;
        !           479:         case CMD_BUSRESET:
        !           480:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: reset SCSI bus\n");
        !           481:             esp_bus_reset();
        !           482:             break;
        !           483:             /* Disconnected */
        !           484:         case CMD_RESEL:
        !           485:             Log_Printf(LOG_WARN, "ESP Command: reselect sequence\n");
        !           486:             abort();
        !           487:             break;
        !           488:         case CMD_SEL:
        !           489:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: select without ATN sequence\n");
        !           490:             esp_select(false);
        !           491:             break;
        !           492:         case CMD_SELATN:
        !           493:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: select with ATN sequence\n");
        !           494:             esp_select(true);
        !           495:             break;
        !           496:         case CMD_SELATNS:
        !           497:             Log_Printf(LOG_WARN, "ESP Command: select with ATN and stop sequence\n");
        !           498:             abort();
        !           499:             break;
        !           500:         case CMD_ENSEL:
        !           501:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: enable selection/reselection\n");
        !           502:             esp_finish_command(); /* Our disk doesn't do reselections */
        !           503:             break;
        !           504:         case CMD_DISSEL:
        !           505:             Log_Printf(LOG_WARN, "ESP Command: disable selection/reselection\n");
        !           506:             abort();
        !           507:             break;
        !           508:             /* Initiator */
        !           509:         case CMD_TI:
        !           510:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: transfer information\n");
        !           511:             esp_transfer_info();
        !           512:             break;
        !           513:         case CMD_ICCS:
        !           514:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: initiator command complete sequence\n");
        !           515:             esp_initiator_command_complete();
        !           516:             break;
        !           517:         case CMD_MSGACC:
        !           518:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: message accepted\n");
        !           519:             esp_message_accepted();
        !           520:             break;
        !           521:         case CMD_PAD:
        !           522:             Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: transfer pad\n");
        !           523:             esp_transfer_pad();
        !           524:             break;
        !           525:         case CMD_SATN:
        !           526:             Log_Printf(LOG_WARN, "ESP Command: set ATN\n");
        !           527:             abort();
        !           528:             break;
        !           529:             /* Target */
        !           530:         case CMD_SEMSG:
        !           531:         case CMD_SESTAT:
        !           532:         case CMD_SEDAT:
        !           533:         case CMD_DISSEQ:
        !           534:         case CMD_TERMSEQ:
        !           535:         case CMD_TCCS:
        !           536:         case CMD_RMSGSEQ:
        !           537:         case CMD_RCOMM:
        !           538:         case CMD_RDATA:
        !           539:         case CMD_RCSEQ:
        !           540:             Log_Printf(LOG_WARN, "ESP Command: Target commands not emulated!\n");
        !           541:             abort();
        !           542:             break;
        !           543:         case CMD_DIS:
        !           544:             Log_Printf(LOG_WARN, "ESP Command: DISCONNECT not emulated!\n");
        !           545:             abort();
        !           546:             SCSIbus.phase = PHASE_ST;
        !           547:             intstatus = INTR_DC;
        !           548:             seqstep = SEQ_0;
        !           549:             break;
        !           550:             
        !           551:         default:
        !           552:             Log_Printf(LOG_WARN, "ESP Command: Illegal command!\n");
        !           553:             esp_command_clear();
        !           554:             intstatus |= INTR_ILL;
        !           555:             CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           556:             break;
        !           557:     }
        !           558: }
        !           559: 
        !           560: 
        !           561: /* This is the handler function for ESP delayed interrupts */
        !           562: void ESP_InterruptHandler(void) {
        !           563:        CycInt_AcknowledgeInterrupt();
        !           564:     esp_raise_irq();
        !           565: }
        !           566: 
        !           567: 
        !           568: void esp_raise_irq(void) {
        !           569:     if(!(status & STAT_INT)) {
        !           570:         status |= STAT_INT;
        !           571:         
        !           572:         if (esp_dma.control&ESPCTRL_ENABLE_INT) {
        !           573:             set_interrupt(INT_SCSI, SET_INT);
        !           574:         }
        !           575:         
        !           576:         if (LOG_ESPCMD_LEVEL == LOG_WARN) {
        !           577:             printf("[ESP] Raise IRQ: state=");
        !           578:             switch (esp_state) {
        !           579:                 case DISCONNECTED: printf("disconnected"); break;
        !           580:                 case INITIATOR: printf("initiator"); break;
        !           581:                 case TARGET: printf("target"); break;
        !           582:                 default: printf("unknown"); break;
        !           583:             }
        !           584:             printf(", phase=");
        !           585:             switch (SCSIbus.phase&STAT_PHASE) {
        !           586:                 case PHASE_DO: printf("data out"); break;
        !           587:                 case PHASE_DI: printf("data in"); break;
        !           588:                 case PHASE_CD: printf("command"); break;
        !           589:                 case PHASE_ST: printf("status"); break;
        !           590:                 case PHASE_MI: printf("msg in"); break;
        !           591:                 case PHASE_MO: printf("msg out"); break;
        !           592:                 default: printf("unknown"); break;
        !           593:             }
        !           594:             if (status&STAT_TC) {
        !           595:                 printf(", transfer complete");
        !           596:             } else {
        !           597:                 printf(", transfer not complete");
        !           598:             }
        !           599:             printf(", sequence step=%i", seqstep);
        !           600:             printf(", interrupt status:\n");
        !           601:             if (intstatus&INTR_RST) printf("bus reset\n");
        !           602:             if (intstatus&INTR_BS) printf("bus service\n");
        !           603:             if (intstatus&INTR_DC) printf("disconnected\n");
        !           604:             if (intstatus&INTR_FC) printf("function complete\n");
        !           605:             if (intstatus&INTR_ILL) printf("illegal command\n");
        !           606:             if (intstatus&INTR_RESEL) printf("reselected\n");
        !           607:             if (intstatus&INTR_SEL) printf("selected\n");
        !           608:             if (intstatus&INTR_SELATN) printf("selected with ATN\n");
        !           609:         }
        !           610:     }
        !           611: }
        !           612: 
        !           613: void esp_lower_irq(void) {
        !           614:     if (status & STAT_INT) {
        !           615:         status &= ~STAT_INT;
        !           616:         
        !           617:         set_interrupt(INT_SCSI, RELEASE_INT);
        !           618:         
        !           619:         Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Lower IRQ\n");
        !           620:         
        !           621:         esp_finish_command();
        !           622:     }
        !           623: }
        !           624: 
        !           625: /* Functions */
        !           626: 
        !           627: /* Reset chip */
        !           628: void esp_reset_hard(void) {
        !           629:     Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Hard reset\n");
        !           630: 
        !           631:     clockconv = 0x02;
        !           632:     configuration &= ~0xF8; // clear chip test mode, parity enable, parity test, scsi request/int disable, slow cable mode
        !           633:     esp_fifo_clear();
        !           634:     syncperiod = 0x05;
        !           635:     syncoffset = 0x00;
        !           636:     status &= ~STAT_INT; // release interrupt
        !           637:     set_interrupt(INT_SCSI, RELEASE_INT);
        !           638:     intstatus = 0x00;
        !           639:     status &= ~(STAT_VGC | STAT_PE | STAT_GE); // clear transfer complete aka valid group code, parity error, gross error
        !           640:     esp_reset_soft();
        !           641:     esp_finish_command();
        !           642: }
        !           643: 
        !           644: 
        !           645: 
        !           646: void esp_reset_soft(void) {
        !           647:     status &= ~STAT_TC; /* clear transfer count zero */
        !           648:     
        !           649:     /* check, if this is complete */
        !           650:     mode_dma = 0;
        !           651:     esp_counter = 0; /* reset counter, but not actual registers! */
        !           652:     
        !           653:     seqstep = 0x00;
        !           654:     
        !           655:     /* writetranscountl, writetranscounth, selectbusid, selecttimeout are not initialized by reset */
        !           656: 
        !           657:     /* This part is "disconnect reset" */
        !           658:     esp_command_clear();
        !           659:     esp_state = DISCONNECTED;
        !           660: }
        !           661: 
        !           662: 
        !           663: /* Reset SCSI bus */
        !           664: void esp_bus_reset(void) {
        !           665:     
        !           666:     esp_reset_soft();
        !           667:     if (!(configuration & CFG1_RESREPT)) {
        !           668:         intstatus = INTR_RST;
        !           669:         SCSIbus.phase = PHASE_MI; /* CHECK: why message in phase? */
        !           670:         Log_Printf(LOG_ESPCMD_LEVEL,"[ESP] SCSI bus reset raising IRQ (configuration=$%02X)\n",configuration);
        !           671:         CycInt_AddRelativeInterruptUs(500, 0, INTERRUPT_ESP); /* CHECK: how is this delay defined? */
        !           672:     } else {
        !           673:         Log_Printf(LOG_ESPCMD_LEVEL,"[ESP] SCSI bus reset not interrupting (configuration=$%02X)\n",configuration);
        !           674:         esp_finish_command();
        !           675:     }
        !           676: }
        !           677: 
        !           678: 
        !           679: /* Flush FIFO */
        !           680: void esp_flush_fifo(void) {
        !           681:     esp_fifo_clear();
        !           682:     esp_finish_command();
        !           683: }
        !           684: 
        !           685: 
        !           686: /* Select with or without ATN */
        !           687: void esp_select(bool atn) {
        !           688:     int cmd_size;
        !           689:     Uint8 identify_msg = 0;
        !           690:     Uint8 commandbuf[SCSI_CDB_MAX_SIZE];
        !           691: 
        !           692:     seqstep = 0;
        !           693:     
        !           694:     /* First select our target */
        !           695:     Uint8 target = selectbusid & BUSID_DID; /* Get bus ID from register */
        !           696:     bool timeout = SCSIdisk_Select(target);
        !           697:     if (timeout) {
        !           698:         /* If a timeout occurs, generate disconnect interrupt */
        !           699:         intstatus = INTR_DC;
        !           700:         esp_command_clear();
        !           701:         esp_state = DISCONNECTED;
        !           702:         int seltout = (selecttimeout * 8192 * clockconv) / ESP_CLOCK_FREQ; /* timeout in microseconds */
        !           703:         Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Target %i, timeout after %i microseconds",target,seltout);
        !           704:         CycInt_AddRelativeInterruptUs(seltout, 0, INTERRUPT_ESP);
        !           705:         return;
        !           706:     }
        !           707:     
        !           708:     /* Next get our command */
        !           709:     if(mode_dma == 1) {
        !           710:         cmd_size = esp_counter;
        !           711:         Log_Printf(LOG_WARN, "[ESP] Select: Reading command using DMA, size %i byte (not implemented!)",cmd_size);
        !           712:         abort();
        !           713:     } else {
        !           714:         if (atn) { /* Read identify message from FIFO */
        !           715:             SCSIbus.phase = PHASE_MO;
        !           716:             seqstep = 1;
        !           717:             identify_msg = esp_fifo_read();
        !           718:             Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Reading message from FIFO");
        !           719:             Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Identify Message: $%02X",identify_msg);
        !           720:         }
        !           721:         
        !           722:         /* Read command from FIFO */
        !           723:         SCSIbus.phase = PHASE_CD;
        !           724:         seqstep = 3;
        !           725:         for (cmd_size = 0; cmd_size < SCSI_CDB_MAX_SIZE && fifoflags > 0; cmd_size++) {
        !           726:             commandbuf[cmd_size] = esp_fifo_read();
        !           727:         }
        !           728: 
        !           729:         Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Reading command from FIFO, size: %i byte",cmd_size);
        !           730:     }
        !           731:     
        !           732:     Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Target: %i",target);
        !           733: 
        !           734:     SCSIdisk_Receive_Command(commandbuf, identify_msg);
        !           735:     seqstep = 4;
        !           736:     esp_command_clear();
        !           737: 
        !           738:     intstatus = INTR_BS | INTR_FC;
        !           739:     
        !           740:     esp_state = INITIATOR;
        !           741:     CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           742: }
        !           743: 
        !           744: 
        !           745: /* DMA done: this is called as part of transfer info or transfer pad
        !           746:  * after DMA transfer has completed. */
        !           747: 
        !           748: enum {
        !           749:     ESP_IO_STATE_TRANSFERING,
        !           750:     ESP_IO_STATE_FLUSHING,
        !           751:     ESP_IO_STATE_DONE
        !           752: } esp_io_state;
        !           753: 
        !           754: bool esp_transfer_done(bool write) {
        !           755:     Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer done: ESP counter = %i, SCSI residual bytes: %i",
        !           756:                esp_counter,scsi_buffer.size);
        !           757:     
        !           758:     if (esp_counter == 0) { /* Transfer done */
        !           759:         intstatus = INTR_FC;
        !           760:         status |= STAT_TC;
        !           761:         CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           762:         return true;
        !           763:     } else if ((write && SCSIbus.phase!=PHASE_DI) || (!write && SCSIbus.phase!=PHASE_DO)) { /* Phase change detected */
        !           764:         esp_command_clear();
        !           765:         intstatus = INTR_BS;
        !           766:         CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           767:         return true;
        !           768:     } /* else continue transfering data, no interrupt */
        !           769:     return false;
        !           770: }
        !           771: 
        !           772: 
        !           773: /* Transfer information */
        !           774: void esp_transfer_info(void) {
        !           775:     if(mode_dma) {
        !           776:         esp_io_state=ESP_IO_STATE_TRANSFERING;
        !           777:         CycInt_AddRelativeInterruptUs(SCSI_Seek_Time() + SCSI_Sector_Time(), 100, INTERRUPT_ESP_IO);
        !           778:     } else {
        !           779:         Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] start PIO transfer");
        !           780:         switch (SCSIbus.phase) {
        !           781:             case PHASE_DI:
        !           782:                 esp_fifo_write(SCSIdisk_Send_Data());
        !           783:                 CycInt_AddRelativeInterruptCycles(20, INTERRUPT_ESP);
        !           784:                 break;
        !           785:             case PHASE_MI:
        !           786:                 CycInt_AddRelativeInterruptCycles(20, INTERRUPT_ESP);
        !           787:                 break;
        !           788:             case PHASE_ST:
        !           789:                 /* FIXME: What should happen here? */
        !           790:                 Log_Printf(LOG_WARN, "[ESP] Error! Transfer info status phase");
        !           791:                 CycInt_AddRelativeInterruptCycles(20, INTERRUPT_ESP);
        !           792:                 break;
        !           793:             default:
        !           794:                 Log_Printf(LOG_WARN, "[ESP] PIO transfer (unimplemented)");
        !           795:                 abort();
        !           796:                 break;
        !           797:         }
        !           798:     }
        !           799: }
        !           800: void ESP_IO_Handler(void) {
        !           801:     CycInt_AcknowledgeInterrupt();
        !           802:     
        !           803:     switch (esp_io_state) {
        !           804:         case ESP_IO_STATE_TRANSFERING:
        !           805:             switch (SCSIbus.phase) {
        !           806:                 case PHASE_DI:
        !           807:                     dma_esp_write_memory();
        !           808:                     if (esp_transfer_done(true)) {
        !           809:                         esp_io_state=ESP_IO_STATE_FLUSHING;
        !           810:                     }
        !           811:                     break;
        !           812:                 case PHASE_DO:
        !           813:                     dma_esp_read_memory();
        !           814:                     if (esp_transfer_done(false)) {
        !           815:                         return;
        !           816:                     }
        !           817:                     break;
        !           818:                     
        !           819:                 default:
        !           820:                     break;
        !           821:             }
        !           822:             break;
        !           823:         case ESP_IO_STATE_FLUSHING:
        !           824:             Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer done: Flushing DMA buffer.");
        !           825:             dma_esp_write_memory();
        !           826:             return;
        !           827:             
        !           828:         default:
        !           829:             Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer: Unkown state (%i).",esp_io_state);
        !           830:             return;
        !           831:     }
        !           832:     
        !           833:     CycInt_AddRelativeInterruptUs(100, 0, INTERRUPT_ESP_IO);
        !           834: }
        !           835: 
        !           836: 
        !           837: /* Transfer padding */
        !           838: void esp_transfer_pad(void) {
        !           839:     Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer padding, ESP counter: %i bytes, SCSI resid: %i bytes\n",
        !           840:                esp_counter, scsi_buffer.size);
        !           841: 
        !           842:     switch (SCSIbus.phase) {
        !           843:         case PHASE_DI:
        !           844:             while (SCSIbus.phase==PHASE_DI && esp_counter>0) {
        !           845:                 SCSIdisk_Send_Data();
        !           846:                 esp_counter--;
        !           847:             }
        !           848:             esp_transfer_done(true);
        !           849:             break;
        !           850:         case PHASE_DO:
        !           851:             while (SCSIbus.phase==PHASE_DO && esp_counter>0) {
        !           852:                 SCSIdisk_Receive_Data(0);
        !           853:                 esp_counter--;
        !           854:             }
        !           855:             esp_transfer_done(false);
        !           856:             break;
        !           857:             
        !           858:         default:
        !           859:             abort();
        !           860:             break;
        !           861:     }
        !           862: }
        !           863: 
        !           864: 
        !           865: /* Initiator command complete */
        !           866: void esp_initiator_command_complete(void) {
        !           867:     
        !           868:     if(mode_dma == 1) {
        !           869:         Log_Printf(LOG_WARN, "ESP initiator command complete via DMA not implemented!");
        !           870:         abort();
        !           871:     } else {
        !           872:         /* Receive status byte */
        !           873:         esp_fifo_write(SCSIdisk_Send_Status()); /* Disk sets phase to msg in after status send */
        !           874: 
        !           875:         if (SCSIbus.phase!=PHASE_MI) { /* Stop sequence if no phase change to msg in occured */
        !           876:             esp_command_clear();
        !           877:             intstatus = INTR_BS;
        !           878:             CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           879:             return;
        !           880:         }
        !           881:         
        !           882:         /* Receive message byte */
        !           883:         esp_fifo_write(SCSIdisk_Send_Message()); /* 0x00 = command complete */
        !           884:     }
        !           885: 
        !           886:     intstatus = INTR_FC;
        !           887:     CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           888: }
        !           889: 
        !           890: 
        !           891: /* Message accepted */
        !           892: void esp_message_accepted(void) {
        !           893:     SCSIbus.phase = PHASE_ST; /* set at the end of iccs? */
        !           894:     intstatus = INTR_BS;
        !           895:     esp_state = DISCONNECTED; /* CHECK: only disconnected if message was cmd complete? */
        !           896:     CycInt_AddRelativeInterruptUs(ESP_DELAY, 20, INTERRUPT_ESP);
        !           897: }
        !           898: 
        !           899: 
        !           900: 
        !           901: #if 0 /* this is for target commands! */
        !           902: /* Decode command to determine the command group and thus the
        !           903:  * length of the incoming command. Set "valid group code" bit
        !           904:  * in status register if the group is 0, 1, 5, 6, or 7 (group
        !           905:  * 2 is also valid on NCR53C90A).
        !           906:  */
        !           907: Uint8 scsi_command_group = (commandbuf[0] & 0xE0) >> 5;
        !           908: if(scsi_command_group < 3 || scsi_command_group > 4) {
        !           909:     if(ConfigureParams.System.nSCSI == NCR53C90 && scsi_command_group == 2) {
        !           910:         Log_Printf(LOG_WARN, "[ESP] Select: Invalid command group %i on NCR53C90\n", scsi_command_group);
        !           911:         status &= ~STAT_VGC;
        !           912:     } else {
        !           913:         status |= STAT_VGC;
        !           914:     }
        !           915: } else {
        !           916:     Log_Printf(LOG_WARN, "[ESP] Select: Invalid command group %i on NCR53C90A\n", scsi_command_group);
        !           917:     status &= ~STAT_VGC;
        !           918: }
        !           919: #endif

unix.superglobalmegacorp.com

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