📄 aha152x.c
字号:
ADDMSG(50); ADDMSG(8); printk("outbound SDTR: "); print_msg(&MSG(MSGLEN-5)); SYNCRATE=0x80; CURRENT_SC->SCp.phase |= in_sync; }#if defined(DEBUG_RACE) leave_driver("(SELDO) intr");#endif SETPORT(SCSIRATE, SYNCRATE&0x7f); SETPORT(SCSISIG, P_MSGO); SETPORT(SIMODE0, 0); SETPORT(SIMODE1, ENREQINIT|ENBUSFREE); SETBITS(DMACNTRL0, INTEN); return; } else aha152x_panic(shpnt, "neither timeout nor selection\007"); } else {#if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases)) printk("SELTO, ");#endif /* end selection attempt */ CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO); /* timeout */ SETPORT(SSTAT1, CLRSELTIMO); SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0); SETBITS(DMACNTRL0, INTEN);#if defined(DEBUG_RACE) leave_driver("(SELTO) intr");#endif if(CURRENT_SC->SCp.phase & aborted) {#if defined(DEBUG_ABORT) if(HOSTDATA(shpnt)->debug & debug_abort) printk("(ABORT) selection timeout, ");#endif HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR; HOSTDATA(shpnt)->abortion_complete++; } if(TESTLO(SSTAT0, SELINGO)) /* ARBITRATION not won */ aha152x_done(shpnt, DID_BUS_BUSY << 16); else /* ARBITRATION won, but SELECTION failed */ aha152x_done(shpnt, DID_NO_CONNECT << 16); return; } } /* enable interrupt, when target leaves current phase */ phase = getphase(shpnt); if(!(phase & ~P_MASK)) /* "real" phase */ SETPORT(SCSISIG, phase); SETPORT(SSTAT1, CLRPHASECHG); CURRENT_SC->SCp.phase = (CURRENT_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16); /* information transfer phase */ switch(phase) { case P_MSGO: /* MESSAGE OUT */ { int i, identify=0, abort=0;#if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES) if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgo|debug_phases)) printk("MESSAGE OUT, ");#endif if(MSGLEN==0) { ADDMSG(MESSAGE_REJECT);#if defined(DEBUG_MSGO) if(HOSTDATA(shpnt)->debug & debug_msgo) printk("unexpected MESSAGE OUT phase; rejecting, ");#endif } 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(); #if defined(DEBUG_MSGO) if(HOSTDATA(shpnt)->debug & debug_msgo) { int i; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -