|
|
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:
1.1.1.2 ! root 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 */
1.1 root 18:
19:
20: #define IO_SEG_MASK 0x1FFFF
21:
22: typedef enum {
23: DISCONNECTED,
24: INITIATOR,
1.1.1.2 ! root 25: TARGET
1.1 root 26: } SCSI_STATE;
27:
1.1.1.2 ! root 28: SCSI_STATE esp_state;
1.1 root 29:
1.1.1.2 ! root 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);
1.1 root 45:
46: /* ESP Registers */
47: Uint8 writetranscountl;
48: Uint8 writetranscounth;
1.1.1.2 ! root 49: Uint8 fifo[ESP_FIFO_SIZE];
! 50: Uint8 command[2];
1.1 root 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:
1.1.1.2 ! root 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:
1.1 root 139: /* ESP Status Variables */
140: Uint8 mode_dma;
141:
1.1.1.2 ! root 142: /* Experimental */
! 143: #define ESP_CLOCK_FREQ 20 /* ESP is clocked at 20 MHz */
! 144: #define ESP_DELAY 20000 /* Standard wait time for ESP interrupt (except bus reset and selection timeout) */
1.1 root 145:
146:
1.1.1.2 ! root 147: /* ESP DMA control and status registers */
1.1 root 148:
1.1.1.2 ! root 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];
1.1 root 157:
1.1.1.2 ! root 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: }
1.1 root 165: }
1.1.1.2 ! root 166: if (esp_dma.control&ESPCTRL_CHIP_TYPE) {
! 167: Log_Printf(LOG_ESPDMA_LEVEL, "SCSI controller is WD33C92\n");
1.1 root 168: } else {
1.1.1.2 ! root 169: Log_Printf(LOG_ESPDMA_LEVEL, "SCSI controller is NCR53C90\n");
1.1 root 170: }
1.1.1.2 ! root 171: if (esp_dma.control&ESPCTRL_RESET) {
! 172: Log_Printf(LOG_ESPDMA_LEVEL, "reset SCSI controller\n");
1.1 root 173: esp_reset_hard();
174: }
1.1.1.2 ! root 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");
1.1 root 179: }
1.1.1.2 ! root 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");
1.1 root 197: break;
1.1.1.2 ! root 198: case ESPCTRL_CLK12MHz:
! 199: Log_Printf(LOG_ESPDMA_LEVEL, "12.5 MHz clock\n");
1.1 root 200: break;
1.1.1.2 ! root 201: case ESPCTRL_CLK16MHz:
! 202: Log_Printf(LOG_ESPDMA_LEVEL, "16.6 MHz clock\n");
1.1 root 203: break;
1.1.1.2 ! root 204: case ESPCTRL_CLK20MHz:
! 205: Log_Printf(LOG_ESPDMA_LEVEL, "20 MHz clock\n");
1.1 root 206: break;
207: default:
208: break;
209: }
210: }
211:
1.1.1.2 ! root 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());
1.1 root 215: }
216:
1.1.1.2 ! root 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];
1.1 root 220: }
221:
1.1.1.2 ! root 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: }
1.1 root 231:
232: /* ESP Registers */
233:
1.1.1.2 ! root 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());
1.1 root 237: }
238:
1.1.1.2 ! root 239: void ESP_TransCountL_Write(void) {
1.1 root 240: writetranscountl=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
1.1.1.2 ! root 241: Log_Printf(LOG_ESPREG_LEVEL,"ESP TransCountL write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1.1 root 242: }
243:
1.1.1.2 ! root 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());
1.1 root 247: }
248:
1.1.1.2 ! root 249: void ESP_TransCountH_Write(void) {
1.1 root 250: writetranscounth=IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
1.1.1.2 ! root 251: Log_Printf(LOG_ESPREG_LEVEL,"ESP TransCountH write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1.1 root 252: }
253:
1.1.1.2 ! root 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;
1.1 root 376: } else {
1.1.1.2 ! root 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;
1.1 root 389: }
390:
1.1.1.2 ! root 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: }
1.1 root 403:
1.1.1.2 ! root 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]);
1.1 root 415: }
416: }
417:
1.1.1.2 ! root 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: }
1.1 root 424: }
425:
1.1.1.2 ! root 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;
1.1 root 438:
1.1.1.2 ! root 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_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, 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: }
1.1 root 459: status &= ~STAT_TC;
460: mode_dma = 1;
461: } else {
462: mode_dma = 0;
463: }
464:
1.1.1.2 ! root 465: switch (cmd & CMD_CMD) {
1.1 root 466: /* Miscellaneous */
467: case CMD_NOP:
1.1.1.2 ! root 468: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: NOP\n");
! 469: esp_finish_command();
1.1 root 470: break;
471: case CMD_FLUSH:
1.1.1.2 ! root 472: Log_Printf(LOG_ESPCMD_LEVEL,"ESP Command: flush FIFO\n");
1.1 root 473: esp_flush_fifo();
474: break;
475: case CMD_RESET:
1.1.1.2 ! root 476: Log_Printf(LOG_ESPCMD_LEVEL,"ESP Command: reset chip\n");
1.1 root 477: esp_reset_hard();
478: break;
479: case CMD_BUSRESET:
1.1.1.2 ! root 480: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: reset SCSI bus\n");
! 481: esp_bus_reset();
1.1 root 482: break;
483: /* Disconnected */
1.1.1.2 ! root 484: case CMD_RESEL:
! 485: Log_Printf(LOG_WARN, "ESP Command: reselect sequence\n");
! 486: abort();
! 487: break;
1.1 root 488: case CMD_SEL:
1.1.1.2 ! root 489: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: select without ATN sequence\n");
! 490: esp_select(false);
1.1 root 491: break;
492: case CMD_SELATN:
1.1.1.2 ! root 493: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: select with ATN sequence\n");
! 494: esp_select(true);
1.1 root 495: break;
496: case CMD_SELATNS:
1.1.1.2 ! root 497: Log_Printf(LOG_WARN, "ESP Command: select with ATN and stop sequence\n");
! 498: abort();
1.1 root 499: break;
500: case CMD_ENSEL:
1.1.1.2 ! root 501: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: enable selection/reselection\n");
! 502: esp_finish_command(); /* Our disk doesn't do reselections */
1.1 root 503: break;
504: case CMD_DISSEL:
1.1.1.2 ! root 505: Log_Printf(LOG_WARN, "ESP Command: disable selection/reselection\n");
! 506: abort();
1.1 root 507: break;
508: /* Initiator */
509: case CMD_TI:
1.1.1.2 ! root 510: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: transfer information\n");
! 511: esp_transfer_info();
1.1 root 512: break;
513: case CMD_ICCS:
1.1.1.2 ! root 514: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: initiator command complete sequence\n");
! 515: esp_initiator_command_complete();
1.1 root 516: break;
517: case CMD_MSGACC:
1.1.1.2 ! root 518: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: message accepted\n");
! 519: esp_message_accepted();
! 520: break;
1.1 root 521: case CMD_PAD:
1.1.1.2 ! root 522: Log_Printf(LOG_ESPCMD_LEVEL, "ESP Command: transfer pad\n");
! 523: esp_transfer_pad();
1.1 root 524: break;
525: case CMD_SATN:
1.1.1.2 ! root 526: Log_Printf(LOG_WARN, "ESP Command: set ATN\n");
! 527: abort();
1.1 root 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:
1.1.1.2 ! root 540: Log_Printf(LOG_WARN, "ESP Command: Target commands not emulated!\n");
! 541: abort();
1.1 root 542: break;
543: case CMD_DIS:
1.1.1.2 ! root 544: Log_Printf(LOG_WARN, "ESP Command: DISCONNECT not emulated!\n");
! 545: abort();
! 546: SCSIbus.phase = PHASE_ST;
! 547: intstatus = INTR_DC;
1.1 root 548: seqstep = SEQ_0;
549: break;
550:
551: default:
552: Log_Printf(LOG_WARN, "ESP Command: Illegal command!\n");
1.1.1.2 ! root 553: esp_command_clear();
1.1 root 554: intstatus |= INTR_ILL;
1.1.1.2 ! root 555: CycInt_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, INTERRUPT_ESP);
1.1 root 556: break;
557: }
558: }
559:
560:
1.1.1.2 ! root 561: /* This is the handler function for ESP delayed interrupts */
! 562: void ESP_InterruptHandler(void) {
! 563: CycInt_AcknowledgeInterrupt();
! 564: esp_raise_irq();
1.1 root 565: }
566:
567:
1.1.1.2 ! root 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: }
1.1 root 611: }
612:
1.1.1.2 ! root 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: }
1.1 root 623: }
624:
625: /* Functions */
626:
1.1.1.2 ! root 627: /* Reset chip */
1.1 root 628: void esp_reset_hard(void) {
1.1.1.2 ! root 629: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Hard reset\n");
! 630:
1.1 root 631: clockconv = 0x02;
632: configuration &= ~0xF8; // clear chip test mode, parity enable, parity test, scsi request/int disable, slow cable mode
1.1.1.2 ! root 633: esp_fifo_clear();
1.1 root 634: syncperiod = 0x05;
635: syncoffset = 0x00;
1.1.1.2 ! root 636: status &= ~STAT_INT; // release interrupt
! 637: set_interrupt(INT_SCSI, RELEASE_INT);
1.1 root 638: intstatus = 0x00;
1.1.1.2 ! root 639: status &= ~(STAT_VGC | STAT_PE | STAT_GE); // clear transfer complete aka valid group code, parity error, gross error
1.1 root 640: esp_reset_soft();
1.1.1.2 ! root 641: esp_finish_command();
1.1 root 642: }
643:
1.1.1.2 ! root 644:
! 645:
1.1 root 646: void esp_reset_soft(void) {
1.1.1.2 ! root 647: status &= ~STAT_TC; /* clear transfer count zero */
1.1 root 648:
1.1.1.2 ! root 649: /* check, if this is complete */
1.1 root 650: mode_dma = 0;
1.1.1.2 ! root 651: esp_counter = 0; /* reset counter, but not actual registers! */
! 652:
1.1 root 653: seqstep = 0x00;
1.1.1.2 ! root 654:
! 655: /* writetranscountl, writetranscounth, selectbusid, selecttimeout are not initialized by reset */
1.1 root 656:
1.1.1.2 ! root 657: /* This part is "disconnect reset" */
! 658: esp_command_clear();
! 659: esp_state = DISCONNECTED;
1.1 root 660: }
661:
662:
1.1.1.2 ! root 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: int wait = (ConfigureParams.System.nCpuLevel==3)?400:5440;
! 672: CycInt_AddRelativeInterrupt(wait*(32/ConfigureParams.System.nCpuFreq), INT_CPU_CYCLE, INTERRUPT_ESP); /* CHECK: how is this delay defined? */
! 673: } else {
! 674: Log_Printf(LOG_ESPCMD_LEVEL,"[ESP] SCSI bus reset not interrupting (configuration=$%02X)\n",configuration);
! 675: esp_finish_command();
1.1 root 676: }
677: }
678:
1.1.1.2 ! root 679:
! 680: /* Flush FIFO */
1.1 root 681: void esp_flush_fifo(void) {
1.1.1.2 ! root 682: esp_fifo_clear();
! 683: esp_finish_command();
1.1 root 684: }
685:
1.1.1.2 ! root 686:
! 687: /* Select with or without ATN */
! 688: void esp_select(bool atn) {
! 689: int cmd_size;
! 690: Uint8 identify_msg = 0;
! 691: Uint8 commandbuf[SCSI_CDB_MAX_SIZE];
! 692:
! 693: seqstep = 0;
! 694:
! 695: /* First select our target */
! 696: Uint8 target = selectbusid & BUSID_DID; /* Get bus ID from register */
! 697: bool timeout = SCSIdisk_Select(target);
! 698: if (timeout) {
! 699: /* If a timeout occurs, generate disconnect interrupt */
! 700: intstatus = INTR_DC;
! 701: esp_command_clear();
! 702: esp_state = DISCONNECTED;
! 703: int seltout = (selecttimeout * 8192 * clockconv) / ESP_CLOCK_FREQ; /* timeout in microseconds */
! 704: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Target %i, timeout after %i microseconds",target,seltout);
! 705: CycInt_AddRelativeInterrupt(seltout/**ConfigureParams.System.nCpuFreq*/, INT_CPU_CYCLE, INTERRUPT_ESP);
! 706: return;
! 707: }
1.1 root 708:
1.1.1.2 ! root 709: /* Next get our command */
1.1 root 710: if(mode_dma == 1) {
1.1.1.2 ! root 711: cmd_size = esp_counter;
! 712: Log_Printf(LOG_WARN, "[ESP] Select: Reading command using DMA, size %i byte (not implemented!)",cmd_size);
! 713: abort();
1.1 root 714: } else {
1.1.1.2 ! root 715: if (atn) { /* Read identify message from FIFO */
! 716: SCSIbus.phase = PHASE_MO;
! 717: seqstep = 1;
! 718: identify_msg = esp_fifo_read();
! 719: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Reading message from FIFO");
! 720: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Identify Message: $%02X",identify_msg);
! 721: }
1.1 root 722:
1.1.1.2 ! root 723: /* Read command from FIFO */
! 724: SCSIbus.phase = PHASE_CD;
! 725: seqstep = 3;
! 726: for (cmd_size = 0; cmd_size < SCSI_CDB_MAX_SIZE && fifoflags > 0; cmd_size++) {
! 727: commandbuf[cmd_size] = esp_fifo_read();
! 728: }
! 729:
! 730: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Reading command from FIFO, size: %i byte",cmd_size);
1.1 root 731: }
732:
1.1.1.2 ! root 733: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Select: Target: %i",target);
1.1 root 734:
1.1.1.2 ! root 735: SCSIdisk_Receive_Command(commandbuf, identify_msg);
! 736: seqstep = 4;
! 737: esp_command_clear();
1.1 root 738:
1.1.1.2 ! root 739: intstatus = INTR_BS | INTR_FC;
1.1 root 740:
1.1.1.2 ! root 741: esp_state = INITIATOR;
! 742: CycInt_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, INTERRUPT_ESP);
1.1 root 743: }
744:
745:
1.1.1.2 ! root 746: /* DMA done: this is called as part of transfer info or transfer pad
! 747: * after DMA transfer has completed. */
1.1 root 748:
1.1.1.2 ! root 749: enum {
! 750: ESP_IO_STATE_TRANSFERING,
! 751: ESP_IO_STATE_FLUSHING,
! 752: ESP_IO_STATE_DONE
! 753: } esp_io_state;
1.1 root 754:
1.1.1.2 ! root 755: bool esp_transfer_done(bool write) {
! 756: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer done: ESP counter = %i, SCSI residual bytes: %i",
! 757: esp_counter,scsi_buffer.size);
1.1 root 758:
1.1.1.2 ! root 759: if (esp_counter == 0) { /* Transfer done */
! 760: intstatus = INTR_FC;
! 761: status |= STAT_TC;
! 762: CycInt_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, INTERRUPT_ESP);
! 763: return true;
! 764: } else if ((write && SCSIbus.phase!=PHASE_DI) || (!write && SCSIbus.phase!=PHASE_DO)) { /* Phase change detected */
! 765: esp_command_clear();
! 766: intstatus = INTR_BS;
! 767: CycInt_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, INTERRUPT_ESP);
! 768: return true;
! 769: } /* else continue transfering data, no interrupt */
! 770: return false;
! 771: }
1.1 root 772:
1.1.1.2 ! root 773:
! 774: /* Transfer information */
! 775: void esp_transfer_info(void) {
! 776: if(mode_dma) {
! 777: esp_io_state=ESP_IO_STATE_TRANSFERING;
! 778: CycInt_AddRelativeInterrupt(10000, INT_CPU_CYCLE, INTERRUPT_ESP_IO);
! 779: } else {
! 780: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] start PIO transfer");
! 781: switch (SCSIbus.phase) {
! 782: case PHASE_DI:
! 783: esp_fifo_write(SCSIdisk_Send_Data());
! 784: CycInt_AddRelativeInterrupt(500, INT_CPU_CYCLE, INTERRUPT_ESP);
! 785: break;
! 786: case PHASE_MI:
! 787: CycInt_AddRelativeInterrupt(500, INT_CPU_CYCLE, INTERRUPT_ESP);
! 788: break;
! 789: case PHASE_ST:
! 790: /* FIXME: What should happen here? */
! 791: Log_Printf(LOG_WARN, "[ESP] Error! Transfer info status phase");
! 792: CycInt_AddRelativeInterrupt(500, INT_CPU_CYCLE, INTERRUPT_ESP);
! 793: break;
! 794: default:
! 795: Log_Printf(LOG_WARN, "[ESP] PIO transfer (unimplemented)");
! 796: abort();
! 797: break;
1.1 root 798: }
799: }
1.1.1.2 ! root 800: }
! 801: void ESP_IO_Handler(void) {
! 802: CycInt_AcknowledgeInterrupt();
1.1 root 803:
1.1.1.2 ! root 804: switch (esp_io_state) {
! 805: case ESP_IO_STATE_TRANSFERING:
! 806: switch (SCSIbus.phase) {
! 807: case PHASE_DI:
! 808: dma_esp_write_memory();
! 809: if (esp_transfer_done(true)) {
! 810: esp_io_state=ESP_IO_STATE_FLUSHING;
! 811: }
! 812: break;
! 813: case PHASE_DO:
! 814: dma_esp_read_memory();
! 815: if (esp_transfer_done(false)) {
! 816: return;
! 817: }
! 818: break;
! 819:
! 820: default:
! 821: break;
! 822: }
! 823: break;
! 824: case ESP_IO_STATE_FLUSHING:
! 825: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer done: Flushing DMA buffer.");
! 826: dma_esp_write_memory();
! 827: return;
! 828:
! 829: default:
! 830: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer: Unkown state (%i).",esp_io_state);
! 831: return;
! 832: }
1.1 root 833:
1.1.1.2 ! root 834: CycInt_AddRelativeInterrupt(10000, INT_CPU_CYCLE, INTERRUPT_ESP_IO);
1.1 root 835: }
836:
837:
1.1.1.2 ! root 838: /* Transfer padding */
! 839: void esp_transfer_pad(void) {
! 840: Log_Printf(LOG_ESPCMD_LEVEL, "[ESP] Transfer padding, ESP counter: %i bytes, SCSI resid: %i bytes\n",
! 841: esp_counter, scsi_buffer.size);
! 842:
! 843: switch (SCSIbus.phase) {
! 844: case PHASE_DI:
! 845: while (SCSIbus.phase==PHASE_DI && esp_counter>0) {
! 846: SCSIdisk_Send_Data();
! 847: esp_counter--;
! 848: }
! 849: esp_transfer_done(true);
! 850: break;
! 851: case PHASE_DO:
! 852: while (SCSIbus.phase==PHASE_DO && esp_counter>0) {
! 853: SCSIdisk_Receive_Data(0);
! 854: esp_counter--;
! 855: }
! 856: esp_transfer_done(false);
! 857: break;
! 858:
! 859: default:
! 860: abort();
! 861: break;
1.1 root 862: }
863: }
864:
865:
1.1.1.2 ! root 866: /* Initiator command complete */
! 867: void esp_initiator_command_complete(void) {
1.1 root 868:
1.1.1.2 ! root 869: if(mode_dma == 1) {
! 870: Log_Printf(LOG_WARN, "ESP initiator command complete via DMA not implemented!");
1.1 root 871: abort();
1.1.1.2 ! root 872: } else {
! 873: /* Receive status byte */
! 874: esp_fifo_write(SCSIdisk_Send_Status()); /* Disk sets phase to msg in after status send */
1.1 root 875:
1.1.1.2 ! root 876: if (SCSIbus.phase!=PHASE_MI) { /* Stop sequence if no phase change to msg in occured */
! 877: esp_command_clear();
! 878: intstatus = INTR_BS;
! 879: CycInt_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, INTERRUPT_ESP);
! 880: return;
1.1 root 881: }
1.1.1.2 ! root 882:
! 883: /* Receive message byte */
! 884: esp_fifo_write(SCSIdisk_Send_Message()); /* 0x00 = command complete */
1.1 root 885: }
1.1.1.2 ! root 886:
! 887: intstatus = INTR_FC;
! 888: CycInt_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, INTERRUPT_ESP);
1.1 root 889: }
890:
1.1.1.2 ! root 891:
! 892: /* Message accepted */
! 893: void esp_message_accepted(void) {
! 894: SCSIbus.phase = PHASE_ST; /* set at the end of iccs? */
1.1 root 895: intstatus = INTR_BS;
1.1.1.2 ! root 896: esp_state = DISCONNECTED; /* CHECK: only disconnected if message was cmd complete? */
! 897: CycInt_AddRelativeInterrupt(ESP_DELAY, INT_CPU_CYCLE, INTERRUPT_ESP);
1.1 root 898: }
899:
900:
901:
1.1.1.2 ! root 902: #if 0 /* this is for target commands! */
! 903: /* Decode command to determine the command group and thus the
! 904: * length of the incoming command. Set "valid group code" bit
! 905: * in status register if the group is 0, 1, 5, 6, or 7 (group
! 906: * 2 is also valid on NCR53C90A).
! 907: */
! 908: Uint8 scsi_command_group = (commandbuf[0] & 0xE0) >> 5;
! 909: if(scsi_command_group < 3 || scsi_command_group > 4) {
! 910: if(ConfigureParams.System.nSCSI == NCR53C90 && scsi_command_group == 2) {
! 911: Log_Printf(LOG_WARN, "[ESP] Select: Invalid command group %i on NCR53C90\n", scsi_command_group);
! 912: status &= ~STAT_VGC;
! 913: } else {
! 914: status |= STAT_VGC;
1.1 root 915: }
1.1.1.2 ! root 916: } else {
! 917: Log_Printf(LOG_WARN, "[ESP] Select: Invalid command group %i on NCR53C90A\n", scsi_command_group);
! 918: status &= ~STAT_VGC;
1.1 root 919: }
1.1.1.2 ! root 920: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.