|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.