?? aha152x.c
字號:
SETPORT( DMACNTRL0, INTEN ); } return 0;}/* * Return the "logical geometry" */int aha152x_biosparam( int size, int dev, int *info_array ){#if defined(DEBUG_RACE) enter_driver("biosparam");#else#if defined(DEBUG_BIOSPARAM) printk("\naha152x: biosparam(), ");#endif#endif#if defined(DEBUG_BIOSPARAM) printk("dev=%x, size=%d, ", dev, size);#endif /* I took this from other SCSI drivers, since it provides the correct data for my devices. */ info_array[0]=64; info_array[1]=32; info_array[2]=size>>11;#if defined(DEBUG_BIOSPARAM) printk("bios geometry: head=%d, sec=%d, cyl=%d\n", info_array[0], info_array[1], info_array[2]); printk("WARNING: check, if the bios geometry is correct.\n");#endif#if defined(DEBUG_RACE) leave_driver("biosparam");#endif return 0;}/* * Internal done function */void aha152x_done( int error ){ Scsi_Cmnd *done_SC;#if defined(DEBUG_DONE) printk("\naha152x: done(), "); disp_ports();#endif if (current_SC) {#if defined(DEBUG_DONE) printk("done(%x), ", error);#endif cli(); done_SC = current_SC; current_SC = NULL; /* turn led off, when no commands are in the driver */ commands--; if(!commands) SETPORT( PORTA, 0 ); /* turn led off */#if defined(DEBUG_QUEUES) printk("ok (%d), ", commands);#endif sti(); SETPORT(SIMODE0, disconnected_SC ? ENSELDI : 0 ); SETPORT(SIMODE1, issue_SC ? ENBUSFREE : 0);#if defined(DEBUG_PHASES) printk("BUS FREE loop, ");#endif while( TESTLO( SSTAT1, BUSFREE ) ) ;#if defined(DEBUG_PHASES) printk("BUS FREE\n");#endif done_SC->result = error; if(done_SC->scsi_done) {#if defined(DEBUG_DONE) printk("calling scsi_done, ");#endif done_SC->scsi_done( done_SC );#if defined(DEBUG_DONE) printk("done returned, ");#endif } else panic( "aha152x: current_SC->scsi_done() == NULL" ); } else aha152x_panic( "done() called outside of command" );}/* * Interrupts handler (main routine of the driver) */void aha152x_intr( int irqno ){ int done=0, phase;#if defined(DEBUG_RACE) enter_driver("intr");#else#if defined(DEBUG_INTR) printk("\naha152x: intr(), ");#endif#endif /* no more interrupts from the controller, while we busy. INTEN has to be restored, when we're ready to leave intr(). To avoid race conditions we have to return immediately afterwards. */ CLRBITS( DMACNTRL0, INTEN); sti(); /* disconnected target is trying to reconnect. Only possible, if we have disconnected nexuses and nothing is occuping the bus. */ if( TESTHI( SSTAT0, SELDI ) && disconnected_SC && ( !current_SC || ( current_SC->SCp.phase & in_selection ) ) ) { int identify_msg, target, i; /* Avoid conflicts when a target reconnects while we are trying to connect to another. */ if(current_SC) {#if defined(DEBUG_QUEUES) printk("i+, ");#endif cli(); append_SC( &issue_SC, current_SC); current_SC=NULL; sti(); } /* disable sequences */ SETPORT( SCSISEQ, 0 ); SETPORT( SSTAT0, CLRSELDI ); SETPORT( SSTAT1, CLRBUSFREE );#if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES) printk("reselected, ");#endif i = GETPORT(SELID) & ~(1 << this_host); target=0; if(i) for( ; (i & 1)==0; target++, i>>=1) ; else aha152x_panic("reconnecting target unknown");#if defined(DEBUG_QUEUES) printk("SELID=%02x, target=%d, ", GETPORT(SELID), target );#endif SETPORT( SCSIID, (this_host << OID_) | target ); SETPORT( SCSISEQ, ENRESELI ); if(TESTLO( SSTAT0, SELDI )) aha152x_panic("RESELI failed"); SETPORT( SCSISIG, P_MSGI ); /* Get identify message */ if((i=getphase())!=P_MSGI) { printk("target doesn't enter MSGI to identify (phase=%02x)\n", i); aha152x_panic("unknown lun"); } SETPORT( SCSISEQ, 0 ); SETPORT( SXFRCTL0, CH1); identify_msg = GETPORT(SCSIBUS); if(!(identify_msg & IDENTIFY_BASE)) { printk("target=%d, inbound message (%02x) != IDENTIFY\n", target, identify_msg); aha152x_panic("unknown lun"); } make_acklow(); getphase();#if defined(DEBUG_QUEUES) printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f );#endif cli();#if defined(DEBUG_QUEUES) printk("d-, ");#endif current_SC = remove_SC( &disconnected_SC, target, identify_msg & 0x3f ); if(!current_SC) { printk("lun=%d, ", identify_msg & 0x3f ); aha152x_panic("no disconnected command for that lun"); } current_SC->SCp.phase &= ~disconnected; sti(); SETPORT( SIMODE0, 0 ); SETPORT( SIMODE1, ENPHASEMIS );#if defined(DEBUG_RACE) leave_driver("(reselected) intr");#endif SETBITS( DMACNTRL0, INTEN); return; } /* Check, if we aren't busy with a command */ if(!current_SC) { /* bus is free to issue a queued command */ if(TESTHI( SSTAT1, BUSFREE) && issue_SC) { cli();#if defined(DEBUG_QUEUES) printk("i-, ");#endif current_SC = remove_first_SC( &issue_SC ); sti();#if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) printk("issueing command, ");#endif current_SC->SCp.phase = in_selection; #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) printk("selecting %d, ", current_SC->target); #endif SETPORT( SCSIID, (this_host << OID_) | current_SC->target ); /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */ SETPORT( SXFRCTL1, ENSPCHK|ENSTIMER); /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */ SETPORT( SIMODE0, ENSELDO | (disconnected_SC ? ENSELDI : 0) ); SETPORT( SIMODE1, ENSELTIMO ); /* Enable SELECTION OUT sequence */ SETBITS(SCSISEQ, ENSELO | ENAUTOATNO ); #if defined(DEBUG_RACE) leave_driver("(selecting) intr"); #endif SETBITS( DMACNTRL0, INTEN ); return; } /* No command we are busy with and no new to issue */ printk("aha152x: ignoring spurious interrupt, nothing to do\n"); return; } /* the bus is busy with something */#if defined(DEBUG_INTR) disp_ports();#endif /* we are waiting for the result of a selection attempt */ if(current_SC->SCp.phase & in_selection) { if( TESTLO( SSTAT1, SELTO ) ) /* no timeout */ if( TESTHI( SSTAT0, SELDO ) ) { /* clear BUS FREE interrupt */ SETPORT( SSTAT1, CLRBUSFREE); /* Disable SELECTION OUT sequence */ CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO ); /* Disable SELECTION OUT DONE interrupt */ CLRBITS(SIMODE0, ENSELDO); CLRBITS(SIMODE1, ENSELTIMO); if( TESTLO(SSTAT0, SELDO) ) { printk("aha152x: passing bus free condition\n");#if defined(DEBUG_RACE) leave_driver("(passing bus free) intr");#endif SETBITS( DMACNTRL0, INTEN); if(current_SC->SCp.phase & aborted) { abort_result=1; wake_up( &abortion_complete ); } aha152x_done( DID_NO_CONNECT << 16 ); return; }#if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES) printk("SELDO (SELID=%x), ", GETPORT(SELID));#endif /* selection was done */ SETPORT( SSTAT0, CLRSELDO );#if defined(DEBUG_ABORT) if(current_SC->SCp.phase & aborted) printk("(ABORT) target selected, ");#endif current_SC->SCp.phase &= ~in_selection; current_SC->SCp.phase |= in_other;#if defined(DEBUG_RACE) leave_driver("(SELDO) intr");#endif SETPORT( SCSISIG, P_MSGO ); SETPORT( SIMODE0, 0 ); SETPORT( SIMODE1, ENREQINIT ); SETBITS( DMACNTRL0, INTEN); return; } else aha152x_panic("neither timeout nor selection\007"); else {#if defined(DEBUG_SELECTION) || defined(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) printk("(ABORT) selection timeout, ");#endif abort_result=1; wake_up( &abortion_complete ); } if( TESTLO( SSTAT0, SELINGO ) ) /* ARBITRATION not won */ aha152x_done( DID_BUS_BUSY << 16 ); else /* ARBITRATION won, but SELECTION failed */ aha152x_done( DID_NO_CONNECT << 16 ); return; } } /* enable interrupt, when target leaves current phase */ phase = getphase(); 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 */ { unsigned char message;#if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES) printk("MESSAGE OUT, ");#endif if( current_SC->SCp.phase & aborted ) {#if defined(DEBUG_MSGO) || defined(DEBUG_ABORT) printk("ABORT, ");#endif message=ABORT; } else /* If we didn't identify yet, do it. Otherwise there's nothing to do, but reject (probably we got an message before, that we have to reject (SDTR, WDTR, etc.) */ if( !(current_SC->SCp.phase & sent_ident)) { message=IDENTIFY(can_disconnect,current_SC->lun);#if defined(DEBUG_MSGO) printk("IDENTIFY (reconnect=%s;lun=%d), ", can_disconnect ? "enabled" : "disabled", current_SC->lun);#endif } else { message=MESSAGE_REJECT;#if defined(DEBUG_MSGO) printk("REJECT, ");#endif } CLRBITS( SXFRCTL0, ENDMA); SETPORT( SIMODE0, 0 ); SETPORT( SIMODE1, ENPHASEMIS|ENREQINIT ); /* wait for data latch to become ready or a phase change */ while( TESTLO( DMASTAT, INTSTAT ) ) ; if( TESTHI( SSTAT1, PHASEMIS ) ) aha152x_panic("unable to send message"); /* Leave MESSAGE OUT after transfer */ SETPORT( SSTAT1, CLRATNO); SETPORT( SCSIDAT, message ); make_acklow(); getphase(); if(message==IDENTIFY(can_disconnect,current_SC->lun)) current_SC->SCp.phase |= sent_ident; if(message==ABORT) { /* revive abort(); abort() enables interrupts */ abort_result=0; wake_up( &abortion_complete ); current_SC->SCp.phase = (current_SC->SCp.phase & ~(P_MASK<<16)); /* exit */ SETBITS( DMACNTRL0, INTEN );#if defined(DEBUG_RACE) leave_driver("(ABORT) intr");#endif aha152x_done(DID_ABORT<<16); return; } } break; case P_CMD: /* COMMAND phase */#if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES) printk("COMMAND, ");#endif if( !(current_SC->SCp.sent_command) ) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -