📄 aha152x.c
字号:
if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT)) printk("aha152x: P_CMD: %d(%d) bytes left in FIFO, resetting\n", GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT)); /* reset fifo and enable writes */ SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO); SETPORT(DMACNTRL0, ENDMA|WRITE_READ); /* clear transfer count and scsi fifo */ SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 ); SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1); /* missing phase raises INTSTAT */ SETPORT( SIMODE0, 0 ); SETPORT( SIMODE1, ENPHASEMIS ); #if defined(DEBUG_CMD) printk("waiting, ");#endif /* wait for FIFO to get empty */ while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) ) ; if( TESTHI( SSTAT1, PHASEMIS ) ) aha152x_panic("target left COMMAND phase");#if defined(DEBUG_CMD) printk("DFIFOEMP, outsw (%d words), ", COMMAND_SIZE(current_SC->cmnd[0])>>1); disp_ports();#endif outsw( DATAPORT, ¤t_SC->cmnd, COMMAND_SIZE(current_SC->cmnd[0])>>1 );#if defined(DEBUG_CMD) printk("FCNT=%d, STCNT=%d, ", GETPORT(FIFOSTAT), GETSTCNT() ); disp_ports();#endif /* wait for SCSI FIFO to get empty. very important to send complete commands. */ while( TESTLO ( SSTAT2, SEMPTY ) ) ; CLRBITS(SXFRCTL0, SCSIEN|DMAEN); /* transfer can be considered ended, when SCSIEN reads back zero */ while( TESTHI( SXFRCTL0, SCSIEN ) ) ; CLRBITS(DMACNTRL0, ENDMA);#if defined(DEBUG_CMD) || defined(DEBUG_INTR) printk("sent %d/%d command bytes, ", GETSTCNT(), COMMAND_SIZE(current_SC->cmnd[0]));#endif } else aha152x_panic("Nothing to sent while in COMMAND OUT"); break; case P_MSGI: /* MESSAGE IN phase */#if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES) printk("MESSAGE IN, ");#endif SETPORT( SXFRCTL0, CH1); SETPORT( SIMODE0, 0); SETPORT( SIMODE1, ENBUSFREE); while( phase == P_MSGI ) { current_SC->SCp.Message = GETPORT( SCSIBUS ); switch(current_SC->SCp.Message) { case DISCONNECT:#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) printk("target disconnected, ");#endif current_SC->SCp.Message = 0; current_SC->SCp.phase |= disconnected; if(!can_disconnect) aha152x_panic("target was not allowed to disconnect"); break; case COMMAND_COMPLETE:#if defined(DEBUG_MSGI) || defined(DEBUG_PHASES) printk("inbound message ( COMMAND COMPLETE ), ");#endif done++; break; case MESSAGE_REJECT:#if defined(DEBUG_MSGI) || defined(DEBUG_TIMING) printk("inbound message ( MESSAGE REJECT ), ");#endif break; case SAVE_POINTERS:#if defined(DEBUG_MSGI) printk("inbound message ( SAVE DATA POINTERS ), ");#endif break; case EXTENDED_MESSAGE: { int i, code;#if defined(DEBUG_MSGI) printk("inbound message ( EXTENDED MESSAGE ), ");#endif make_acklow(); if(getphase()!=P_MSGI) break; i=GETPORT(SCSIBUS);#if defined(DEBUG_MSGI) printk("length (%d), ", i);#endif#if defined(DEBUG_MSGI) printk("code ( ");#endif make_acklow(); if(getphase()!=P_MSGI) break; code = GETPORT(SCSIBUS); switch( code ) { case 0x00:#if defined(DEBUG_MSGI) printk("MODIFY DATA POINTER ");#endif SETPORT(SCSISIG, P_MSGI|ATNO); break; case 0x01:#if defined(DEBUG_MSGI) printk("SYNCHRONOUS DATA TRANSFER REQUEST ");#endif SETPORT(SCSISIG, P_MSGI|ATNO); break; case 0x02:#if defined(DEBUG_MSGI) printk("EXTENDED IDENTIFY ");#endif break; case 0x03:#if defined(DEBUG_MSGI) printk("WIDE DATA TRANSFER REQUEST ");#endif SETPORT(SCSISIG, P_MSGI|ATNO); break; default:#if defined(DEBUG_MSGI) if( code & 0x80 ) printk("reserved (%d) ", code ); else printk("vendor specific (%d) ", code);#endif SETPORT(SCSISIG, P_MSGI|ATNO); break; }#if defined(DEBUG_MSGI) printk(" ), data ( ");#endif while( --i && (make_acklow(), getphase()==P_MSGI)) {#if defined(DEBUG_MSGI) printk("%x ", GETPORT(SCSIBUS) );#else GETPORT(SCSIBUS);#endif }#if defined(DEBUG_MSGI) printk(" ), ");#endif /* We reject all extended messages. To do this we just enter MSGO by asserting ATN. Since we have already identified a REJECT message will be sent. */ SETPORT(SCSISIG, P_MSGI|ATNO); } break; default: printk("unsupported inbound message %x, ", current_SC->SCp.Message); break; } make_acklow(); phase=getphase(); } /* clear SCSI fifo on BUSFREE */ if(phase==P_BUSFREE) SETPORT(SXFRCTL0, CH1|CLRCH1); if(current_SC->SCp.phase & disconnected) { cli();#if defined(DEBUG_QUEUES) printk("d+, ");#endif append_SC( &disconnected_SC, current_SC); current_SC = NULL; sti(); 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) printk("STATUS, ");#endif SETPORT( SXFRCTL0, CH1); SETPORT( SIMODE0, 0 ); SETPORT( SIMODE1, ENREQINIT ); if( TESTHI( SSTAT1, PHASEMIS ) ) printk("aha152x: passing STATUS phase"); current_SC->SCp.Status = GETPORT( SCSIBUS ); make_acklow(); getphase();#if defined(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) printk("DATA IN, ");#endif 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)); /* 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) printk("expecting data, ");#endif /* wait for PHASEMIS or full FIFO */ while( TESTLO ( DMASTAT, DFIFOFULL|INTSTAT ) ) ; if( TESTHI( DMASTAT, DFIFOFULL ) ) fifodata=132; else { /* wait for SCSI fifo to get empty */ while( TESTLO( SSTAT2, SEMPTY ) ) ; /* rest of data in FIFO */ fifodata=GETPORT(FIFOSTAT);#if defined(DEBUG_DATAI) printk("last transfer, ");#endif done=1; } #if defined(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) 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--; } else { CLRBITS(DMACNTRL0, _8BIT ); data_count >>= 1; /* Number of words */ insw( DATAPORT, current_SC->SCp.ptr, data_count );#if defined(DEBUG_DATAI)/* show what comes with the last transfer */ if(done) { int i; unsigned char *data; 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 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; } } /* rare (but possible) status bytes (probably also DISCONNECT messages) get transfered in the data phase, so I assume 1 additional byte is ok */ if(fifodata>1) { printk("aha152x: more data than expected (%d bytes)\n", GETPORT(FIFOSTAT)); }#if defined(DEBUG_DATAI) if(!fifodata) printk("fifo empty, "); else printk("something left in fifo, ");#endif }#if defined(DEBUG_DATAI) if(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 ) ) ; CLRBITS(DMACNTRL0, ENDMA );#if defined(DEBUG_DATAI) || defined(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) printk("DATA OUT, ");#endif#if defined(DEBUG_DATAO) printk("got data to send (bytes=%d, buffers=%d), ", current_SC->SCp.this_residual, current_SC->SCp.buffers_residual );#endif if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT) ) { printk("%d(%d) left in FIFO, ", GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT) ); aha152x_panic("FIFO should be empty"); } SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO); SETPORT(DMACNTRL0, ENDMA|WRITE_READ); SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1 ); SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1); SETPORT( SIMODE0, 0 ); SETPORT( SIMODE1, ENPHASEMIS ); /* while current buffer is not empty or there are more buffers to transfer */ while( TESTLO( SSTAT1, PHASEMIS ) && (current_SC->SCp.this_residual || current_SC->SCp.buffers_residual) ) {#if defined(DEBUG_DATAO) printk("sending data (left: bytes=%d, buffers=%d), waiting, ", current_SC->SCp.this_residual, current_SC->SCp.buffers_residual);#endif /* transfer rest of buffer, but max. 128 byte */ data_count = current_SC->SCp.this_residual > 128 ? 128 : current_SC->SCp.this_residual ;#if defined(DEBUG_DATAO) printk("data_count=%d, ", data_count);#endif if(data_count == 1) { /* put a single byte in byte mode */ SETBITS(DMACNTRL0, _8BIT ); SETPORT(DATAPORT, *current_SC->SCp.ptr++); current_SC->SCp.this_residual--; } else { CLRBITS(DMACNTRL0, _8BIT ); data_count >>= 1; /* Number of words */ outsw( DATAPORT, current_SC->SCp.ptr, data_count ); current_SC->SCp.ptr += 2 * data_count; current_SC->SCp.this_residual -= 2 * data_count; } /* wait for FIFO to get empty */ while( TESTLO ( DMASTAT, DFIFOEMP|INTSTAT ) ) ;#if defined(DEBUG_DATAO) printk("fifo (%d bytes), transfered (%d bytes), ", GETPORT(FIFOSTAT), GETSTCNT() );#endif /* if this buffer is empty and there are more buffers left */ if ( TESTLO( SSTAT1, PHASEMIS ) && !current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) { /* advance to next buffer */ current_SC->SCp.buffers_residual--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -