📄 aha152x.c
字号:
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) )
{
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 ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -