?? fdomain.c
字號:
return 1;
}
void my_done( int error )
{
if (in_command) {
in_command = 0;
outb( 0x00, Interrupt_Cntl_port );
fdomain_make_bus_idle();
current_SC->result = error;
if (current_SC->scsi_done)
current_SC->scsi_done( current_SC );
else panic( "Future Domain: current_SC->scsi_done() == NULL" );
} else {
panic( "Future Domain: my_done() called outside of command\n" );
}
#if DEBUG_RACE
in_interrupt_flag = 0;
#endif
}
void fdomain_16x0_intr( int unused )
{
int status;
int done = 0;
unsigned data_count;
sti();
outb( 0x00, Interrupt_Cntl_port );
/* We usually have one spurious interrupt after each command. Ignore it. */
if (!in_command || !current_SC) { /* Spurious interrupt */
#if EVERY_ACCESS
printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
in_command, current_SC );
#endif
return;
}
/* Abort calls my_done, so we do nothing here. */
if (current_SC->SCp.phase & aborted) {
#if DEBUG_ABORT
printk( "Interrupt after abort, ignoring\n" );
#endif
/*
return; */
}
#if DEBUG_RACE
++in_interrupt_flag;
#endif
if (current_SC->SCp.phase & in_arbitration) {
status = inb( TMC_Status_port ); /* Read adapter status */
if (!(status & 0x02)) {
#if EVERY_ACCESS
printk( " AFAIL " );
#endif
my_done( DID_BUS_BUSY << 16 );
return;
}
current_SC->SCp.phase = in_selection;
outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port );
outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */
outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port );
/* Stop arbitration and enable parity */
outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
#if DEBUG_RACE
in_interrupt_flag = 0;
#endif
return;
} else if (current_SC->SCp.phase & in_selection) {
status = inb( SCSI_Status_port );
if (!(status & 0x01)) {
/* Try again, for slow devices */
if (fdomain_select( current_SC->target )) {
#if EVERY_ACCESS
printk( " SFAIL " );
#endif
my_done( DID_NO_CONNECT << 16 );
return;
} else {
#if EVERY_ACCESS
printk( " AltSel " );
#endif
/* Stop arbitration and enable parity */
outb( 0x10 | PARITY_MASK, TMC_Cntl_port );
}
}
current_SC->SCp.phase = in_other;
outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );
outb( 0x80, SCSI_Cntl_port );
#if DEBUG_RACE
in_interrupt_flag = 0;
#endif
return;
}
/* current_SC->SCp.phase == in_other: this is the body of the routine */
status = inb( SCSI_Status_port );
if (status & 0x10) { /* REQ */
switch (status & 0x0e) {
case 0x08: /* COMMAND OUT */
outb( current_SC->cmnd[current_SC->SCp.sent_command++],
Write_SCSI_Data_port );
#if EVERY_ACCESS
printk( "CMD = %x,",
current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
#endif
break;
case 0x00: /* DATA OUT -- tmc18c50 only */
if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
current_SC->SCp.have_data_in = -1;
outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
}
break;
case 0x04: /* DATA IN -- tmc18c50 only */
if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
current_SC->SCp.have_data_in = 1;
outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
}
break;
case 0x0c: /* STATUS IN */
current_SC->SCp.Status = inb( Read_SCSI_Data_port );
#if EVERY_ACCESS
printk( "Status = %x, ", current_SC->SCp.Status );
#endif
#if ERRORS_ONLY
if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
printk( "Future Domain: target = %d, command = %x, "
"Status = %x\n",
current_SC->target, current_SC->cmnd[0],
current_SC->SCp.Status );
}
#endif
break;
case 0x0a: /* MESSAGE OUT */
outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */
break;
case 0x0e: /* MESSAGE IN */
current_SC->SCp.Message = inb( Read_SCSI_Data_port );
#if EVERY_ACCESS
printk( "Message = %x, ", current_SC->SCp.Message );
#endif
if (!current_SC->SCp.Message) ++done;
#if DEBUG_MESSAGES || EVERY_ACCESS
if (current_SC->SCp.Message) {
printk( "Future Domain: Message = %x\n",
current_SC->SCp.Message );
}
#endif
break;
}
}
if (chip == tmc1800
&& !current_SC->SCp.have_data_in
&& (current_SC->SCp.sent_command
>= COMMAND_SIZE( current_SC->cmnd[ 0 ] ))) {
/* We have to get the FIFO direction
correct, so I've made a table based
on the SCSI Standard of which commands
appear to require a DATA OUT phase.
*/
/*
p. 94: Command for all device types
CHANGE DEFINITION 40 DATA OUT
COMPARE 39 DATA OUT
COPY 18 DATA OUT
COPY AND VERIFY 3a DATA OUT
INQUIRY 12
LOG SELECT 4c DATA OUT
LOG SENSE 4d
MODE SELECT (6) 15 DATA OUT
MODE SELECT (10) 55 DATA OUT
MODE SENSE (6) 1a
MODE SENSE (10) 5a
READ BUFFER 3c
RECEIVE DIAGNOSTIC RESULTS 1c
REQUEST SENSE 03
SEND DIAGNOSTIC 1d DATA OUT
TEST UNIT READY 00
WRITE BUFFER 3b DATA OUT
p.178: Commands for direct-access devices (not listed on p. 94)
FORMAT UNIT 04 DATA OUT
LOCK-UNLOCK CACHE 36
PRE-FETCH 34
PREVENT-ALLOW MEDIUM REMOVAL 1e
READ (6)/RECEIVE 08
READ (10) 3c
READ CAPACITY 25
READ DEFECT DATA (10) 37
READ LONG 3e
REASSIGN BLOCKS 07 DATA OUT
RELEASE 17
RESERVE 16 DATA OUT
REZERO UNIT/REWIND 01
SEARCH DATA EQUAL (10) 31 DATA OUT
SEARCH DATA HIGH (10) 30 DATA OUT
SEARCH DATA LOW (10) 32 DATA OUT
SEEK (6) 0b
SEEK (10) 2b
SET LIMITS (10) 33
START STOP UNIT 1b
SYNCHRONIZE CACHE 35
VERIFY (10) 2f
WRITE (6)/PRINT/SEND 0a DATA OUT
WRITE (10)/SEND 2a DATA OUT
WRITE AND VERIFY (10) 2e DATA OUT
WRITE LONG 3f DATA OUT
WRITE SAME 41 DATA OUT ?
p. 261: Commands for sequential-access devices (not previously listed)
ERASE 19
LOAD UNLOAD 1b
LOCATE 2b
READ BLOCK LIMITS 05
READ POSITION 34
READ REVERSE 0f
RECOVER BUFFERED DATA 14
SPACE 11
WRITE FILEMARKS 10 ?
p. 298: Commands for printer devices (not previously listed)
****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
SLEW AND PRINT 0b DATA OUT -- same as seek
STOP PRINT 1b
SYNCHRONIZE BUFFER 10
p. 315: Commands for processor devices (not previously listed)
p. 321: Commands for write-once devices (not previously listed)
MEDIUM SCAN 38
READ (12) a8
SEARCH DATA EQUAL (12) b1 DATA OUT
SEARCH DATA HIGH (12) b0 DATA OUT
SEARCH DATA LOW (12) b2 DATA OUT
SET LIMITS (12) b3
VERIFY (12) af
WRITE (12) aa DATA OUT
WRITE AND VERIFY (12) ae DATA OUT
p. 332: Commands for CD-ROM devices (not previously listed)
PAUSE/RESUME 4b
PLAY AUDIO (10) 45
PLAY AUDIO (12) a5
PLAY AUDIO MSF 47
PLAY TRACK RELATIVE (10) 49
PLAY TRACK RELATIVE (12) a9
READ HEADER 44
READ SUB-CHANNEL 42
READ TOC 43
p. 370: Commands for scanner devices (not previously listed)
GET DATA BUFFER STATUS 34
GET WINDOW 25
OBJECT POSITION 31
SCAN 1b
SET WINDOW 24 DATA OUT
p. 391: Commands for optical memory devices (not listed)
ERASE (10) 2c
ERASE (12) ac
MEDIUM SCAN 38 DATA OUT
READ DEFECT DATA (12) b7
READ GENERATION 29
READ UPDATED BLOCK 2d
UPDATE BLOCK 3d DATA OUT
p. 419: Commands for medium changer devices (not listed)
EXCHANGE MEDIUM 46
INITIALIZE ELEMENT STATUS 07
MOVE MEDIUM a5
POSITION TO ELEMENT 2b
READ ELEMENT STATUS b8
REQUEST VOL. ELEMENT ADDRESS b5
SEND VOLUME TAG b6 DATA OUT
p. 454: Commands for communications devices (not listed previously)
GET MESSAGE (6) 08
GET MESSAGE (10) 28
GET MESSAGE (12) a8
*/
switch (current_SC->cmnd[0]) {
case CHANGE_DEFINITION: case COMPARE: case COPY:
case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT:
case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER:
case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE:
case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW:
case WRITE_6: case WRITE_10: case WRITE_VERIFY:
case 0x3f: case 0x41:
case 0xb1: case 0xb0: case 0xb2:
case 0xaa: case 0xae:
case 0x24:
case 0x38: case 0x3d:
case 0xb6:
case 0xea: /* alternate number for WRITE LONG */
current_SC->SCp.have_data_in = -1;
outb( 0xd0 | PARITY_MASK, TMC_Cntl_port );
break;
case 0x00:
default:
current_SC->SCp.have_data_in = 1;
outb( 0x90 | PARITY_MASK, TMC_Cntl_port );
break;
}
}
if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
while ( (data_count = 0x2000 - inw( FIFO_Data_Count_port )) > 512 ) {
#if EVERY_ACCESS
printk( "DC=%d, ", data_count ) ;
#endif
if (data_count > current_SC->SCp.this_residual)
data_count = current_SC->SCp.this_residual;
if (data_count > 0) {
#if EVERY_ACCESS
printk( "%d OUT, ", data_count );
#endif
if (data_count == 1) {
outb( *current_SC->SCp.ptr++, Write_FIFO_port );
--current_SC->SCp.this_residual;
} else {
data_count >>= 1;
outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );
current_SC->SCp.ptr += 2 * data_count;
current_SC->SCp.this_residual -= 2 * data_count;
}
}
if (!current_SC->SCp.this_residual) {
if (current_SC->SCp.buffers_residual) {
--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;
} else
break;
}
}
}
if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
while ((data_count = inw( FIFO_Data_Count_port )) > 0) {
#if EVERY_ACCESS
printk( "DC=%d, ", data_count );
#endif
if (data_count > current_SC->SCp.this_residual)
data_count = current_SC->SCp.this_residual;
if (data_count) {
#if EVERY_ACCESS
printk( "%d IN, ", data_count );
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -