⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdomain.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
   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 + -