📄 aha152x.c
字号:
printk("messages ("); for (i = 0; i < MSGLEN; i += print_msg(&MSG(i)), printk(" ")); printk("), "); }#endif for (i = 0; i < MSGLEN && TESTLO(SSTAT1, PHASEMIS); i++) {#if defined(DEBUG_MSGO) if (HOSTDATA(shpnt)->debug & debug_msgo) printk("%x ", MSG(i));#endif if (i == MSGLEN - 1) { /* Leave MESSAGE OUT after transfer */ SETPORT(SSTAT1, CLRATNO); } SETPORT(SCSIDAT, MSG(i)); make_acklow(shpnt); getphase(shpnt); if (MSG(i) == IDENTIFY(HOSTDATA(shpnt)->reconnect, CURRENT_SC->lun)) identify++; if (MSG(i) == ABORT) abort++; } MSGLEN = 0; if (identify) CURRENT_SC->SCp.phase |= sent_ident; if (abort) { /* revive abort(); abort() enables interrupts */ HOSTDATA(shpnt)->abort_result = SCSI_ABORT_SUCCESS; HOSTDATA(shpnt)->abortion_complete++; CURRENT_SC->SCp.phase &= ~(P_MASK << 16); /* exit */ SETBITS(DMACNTRL0, INTEN);#if defined(DEBUG_RACE) leave_driver("(ABORT) intr");#endif aha152x_done(shpnt, DID_ABORT << 16); return; } } break; case P_CMD: /* COMMAND phase */#if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES) if (HOSTDATA(shpnt)->debug & (debug_intr | debug_cmd | debug_phases)) printk("COMMAND, ");#endif if (!(CURRENT_SC->SCp.sent_command)) { int i; CLRBITS(SXFRCTL0, ENDMA); SETPORT(SIMODE0, 0); SETPORT(SIMODE1, ENPHASEMIS | ENREQINIT | ENBUSFREE); /* wait for data latch to become ready or a phase change */ while (TESTLO(DMASTAT, INTSTAT)) barrier(); for (i = 0; i < CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++) { SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]); make_acklow(shpnt); getphase(shpnt); } if (i < CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS)) aha152x_panic(shpnt, "target left COMMAND"); CURRENT_SC->SCp.sent_command++; } else aha152x_panic(shpnt, "Nothing to send while in COMMAND"); break; case P_MSGI: /* MESSAGE IN phase */ { int start_sync = 0;#if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES) if (HOSTDATA(shpnt)->debug & (debug_intr | debug_msgi | debug_phases)) printk("MESSAGE IN, ");#endif SETPORT(SXFRCTL0, CH1); SETPORT(SIMODE0, 0); SETPORT(SIMODE1, ENBUSFREE); while (phase == P_MSGI) { CURRENT_SC->SCp.Message = GETPORT(SCSIDAT); switch (CURRENT_SC->SCp.Message) { case DISCONNECT:#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) if (HOSTDATA(shpnt)->debug & (debug_msgi | debug_phases)) printk("target disconnected, ");#endif CURRENT_SC->SCp.Message = 0; CURRENT_SC->SCp.phase |= disconnected; if (!HOSTDATA(shpnt)->reconnect) aha152x_panic(shpnt, "target was not allowed to disconnect"); break; case COMMAND_COMPLETE:#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) if (HOSTDATA(shpnt)->debug & (debug_msgi | debug_phases)) printk("inbound message (COMMAND COMPLETE), ");#endif done++; break; case MESSAGE_REJECT: if (CURRENT_SC->SCp.phase & in_sync) { CURRENT_SC->SCp.phase &= ~in_sync; SYNCRATE = 0x80; printk("synchronous rejected, "); } else printk("inbound message (MESSAGE REJECT), ");#if defined(DEBUG_MSGI) if (HOSTDATA(shpnt)->debug & debug_msgi) printk("inbound message (MESSAGE REJECT), ");#endif break; case SAVE_POINTERS:#if defined(DEBUG_MSGI) if (HOSTDATA(shpnt)->debug & debug_msgi) printk("inbound message (SAVE DATA POINTERS), ");#endif break; case RESTORE_POINTERS:#if defined(DEBUG_MSGI) if (HOSTDATA(shpnt)->debug & debug_msgi) printk("inbound message (RESTORE DATA POINTERS), ");#endif break; case EXTENDED_MESSAGE: { char buffer[16]; int i;#if defined(DEBUG_MSGI) if (HOSTDATA(shpnt)->debug & debug_msgi) printk("inbound message (EXTENDED MESSAGE), ");#endif make_acklow(shpnt); if (getphase(shpnt) != P_MSGI) break; buffer[0] = EXTENDED_MESSAGE; buffer[1] = GETPORT(SCSIDAT); for (i = 0; i < buffer[1] && (make_acklow(shpnt), getphase(shpnt) == P_MSGI); i++) buffer[2 + i] = GETPORT(SCSIDAT);#if defined(DEBUG_MSGI) if (HOSTDATA(shpnt)->debug & debug_msgi) print_msg(buffer);#endif switch (buffer[2]) { case EXTENDED_SDTR: { long ticks; if (buffer[1] != 3) aha152x_panic(shpnt, "SDTR message length != 3"); if (!HOSTDATA(shpnt)->synchronous) break; printk("inbound SDTR: "); print_msg(buffer); ticks = (buffer[3] * 4 + 49) / 50; if (CURRENT_SC->SCp.phase & in_sync) { /* we initiated SDTR */ if (ticks > 9 || buffer[4] < 1 || buffer[4] > 8) aha152x_panic(shpnt, "received SDTR invalid"); SYNCRATE |= ((ticks - 2) << 4) + buffer[4]; } else if (ticks <= 9 && buffer[4] >= 1) { if (buffer[4] > 8) buffer[4] = 8; ADDMSG(EXTENDED_MESSAGE); ADDMSG(3); ADDMSG(EXTENDED_SDTR); if (ticks < 4) { ticks = 4; ADDMSG(50); } else ADDMSG(buffer[3]); ADDMSG(buffer[4]); printk("outbound SDTR: "); print_msg(&MSG(MSGLEN - 5)); CURRENT_SC->SCp.phase |= in_sync; SYNCRATE |= ((ticks - 2) << 4) + buffer[4]; start_sync++; } else { /* requested SDTR is too slow, do it asynchronously */ ADDMSG(MESSAGE_REJECT); SYNCRATE = 0; } SETPORT(SCSIRATE, SYNCRATE & 0x7f); } break; case EXTENDED_MODIFY_DATA_POINTER: case EXTENDED_EXTENDED_IDENTIFY: case EXTENDED_WDTR: default: ADDMSG(MESSAGE_REJECT); break; } } break; default: printk("unsupported inbound message %x, ", CURRENT_SC->SCp.Message); break; } make_acklow(shpnt); phase = getphase(shpnt); } if (start_sync) CURRENT_SC->SCp.phase |= in_sync; else CURRENT_SC->SCp.phase &= ~in_sync; if (MSGLEN > 0) SETPORT(SCSISIG, P_MSGI | ATNO); /* clear SCSI fifo on BUSFREE */ if (phase == P_BUSFREE) SETPORT(SXFRCTL0, CH1 | CLRCH1); if (CURRENT_SC->SCp.phase & disconnected) { save_flags(flags); cli();#if defined(DEBUG_QUEUES) if (HOSTDATA(shpnt)->debug & debug_queues) printk("d+, ");#endif append_SC(&DISCONNECTED_SC, CURRENT_SC); CURRENT_SC->SCp.phase |= 1 << 16; CURRENT_SC = NULL; restore_flags(flags); SETBITS(SCSISEQ, ENRESELI); SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); SETBITS(DMACNTRL0, INTEN); return; } } break; case P_STATUS: /* STATUS IN phase */#if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) if (HOSTDATA(shpnt)->debug & (debug_status | debug_intr | debug_phases)) printk("STATUS, ");#endif SETPORT(SXFRCTL0, CH1); SETPORT(SIMODE0, 0); SETPORT(SIMODE1, ENREQINIT | ENBUSFREE); if (TESTHI(SSTAT1, PHASEMIS)) printk("aha152x: passing STATUS phase"); CURRENT_SC->SCp.Status = GETPORT(SCSIBUS); make_acklow(shpnt); getphase(shpnt);#if defined(DEBUG_STATUS) if (HOSTDATA(shpnt)->debug & debug_status) { printk("inbound status "); print_status(CURRENT_SC->SCp.Status); printk(", "); }#endif break; case P_DATAI: /* DATA IN phase */ { int fifodata, data_count, done;#if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) if (HOSTDATA(shpnt)->debug & (debug_datai | debug_intr | debug_phases)) printk("DATA IN, ");#endif#if 0 if (GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL | SFCNT)) printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n", GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL | SFCNT));#endif /* reset host fifo */ SETPORT(DMACNTRL0, RSTFIFO); SETPORT(DMACNTRL0, RSTFIFO | ENDMA); SETPORT(SXFRCTL0, CH1 | SCSIEN | DMAEN); SETPORT(SIMODE0, 0); SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE); /* done is set when the FIFO is empty after the target left DATA IN */ done = 0; /* while the target stays in DATA to transfer data */ while (!done) {#if defined(DEBUG_DATAI) if (HOSTDATA(shpnt)->debug & debug_datai) printk("expecting data, ");#endif /* wait for PHASEMIS or full FIFO */ while (TESTLO(DMASTAT, DFIFOFULL | INTSTAT)) barrier();#if defined(DEBUG_DATAI) if (HOSTDATA(shpnt)->debug & debug_datai) printk("ok, ");#endif if (TESTHI(DMASTAT, DFIFOFULL)) fifodata = GETPORT(FIFOSTAT); else { /* wait for SCSI fifo to get empty */ while (TESTLO(SSTAT2, SEMPTY)) barrier(); /* rest of data in FIFO */ fifodata = GETPORT(FIFOSTAT);#if defined(DEBUG_DATAI) if (HOSTDATA(shpnt)->debug & debug_datai) printk("last transfer, ");#endif done = 1; }#if defined(DEBUG_DATAI) if (HOSTDATA(shpnt)->debug & debug_datai) printk("fifodata=%d, ", fifodata);#endif while (fifodata && CURRENT_SC->SCp.this_residual) { data_count = fifodata; /* limit data transfer to size of first sg buffer */ if (data_count > CURRENT_SC->SCp.this_residual) data_count = CURRENT_SC->SCp.this_residual; fifodata -= data_count;#if defined(DEBUG_DATAI) if (HOSTDATA(shpnt)->debug & debug_datai) printk("data_count=%d, ", data_count);#endif if (data_count & 1) { /* get a single byte in byte mode */ SETBITS(DMACNTRL0, _8BIT); *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); CURRENT_SC->SCp.this_residual--; } if (data_count > 1) { CLRBITS(DMACNTRL0, _8BIT); data_count >>= 1; /* Number of words */ insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);#if defined(DEBUG_DATAI) if (HOSTDATA(shpnt)->debug & debug_datai) /* show what comes with the last transfer */ if (done) {#if 0 int i; unsigned char *data;#endif printk("data on last transfer (%d bytes) ", 2 * data_count);#if 0 printk("data on last transfer (%d bytes: ", 2 * data_count); data = (unsigned char *) CURRENT_SC->SCp.ptr; for (i = 0; i < 2 * data_count; i++) printk("%2x ", *data++); printk("), ");#endif }#endif CURRENT_SC->SCp.ptr += 2 * data_count; CURRENT_SC->SCp.this_residual -= 2 * data_count; } /* if this buffer is full and there are more buffers left */ if (!CURRENT_SC->SCp.this_residual && CURRENT_SC->SCp.buffers_residual) { /* advance to next buffer */ CURRENT_SC->SCp.buffers_residual--; CURRENT_SC->SCp.buffer++; CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; } } /* * FIFO should be empty */ if (fifodata > 0) { printk("aha152x: more data than expected (%d bytes)\n", GETPORT(FIFOSTAT)); SETBITS(DMACNTRL0, _8BIT); printk("aha152x: data ("); while (fifodata--) printk("%2x ", GETPORT(DATAPORT)); printk(")\n"); }#if defined(DEBUG_DATAI) if (HOSTDATA(shpnt)->debug & debug_datai) if (!fifodata) printk("fifo empty, "); else printk("something left in fifo, ");#endif }#if defined(DEBUG_DATAI) if ((HOSTDATA(shpnt)->debug & debug_datai) && (CURRENT_SC->SCp.buffers_residual || CURRENT_SC->SCp.this_residual)) printk("left buffers (buffers=%d, bytes=%d), ", CURRENT_SC->SCp.buffers_residual, CURRENT_SC->SCp.this_residual);#endif /* transfer can be considered ended, when SCSIEN reads back zero */ CLRBITS(SXFRCTL0, SCSIEN | DMAEN); while (TESTHI(SXFRCTL0, SCSIEN)) barrier(); CLRBITS(DMACNTRL0, ENDMA);#if defined(DEBUG_DATAI) || defined(DEBUG_INTR) if (HOSTDATA(shpnt)->debug & (debug_datai | debug_intr)) printk("got %d bytes, ", GETSTCNT());#endif CURRENT_SC->SCp.have_data_in++; } break; case P_DATAO: /* DATA OUT phase */ { int data_count;#if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES) if (HOSTDATA(shpnt)->debug & (debug_datao | debug_intr | debug_phases)) printk("DATA OUT, ");#endif#if defined(DEBUG_DATAO) if (HOSTDATA(sh
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -