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

📄 fdomain.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
      if (done) {#if EVERY_ACCESS      printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );#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;	    unsigned char qualifier;	    key = (unsigned char)(*((char *)current_SC->request_buffer + 2))		  & 0x0f;	    code = (unsigned char)(*((char *)current_SC->request_buffer + 12));	    qualifier = (unsigned char)(*((char *)current_SC->request_buffer					  + 13));	    if (key != UNIT_ATTENTION		&& !(key == NOT_READY		     && code == 0x04		     && (!qualifier || qualifier == 0x02 || qualifier == 0x01))		&& !(key == ILLEGAL_REQUEST && (code == 0x25						|| code == 0x24						|| !code)))		  		  printk( "scsi: <fdomain> REQUEST SENSE"			  " Key = %x, Code = %x, Qualifier = %x\n",			  key, code, qualifier );	 }      }#endif#if EVERY_ACCESS      printk( "BEFORE MY_DONE. . ." );#endif      spin_lock_irqsave(&io_request_lock, flags);      my_done( (current_SC->SCp.Status & 0xff)	       | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );      spin_unlock_irqrestore(&io_request_lock, flags);#if EVERY_ACCESS      printk( "RETURNING.\n" );#endif         } else {      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 );      }   }#if DEBUG_RACE   in_interrupt_flag = 0;#endif   return;}int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)){   if (in_command) {      panic( "scsi: <fdomain> 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              = (char *)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( adapter_mask, 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;}/* The following code, which simulates the old-style command function, was   taken from Tommy Thorn's aha1542.c file.  This code is Copyright (C)   1992 Tommy Thorn. */static volatile int internal_done_flag    = 0;static volatile int internal_done_errcode = 0;static void internal_done( Scsi_Cmnd *SCpnt ){    internal_done_errcode = SCpnt->result;    ++internal_done_flag;}int fdomain_16x0_command( Scsi_Cmnd *SCpnt ){    fdomain_16x0_queue( SCpnt, internal_done );    while (!internal_done_flag)	  ;    internal_done_flag = 0;    return internal_done_errcode;}/* End of code derived from Tommy Thorn's work. */void print_info( Scsi_Cmnd *SCpnt ){   unsigned int imr;   unsigned int irr;   unsigned int isr;   if (!SCpnt || !SCpnt->host) {      printk( "scsi: <fdomain> Cannot provide detailed information\n" );      return;   }      printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );   print_banner( SCpnt->host );   switch (SCpnt->SCp.phase) {   case in_arbitration: printk( "arbitration " ); break;   case in_selection:   printk( "selection " );   break;   case in_other:       printk( "other " );       break;   default:             printk( "unknown " );     break;   }   printk( "(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",	   SCpnt->SCp.phase,	   SCpnt->target,	   *(unsigned char *)SCpnt->cmnd,	   SCpnt->use_sg,	   SCpnt->request_bufflen );   printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",	   SCpnt->SCp.sent_command,	   SCpnt->SCp.have_data_in,	   SCpnt->timeout );#if DEBUG_RACE   printk( "in_interrupt_flag = %d\n", in_interrupt_flag );#endif   imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );   outb( 0x0a, 0xa0 );   irr = inb( 0xa0 ) << 8;   outb( 0x0a, 0x20 );   irr += inb( 0x20 );   outb( 0x0b, 0xa0 );   isr = inb( 0xa0 ) << 8;   outb( 0x0b, 0x20 );   isr += inb( 0x20 );				/* Print out interesting information */   printk( "IMR = 0x%04x", imr );   if (imr & (1 << interrupt_level))	 printk( " (masked)" );   printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );   printk( "SCSI Status      = 0x%02x\n", inb( SCSI_Status_port ) );   printk( "TMC Status       = 0x%02x", inb( TMC_Status_port ) );   if (inb( TMC_Status_port & 1))	 printk( " (interrupt)" );   printk( "\n" );   printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) );   if (inb( Interrupt_Status_port ) & 0x08)	 printk( " (enabled)" );   printk( "\n" );   if (chip == tmc18c50 || chip == tmc18c30) {      printk( "FIFO Status      = 0x%02x\n", inb( port_base + FIFO_Status ) );      printk( "Int. Condition   = 0x%02x\n",	      inb( port_base + Interrupt_Cond ) );   }   printk( "Configuration 1  = 0x%02x\n", inb( port_base + Configuration1 ) );   if (chip == tmc18c50 || chip == tmc18c30)	 printk( "Configuration 2  = 0x%02x\n",		 inb( port_base + Configuration2 ) );}int fdomain_16x0_abort( Scsi_Cmnd *SCpnt){   unsigned long flags;#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT   printk( "scsi: <fdomain> abort " );#endif   save_flags( flags );   cli();   if (!in_command) {#if EVERY_ACCESS || ERRORS_ONLY      printk( " (not in command)\n" );#endif      restore_flags( flags );      return SCSI_ABORT_NOT_RUNNING;   } else printk( "\n" );#if DEBUG_ABORT   print_info( SCpnt );#endif   fdomain_make_bus_idle();   current_SC->SCp.phase |= aborted;   current_SC->result = DID_ABORT << 16;   restore_flags( flags );      /* Aborts are not done well. . . */   my_done( DID_ABORT << 16 );   return SCSI_ABORT_SUCCESS;}int fdomain_16x0_reset( Scsi_Cmnd *SCpnt, unsigned int ignored ){#if DEBUG_RESET   static int called_once = 0;#endif#if ERRORS_ONLY   if (SCpnt) printk( "scsi: <fdomain> SCSI Bus Reset\n" );#endif#if DEBUG_RESET   if (called_once) print_info( current_SC );   called_once = 1;#endif      outb( 1, SCSI_Cntl_port );   do_pause( 2 );   outb( 0, SCSI_Cntl_port );   do_pause( 115 );   outb( 0, SCSI_Mode_Cntl_port );   outb( PARITY_MASK, TMC_Cntl_port );   /* Unless this is the very first call (i.e., SCPnt == NULL), everything      is probably hosed at this point.  We will, however, try to keep      things going by informing the high-level code that we need help. */   return SCSI_RESET_WAKEUP;}#include "sd.h"#include <scsi/scsi_ioctl.h>int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array ){   int              drive;   unsigned char    buf[512 + sizeof (Scsi_Ioctl_Command)];   Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;   int		    size      = disk->capacity;   unsigned char    *data     = sic->data;   unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };   int              retcode;   unsigned long    offset;   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.      For BIOS Version 2.0:            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.                  For the ISA-200S version of BIOS Version 2.0:      The drive parameter table starts at 0x1f33.      WARNING: Assume that the table entry is 25 bytes long.  Someone needs      to check this for the Quantum ISA-200S card.                  For BIOS Version 3.2:      The drive parameter table starts at 0x1f70.  Each entry is      0x0a bytes long.  Heads are one less than we need to report.    */   if (MAJOR(dev) != SCSI_DISK0_MAJOR) {      printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");      return 0;   }   drive = MINOR(dev) >> 4;   if (bios_major == 2) {      switch (Quantum) {      case 2:			/* ISA_200S */				/* The value of 25 has never been verified.				   It should probably be 15. */	 offset = bios_base + 0x1f33 + drive * 25;	 break;      case 3:			/* ISA_250MG */	 offset = bios_base + 0x1f36 + drive * 15;	 break;      case 4:			/* ISA_200S (another one) */	 offset = bios_base + 0x1f34 + drive * 15;	 break;      default:	 offset = bios_base + 0x1f31 + drive * 25;	 break;      }      isa_memcpy_fromio( &i, offset, sizeof( struct drive_info ) );      info_array[0] = i.heads;      info_array[1] = i.sectors;      info_array[2] = i.cylinders;   } else if (bios_major == 3	      && bios_minor >= 0	      && bios_minor < 4) { /* 3.0 and 3.2 BIOS */      memcpy_fromio( &i, bios_base + 0x1f71 + drive * 10,		     sizeof( struct drive_info ) );      info_array[0] = i.heads + 1;      info_array[1] = i.sectors;      info_array[2] = i.cylinders;   } else {			/* 3.4 BIOS (and up?) */      /* This algorithm was provided by Future Domain (much thanks!). */      sic->inlen  = 0;		/* zero bytes out */      sic->outlen = 512;		/* one sector in */      memcpy( data, do_read, sizeof( do_read ) );      retcode = kernel_scsi_ioctl( disk->device,				   SCSI_IOCTL_SEND_COMMAND,				   sic );      if (!retcode				    /* SCSI command ok */	  && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */	  && data[0x1c2]) {			    /* Partition type */	 /* The partition table layout is as follows:	    Start: 0x1b3h	    Offset: 0 = partition status		    1 = starting head		    2 = starting sector and cylinder (word, encoded)		    4 = partition type		    5 = ending head		    6 = ending sector and cylinder (word, encoded)		    8 = starting absolute sector (double word)		    c = number of sectors (double word)	    Signature: 0x1fe = 0x55aa	    So, this algorithm assumes:	    1) the first partition table is in use,	    2) the data in the first entry is correct, and	    3) partitions never divide cylinders	    Note that (1) may be FALSE for NetBSD (and other BSD flavors),	    as well as for Linux.  Note also, that Linux doesn't pay any	    attention to the fields that are used by this algorithm -- it	    only uses the absolute sector data.  Recent versions of Linux's	    fdisk(1) will fill this 

⌨️ 快捷键说明

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