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

📄 fdomain.c

📁 linux0.99源代码用于研究linux操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
      }   }   if (done) {#if EVERY_ACCESS      printk( " ** IN DONE ** " );#endif      if (current_SC->SCp.have_data_in) {	 while ((data_count = inw( FIFO_Data_Count_port )) != 0) {	    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	       if (data_count == 1) {		  *current_SC->SCp.ptr++ = inb( Read_FIFO_port );		  --current_SC->SCp.this_residual;	       } else {		  data_count >>= 1; /* Number of words */		  insw( current_SC->SCp.ptr, data_count, Read_FIFO_port );		  current_SC->SCp.this_residual -= 2 * data_count;	       }	    }	    if (!current_SC->SCp.this_residual		&& 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;	    }	 }      }#if EVERY_ACCESS      printk( "AFTER DATA GET\n" );#endif      #if ERRORS_ONLY      if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {	 if ((unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f) {	    unsigned char key;	    unsigned char code;	    key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) & 0x0f;	    code = (unsigned char)(*((char *)current_SC->request_buffer + 12));	    if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))		&& !(key == ILLEGAL_REQUEST && (code == 0x25 || !code)))				printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",		       key, code );	 }      }#endif#if EVERY_ACCESS      printk( "BEFORE MY_DONE. . ." );#endif      my_done( (current_SC->SCp.Status & 0xff) | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );#if EVERY_ACCESS      printk( "RETURNING.\n" );#endif         } else {      in_interrupt_code = 0;      if (current_SC->SCp.phase & disconnect) {	 outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port );	 outb( 0x00, SCSI_Cntl_port );      } else {	 outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port );      }   }   return;}int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)){   if (in_command) {      panic( "SCSI (Future Domain): fdomain_16x0_queue() NOT REENTRANT!\n" );   }#if EVERY_ACCESS   printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",	   SCpnt->target,	   *(unsigned char *)SCpnt->cmnd,	   SCpnt->use_sg,	   SCpnt->request_bufflen );#endif   fdomain_make_bus_idle();   current_SC            = SCpnt; /* Save this for the done function */   current_SC->scsi_done = done;   /* Initialize static data */   if (current_SC->use_sg) {      current_SC->SCp.buffer =	    (struct scatterlist *)current_SC->request_buffer;      current_SC->SCp.ptr              = current_SC->SCp.buffer->address;      current_SC->SCp.this_residual    = current_SC->SCp.buffer->length;      current_SC->SCp.buffers_residual = current_SC->use_sg - 1;   } else {      current_SC->SCp.ptr              = current_SC->request_buffer;      current_SC->SCp.this_residual    = current_SC->request_bufflen;      current_SC->SCp.buffer           = NULL;      current_SC->SCp.buffers_residual = 0;   }	       current_SC->SCp.Status              = 0;   current_SC->SCp.Message             = 0;   current_SC->SCp.have_data_in        = 0;   current_SC->SCp.sent_command        = 0;   current_SC->SCp.phase               = in_arbitration;   /* Start arbitration */   outb( 0x00, Interrupt_Cntl_port );   outb( 0x00, SCSI_Cntl_port );              /* Disable data drivers */   outb( 0x40, SCSI_Data_NoACK_port );        /* Set our id bit */   ++in_command;   outb( 0x20, Interrupt_Cntl_port );   outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */   return 0;}int fdomain_16x0_command( Scsi_Cmnd *SCpnt ){   const char     *cmd_pt = SCpnt->cmnd;   const char     *the_command = SCpnt->cmnd;   unsigned char  *out_buf_pt = SCpnt->request_buffer;   unsigned char  *in_buf_pt = SCpnt->request_buffer;   unsigned char  target = SCpnt->target;   void           *buff = SCpnt->request_buffer;   int            bufflen = SCpnt->request_bufflen;   int            Status = 0;   int            Message = 0;   int            status;   int            done = 0;   unsigned long  timeout;   unsigned       data_sent = 0;   unsigned       data_count;   int            have_data_in = 0;   current_SC = SCpnt;#if EVERY_ACCESS   printk( "fdomain_command(%d, %x): ", target, (unsigned char)*the_command );#endif   if (fdomain_arbitrate()) {#if ERRORS_ONLY      printk( ", target = %d, command = %x\n",	     target, (unsigned char)*the_command );#endif      return DID_TIME_OUT << 16;   }   if (fdomain_select( target )) {#if ERRORS_ONLY      if (!target) printk( ", target = %d, command = %x\n",			 target, (unsigned char)*the_command );#endif      return DID_NO_CONNECT << 16;   }   timeout = jiffies + 500;	/* 5000 mS -- For Maxtor after a RST */   current_SC->SCp.phase = non_queueing;   switch ((unsigned char)*the_command) {   case 0x04: case 0x07: case 0x0a: case 0x15: case 0x2a:   case 0x2e: case 0x3b: case 0xea: case 0x3f:      data_count = 0x2000 - inw( FIFO_Data_Count_port );      if (bufflen - data_sent < data_count)	    data_count = bufflen - data_sent;      if (data_count == 1) {	 outb( *out_buf_pt++, Write_FIFO_port );	 ++data_sent;      } else {	 data_count >>= 1;	 outsw( out_buf_pt, data_count, Write_FIFO_port );	 out_buf_pt += 2 * data_count;	 data_sent += 2 * data_count;      }      break;   default:      outb( 0x80 | PARITY_MASK, TMC_Cntl_port );      ++have_data_in;      break;   }      while (((status = inb( SCSI_Status_port )) & 1)	  && !done && !(current_SC->SCp.phase & aborted)	  && jiffies < timeout) {            if (status & 0x10) {	/* REQ */	 switch (status & 0x0e) {	 case 0x00:		/* DATA OUT */	    data_count = 0x2000 - inw( FIFO_Data_Count_port );	    if (bufflen - data_sent < data_count)		  data_count = bufflen - data_sent;	    if (data_count == 1) {	       outb( *out_buf_pt++, Write_FIFO_port );	       ++data_sent;	    } else {	       data_count >>= 1;	       outsw( out_buf_pt, data_count, Write_FIFO_port );	       out_buf_pt += 2 * data_count;	       data_sent += 2 * data_count;	    }	    break;	 case 0x04:		/* DATA IN */	    if (!have_data_in) {	       outb( 0x80 | PARITY_MASK, TMC_Cntl_port );	       ++have_data_in;	    }	    data_count = inw( FIFO_Data_Count_port );	    if (data_count == 1) {	       *in_buf_pt++ = inb( Read_FIFO_port );	    } else {	       data_count >>= 1; /* Number of words */	       insw( in_buf_pt, data_count, Read_FIFO_port );	       in_buf_pt += 2 * data_count;	    }	    break;	 case 0x08:		/* COMMAND OUT */	    outb( *cmd_pt++, Write_SCSI_Data_port );#if EVERY_ACCESS	    printk( "%x,", (unsigned char)cmd_pt[-1] );#endif	    break;	 case 0x0c:		/* STATUS IN */	    Status = inb( Read_SCSI_Data_port );#if EVERY_ACCESS	    printk( "Status = %x, ", Status );#endif#if ERRORS_ONLY	    if (Status) {	       printk( "SCSI (Future Domain): target = %d, command = %x, Status = %x\n",		      target, (unsigned char)*the_command, Status );	    }#endif	    break;	 case 0x0a:		/* MESSAGE OUT */	    outb( 0x07, Write_SCSI_Data_port ); /* Reject */	    break;	 case 0x0e:		/* MESSAGE IN */	    Message = inb( Read_SCSI_Data_port );#if EVERY_ACCESS	    printk( "Message = %x, ", Message );#endif	    if (!Message) ++done;	    if (Message == DISCONNECT) printk( "DISCONNECT\n" );	    break;	 }      }   }   if (jiffies >= timeout) {#if EVERY_ACCESS      printk( "Time out, status = %x\n", status );#endif#if ERRORS_ONLY      printk( "SCSI (Future Domain): "	     "Time out, status = %x (target = %d, command = %x)\n",	     status, target, (unsigned char)*the_command );#endif      fdomain_make_bus_idle();      return DID_BUS_BUSY << 16;   }   if (current_SC->SCp.phase & aborted) {#if EVERY_ACCESS      printk( "Aborted\n" );#endif#if ERRORS_ONLY      printk( "SCSI (Future Domain): Aborted (command = %x)\n",	     (unsigned char)*the_command );#endif      fdomain_16x0_reset();      return DID_RESET << 16;   }      if (have_data_in) {      while ((data_count = inw( FIFO_Data_Count_port )) != 0) {	 if (data_count == 1) {	    *in_buf_pt++ = inb( Read_FIFO_port );	 } else {	    data_count >>= 1; /* Number of words */	    insw( in_buf_pt, data_count, Read_FIFO_port );	    in_buf_pt += 2 * data_count;	 }      }   }   fdomain_make_bus_idle();#if EVERY_ACCESS   printk( "Retcode = %x\n",	  (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16) );#endif#if ERRORS_ONLY   if (*the_command == REQUEST_SENSE && !Status) {      if ((unsigned char)(*((char *)buff + 2)) & 0x0f) {	 printk( "SCSI REQUEST SENSE: Sense Key = %x, Sense Code = %x\n",		(unsigned char)(*((char *)buff + 2)) & 0x0f,		(unsigned char)(*((char *)buff + 12)) );      }   }#endif   return (Status & 0xff) | ((Message & 0xff) << 8) | (DID_OK << 16);}int fdomain_16x0_abort( Scsi_Cmnd *SCpnt, int code ){#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT   printk( "SCSI (Future Domain): Abort " );#endif#if DEBUG_ABORT   printk( "Phase = %d, flag = %d, target = %d cmnd = 0x%02x pieces = %d size = %u\n",    current_SC->SCp.phase,    in_interrupt_code,    current_SC->target,    *(unsigned char *)current_SC->cmnd,    current_SC->use_sg,    current_SC->request_bufflen );   printk( "IMR = 0x%02x%02x\n", inb( 0x0a1 ), inb( 0x21 ) );   outb( 0x0a, 0xa0 );   printk( "IRR = 0x%02x", inb( 0xa0 ) );   outb( 0x0a, 0x20 );   printk( "%02x\n", inb( 0x20 ) );   outb( 0x0b, 0xa0 );   printk( "ISR = 0x%02x", inb( 0xa0 ) );   outb( 0x0b, 0x20 );   printk( "%02x\n", inb( 0x20 ) );   printk( "SCSI Status    = %x\n", inb( SCSI_Status_port ) );   printk( "TMC Status     = %x\n", inb( TMC_Status_port ) );   printk( "Interrupt Mask = %x\n", inb( Interrupt_Mask_port ) );#else   cli();   if (!in_command) {#if EVERY_ACCESS || ERRORS_ONLY      printk( " (not in command)\n" );#endif      sti();      return 0;   } else {#if EVERY_ACCESS || ERRORS_ONLY      printk( " code = %d\n", code );#endif   }   current_SC->SCp.phase |= aborted;   current_SC->result = code ? code : DID_ABORT;   sti();      /* Aborts are not done well. . . */   my_done( code << 16 );#endif   return 0;}int fdomain_16x0_reset( void ){#if ERRORS_ONLY   printk( "Future Domain: SCSI Bus Reset\n" );#endif   outb( 1, SCSI_Cntl_port );   do_pause( 2 );   outb( 0, SCSI_Cntl_port );   do_pause( 115 );   outb( 0, Data_Mode_Cntl_port );   outb( PARITY_MASK, TMC_Cntl_port );   return 0;}int fdomain_16x0_biosparam( int size, int dev, int *info ){   int    drive;   struct drive_info {      unsigned short cylinders;      unsigned char  heads;      unsigned char  sectors;   } *i;   /* NOTES:      The RAM area starts at 0x1f00 from the bios_base address.      The drive parameter table seems to start at 0x1f30.      The first byte's purpose is not known.      Next is the cylinder, head, and sector information.      The last 4 bytes appear to be the drive's size in sectors.      The other bytes in the drive parameter table are unknown.      If anyone figures them out, please send me mail, and I will      update these notes.      Tape drives do not get placed in this table.      There is another table at 0x1fea:      If the byte is 0x01, then the SCSI ID is not in use.      If the byte is 0x18 or 0x48, then the SCSI ID is in use,      although tapes don't seem to be in this table.  I haven't      seen any other numbers (in a limited sample).      0x1f2d is a drive count (i.e., not including tapes)      The table at 0x1fcc are I/O ports addresses for the various      operations.  I calculate these by hand in this driver code.    */   drive = MINOR(dev) / 16;   i = (struct drive_info *)( (char *)bios_base + 0x1f31 + drive * 25 );   info[0] = i->heads;   info[1] = i->sectors;   info[2] = i->cylinders;   return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -