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

📄 fd_mcs.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	    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 = FIFO_Size - 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) {	  Bytes_Written++;	  outb( *current_SC->SCp.ptr++, Write_FIFO_port );	  --current_SC->SCp.this_residual;	} else {	  data_count >>= 1;	  tmp_count = data_count << 1;	  outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count );	  current_SC->SCp.ptr += tmp_count;	  Bytes_Written += tmp_count;	  current_SC->SCp.this_residual -= tmp_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;      }    }  } else 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	if (data_count == 1) {	  Bytes_Read++;	  *current_SC->SCp.ptr++ = inb( Read_FIFO_port );	  --current_SC->SCp.this_residual;	} else {	  data_count >>= 1; /* Number of words */	  tmp_count = data_count << 1;	  insw( Read_FIFO_port, current_SC->SCp.ptr, data_count );	  current_SC->SCp.ptr += tmp_count;	  Bytes_Read += tmp_count;	  current_SC->SCp.this_residual -= tmp_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 (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( "fd_mcs: 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( shpnt,	     (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 fd_mcs_release(struct Scsi_Host *shpnt){  int i, this_host, irq_usage;  release_region(shpnt->io_port, shpnt->n_io_port);  this_host = -1;  irq_usage = 0;  for (i = 0; i < found; i++) {    if (shpnt == hosts[i])      this_host = i;    if (shpnt->irq == hosts[i]->irq)      irq_usage++;  }  /* only for the last one */  if (1 == irq_usage)    free_irq(shpnt->irq, hosts);  found--;  for (i = this_host; i < found; i++)    hosts[i] = hosts[i+1];  hosts[found] = NULL;  return 0;}int fd_mcs_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)){  struct Scsi_Host *shpnt = SCpnt->host;  if (in_command) {    panic( "fd_mcs: fd_mcs_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  fd_mcs_make_bus_idle(shpnt);  SCpnt->scsi_done = done;	/* Save this for the done function */  current_SC       = SCpnt;  /* 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 = 1;  outb( 0x20, Interrupt_Cntl_port );  outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */  return 0;}static void internal_done( Scsi_Cmnd *SCpnt ){  /* flag it done */  SCpnt->host_scribble = (unsigned char *)1;}int fd_mcs_command( Scsi_Cmnd *SCpnt ){  fd_mcs_queue( SCpnt, internal_done );  /* host_scribble is used for status here */  SCpnt->host_scribble = NULL;  while (!SCpnt->host_scribble)    barrier();  return SCpnt->result;}#if DEBUG_ABORT || DEBUG_RESETstatic void fd_mcs_print_info( Scsi_Cmnd *SCpnt ){  unsigned int imr;  unsigned int irr;  unsigned int isr;  struct Scsi_Host *shpnt = SCpnt->host;  if (!SCpnt || !SCpnt->host) {    printk( "fd_mcs: cannot provide detailed information\n" );  }     printk( "%s\n", fd_mcs_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 << shpnt->irq))    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( shpnt->io_port + FIFO_Status ) );    printk( "Int. Condition   = 0x%02x\n",	    inb( shpnt->io_port + Interrupt_Cond ) );  }  printk( "Configuration 1  = 0x%02x\n", inb( shpnt->io_port + Configuration1 ) );  if (chip == tmc18c50 || chip == tmc18c30)    printk( "Configuration 2  = 0x%02x\n",	    inb( shpnt->io_port + Configuration2 ) );}#endifint fd_mcs_abort( Scsi_Cmnd *SCpnt){  struct Scsi_Host *shpnt = SCpnt->host;  unsigned long flags;#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT  printk( "fd_mcs: 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  fd_mcs_print_info( SCpnt );#endif  fd_mcs_make_bus_idle(shpnt);  current_SC->SCp.phase |= aborted;  current_SC->result = DID_ABORT << 16;  restore_flags( flags );     /* Aborts are not done well. . . */  spin_lock_irqsave(&io_request_lock, flags);  my_done( shpnt, DID_ABORT << 16 );  spin_unlock_irqrestore(&io_request_lock, flags);  return SCSI_ABORT_SUCCESS;}int fd_mcs_reset( Scsi_Cmnd *SCpnt, unsigned int reset_flags ){  struct Scsi_Host *shpnt = SCpnt->host;#if DEBUG_RESET  static int called_once = 0;#endif#if ERRORS_ONLY  if (SCpnt) printk( "fd_mcs: SCSI Bus Reset\n" );#endif#if DEBUG_RESET  if (called_once) fd_mcs_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 fd_mcs_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array ){  int              drive;  unsigned char    buf[512 + sizeof( int ) * 2];  int		    size      = disk->capacity;  int              *sizes    = (int *)buf;  unsigned char    *data     = (unsigned char *)(sizes + 2);  unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };  int              retcode;  /* BIOS >= 3.4 for MCA cards */  drive = MINOR(dev) / 16;  /* This algorithm was provided by Future Domain (much thanks!). */  sizes[0] = 0;		/* zero bytes out */  sizes[1] = 512;		/* one sector in */  memcpy( data, do_read, sizeof( do_read ) );  retcode = kernel_scsi_ioctl( disk->device,			       SCSI_IOCTL_SEND_COMMAND,			       (void *)buf );  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 data in correctly, and forthcoming	 versions will check for consistency.	 Checking for a non-zero partition type is not part of the	 Future Domain algorithm, but it seemed to be a reasonable thing	 to do, especially in the Linux and BSD worlds. */    info_array[0] = data[0x1c3] + 1;	    /* heads */    info_array[1] = data[0x1c4] & 0x3f;	    /* sectors */  } else {    /* Note that this new method guarantees that there will always be	 less than 1024 cylinders on a platter.  This is good for drives	 up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */    if ((unsigned int)size >= 0x7e0000U) {      info_array[0] = 0xff; /* heads   = 255 */      info_array[1] = 0x3f; /* sectors =  63 */    } else if ((unsigned int)size >= 0x200000U) {      info_array[0] = 0x80; /* heads   = 128 */      info_array[1] = 0x3f; /* sectors =  63 */    } else {      info_array[0] = 0x40; /* heads   =  64 */      info_array[1] = 0x20; /* sectors =  32 */    }  }  /* For both methods, compute the cylinders */  info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );     return 0;}/* Eventually this will go into an include file, but this will be later */static Scsi_Host_Template driver_template = FD_MCS;#include "scsi_module.c"

⌨️ 快捷键说明

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