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

📄 scsi.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
               "(n should be 0 or non-zero)\n");    } else {	scsi_logging_level = (ints[1])? ~0 : 0;    }}#ifdef CONFIG_SCSI_MULTI_LUNstatic int max_scsi_luns = 8;#elsestatic int max_scsi_luns = 1;#endif__initfunc(void scsi_luns_setup(char *str, int *ints)){    if (ints[0] != 1)	printk("scsi_luns_setup : usage max_scsi_luns=n (n should be between 1 and 8)\n");    else	max_scsi_luns = ints[1];}/* *  Detecting SCSI devices : *  We scan all present host adapter's busses,  from ID 0 to ID (max_id). *  We use the INQUIRY command, determine device type, and pass the ID / *  lun address of all sequential devices to the tape driver, all random *  devices to the disk driver. */static void scan_scsis (struct Scsi_Host *shpnt,                         unchar hardcoded,                        unchar hchannel,                         unchar hid,                         unchar hlun){  int             channel;  int             dev;  int             lun;  int             max_dev_lun;  Scsi_Cmnd     * SCpnt;  unsigned char * scsi_result;  unsigned char   scsi_result0[256];  Scsi_Device   * SDpnt;  Scsi_Device   * SDtail;  int             sparse_lun;  scsi_result = NULL;  SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), 					  GFP_ATOMIC | GFP_DMA);    if (SCpnt) {	SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device), 						 GFP_ATOMIC);	if (SDpnt) {	    /* Make sure we have something that is valid for DMA purposes */	    scsi_result = ( ( !shpnt->unchecked_isa_dma )			? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA));	}    }  if (scsi_result == NULL)   {      printk ("Unable to obtain scsi_result buffer\n");      goto leave;  }  /*   * We must chain ourself in the host_queue, so commands can time out    */  SCpnt->next = NULL;  SDpnt->device_queue = SCpnt;  SDpnt->host = shpnt;  SDpnt->online = TRUE;  /*   * Next, hook the device to the host in question.   */  SDpnt->prev = NULL;  SDpnt->next = NULL;  if( shpnt->host_queue != NULL )  {      SDtail = shpnt->host_queue;      while( SDtail->next != NULL )          SDtail = SDtail->next;      SDtail->next = SDpnt;      SDpnt->prev = SDtail;  }  else  {      shpnt->host_queue = SDpnt;  }  /*   * We need to increment the counter for this one device so we can track when   * things are quiet.   */  atomic_inc(&shpnt->host_active);   if (hardcoded == 1) {    Scsi_Device *oldSDpnt=SDpnt;    struct Scsi_Device_Template * sdtpnt;    channel = hchannel;    if(channel > shpnt->max_channel) goto leave;    dev = hid;    if(dev >= shpnt->max_id) goto leave;    lun = hlun;    if(lun >= shpnt->max_lun) goto leave;    scan_scsis_single (channel, dev, lun, &max_dev_lun, &sparse_lun,		       &SDpnt, SCpnt, shpnt, scsi_result);    /* See warning by (DB) in scsi_proc_info() towards end of       'add-single-device' section. (dpg) */    if (shpnt->select_queue_depths != NULL)	(shpnt->select_queue_depths)(shpnt, shpnt->host_queue);    if(SDpnt!=oldSDpnt) {	/* it could happen the blockdevice hasn't yet been inited */	for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)	    if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)();	oldSDpnt->scsi_request_fn = NULL;	for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {	    if(sdtpnt->attach) {		(*sdtpnt->attach)(oldSDpnt);		if(oldSDpnt->attached) {		    scsi_build_commandblocks(oldSDpnt);		    if (0 == oldSDpnt->has_cmdblocks) {			printk("scan_scsis: DANGER, no command blocks\n");			/* What to do now ?? */		    }		}	    }	}	resize_dma_pool();        for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {            if(sdtpnt->finish && sdtpnt->nr_dev)                {(*sdtpnt->finish)();}	}    }  }  else {    /* Actual LUN. PC ordering is 0->n IBM/spec ordering is n->0 */    int order_dev;        for (channel = 0; channel <= shpnt->max_channel; channel++) {      for (dev = 0; dev < shpnt->max_id; ++dev) {        if( shpnt->reverse_ordering)        	/* Shift to scanning 15,14,13... or 7,6,5,4, */        	order_dev = shpnt->max_id-dev-1;        else        	order_dev = dev;        	        if (shpnt->this_id != order_dev) {          /*           * We need the for so our continue, etc. work fine. We put this in           * a variable so that we can override it during the scan if we           * detect a device *KNOWN* to have multiple logical units.           */          max_dev_lun = (max_scsi_luns < shpnt->max_lun ?                         max_scsi_luns : shpnt->max_lun);	  sparse_lun = 0;          for (lun = 0; lun < max_dev_lun; ++lun) {            if (!scan_scsis_single (channel, order_dev, lun, &max_dev_lun,				    &sparse_lun, &SDpnt, SCpnt, shpnt,				    scsi_result)		&& !sparse_lun)              break; /* break means don't probe further for luns!=0 */          }                     /* for lun ends */        }                       /* if this_id != id ends */      }                         /* for dev ends */    }                           /* for channel ends */  } 				/* if/else hardcoded */  /*   * We need to decrement the counter for this one device   * so we know when everything is quiet.   */  atomic_dec(&shpnt->host_active);   leave:  {/* Unchain SCpnt from host_queue */      Scsi_Device *prev, *next;      Scsi_Device * dqptr;            for(dqptr = shpnt->host_queue; dqptr != SDpnt; dqptr = dqptr->next)           continue;      if(dqptr)       {          prev = dqptr->prev;          next = dqptr->next;          if(prev)              prev->next = next;          else              shpnt->host_queue = next;          if(next) next->prev = prev;      }  }     /* Last device block does not exist.  Free memory. */    if (SDpnt != NULL)      scsi_init_free ((char *) SDpnt, sizeof (Scsi_Device));    if (SCpnt != NULL)      scsi_init_free ((char *) SCpnt, sizeof (Scsi_Cmnd));    /* If we allocated a buffer so we could do DMA, free it now */    if (scsi_result != &scsi_result0[0] && scsi_result != NULL)    {        scsi_init_free (scsi_result, 512);    }    {        Scsi_Device * sdev;        Scsi_Cmnd   * scmd;        SCSI_LOG_SCAN_BUS(4,printk("Host status for host %p:\n", shpnt));        for(sdev = shpnt->host_queue; sdev; sdev = sdev->next)        {            SCSI_LOG_SCAN_BUS(4,printk("Device %d %p: ", sdev->id, sdev));            for(scmd=sdev->device_queue; scmd; scmd = scmd->next)            {                SCSI_LOG_SCAN_BUS(4,printk("%p ", scmd));            }            SCSI_LOG_SCAN_BUS(4,printk("\n"));        }    }}/* * The worker for scan_scsis. * Returning 0 means Please don't ask further for lun!=0, 1 means OK go on. * Global variables used : scsi_devices(linked list) */int scan_scsis_single (int channel, int dev, int lun, int *max_dev_lun,    int *sparse_lun, Scsi_Device **SDpnt2, Scsi_Cmnd * SCpnt,    struct Scsi_Host * shpnt, char *scsi_result){  unsigned char scsi_cmd[12];  struct Scsi_Device_Template *sdtpnt;  Scsi_Device * SDtail, *SDpnt=*SDpnt2;  int bflags, type=-1;  SDpnt->host = shpnt;  SDpnt->id = dev;  SDpnt->lun = lun;  SDpnt->channel = channel;  SDpnt->online = TRUE;  /* Some low level driver could use device->type (DB) */  SDpnt->type = -1;  /*   * Assume that the device will have handshaking problems, and then fix this   * field later if it turns out it doesn't   */  SDpnt->borken = 1;  SDpnt->was_reset = 0;  SDpnt->expecting_cc_ua = 0;  scsi_cmd[0] = TEST_UNIT_READY;  scsi_cmd[1] = lun << 5;  scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0;  SCpnt->host = SDpnt->host;  SCpnt->device = SDpnt;  SCpnt->target = SDpnt->id;  SCpnt->lun = SDpnt->lun;  SCpnt->channel = SDpnt->channel;  {    struct semaphore sem = MUTEX_LOCKED;    SCpnt->request.sem = &sem;    SCpnt->request.rq_status = RQ_SCSI_BUSY;    spin_lock_irq(&io_request_lock);    scsi_do_cmd (SCpnt, (void *) scsi_cmd,                 (void *) scsi_result,                 256, scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);    spin_unlock_irq(&io_request_lock);    down (&sem);    SCpnt->request.sem = NULL;  }  SCSI_LOG_SCAN_BUS(3,  printk ("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n",          dev, lun, SCpnt->result));  SCSI_LOG_SCAN_BUS(3,print_driverbyte(SCpnt->result));  SCSI_LOG_SCAN_BUS(3,print_hostbyte(SCpnt->result));  SCSI_LOG_SCAN_BUS(3,printk("\n"));  if (SCpnt->result) {    if (((driver_byte (SCpnt->result) & DRIVER_SENSE) ||         (status_byte (SCpnt->result) & CHECK_CONDITION)) &&        ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {      if (((SCpnt->sense_buffer[2] & 0xf) != NOT_READY) &&          ((SCpnt->sense_buffer[2] & 0xf) != UNIT_ATTENTION) &&          ((SCpnt->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0))        return 1;    }    else      return 0;  }  SCSI_LOG_SCAN_BUS(3,printk ("scsi: performing INQUIRY\n"));  /*   * Build an INQUIRY command block.   */  scsi_cmd[0] = INQUIRY;  scsi_cmd[1] = (lun << 5) & 0xe0;  scsi_cmd[2] = 0;  scsi_cmd[3] = 0;  scsi_cmd[4] = 255;  scsi_cmd[5] = 0;  SCpnt->cmd_len = 0;  {    struct semaphore sem = MUTEX_LOCKED;    SCpnt->request.sem = &sem;    SCpnt->request.rq_status = RQ_SCSI_BUSY;    spin_lock_irq(&io_request_lock);    scsi_do_cmd (SCpnt, (void *) scsi_cmd,                 (void *) scsi_result,                 256, scan_scsis_done, SCSI_TIMEOUT, 3);    spin_unlock_irq(&io_request_lock);    down (&sem);    SCpnt->request.sem = NULL;  }  SCSI_LOG_SCAN_BUS(3,printk ("scsi: INQUIRY %s with code 0x%x\n",                              SCpnt->result ? "failed" : "successful", SCpnt->result));  if (SCpnt->result)    return 0;     /* assume no peripheral if any sort of error */  /*   * Check the peripheral qualifier field - this tells us whether LUNS   * are supported here or not.   */  if( (scsi_result[0] >> 5) == 3 )    {      return 0;     /* assume no peripheral if any sort of error */    }  /*   * It would seem some TOSHIBA CDROM gets things wrong   */  if (!strncmp (scsi_result + 8, "TOSHIBA", 7) &&      !strncmp (scsi_result + 16, "CD-ROM", 6) &&      scsi_result[0] == TYPE_DISK) {    scsi_result[0] = TYPE_ROM;    scsi_result[1] |= 0x80;     /* removable */  }  /*   * It would seem the Panasonic DVD-RAM is backwards too   * If DVD-RAM or PD media used, it seems to function   * as Direct-Access   */  if (!strncmp (scsi_result + 8, "MATSHITA", 7) &&      !strncmp (scsi_result + 16, "PD-2 LF-D100", 12)) {    scsi_result[0] = TYPE_DISK;    scsi_result[1] |= 0x80;     /* removable */  }  memcpy (SDpnt->vendor, scsi_result + 8, 8);  memcpy (SDpnt->model, scsi_result + 16, 16);  memcpy (SDpnt->rev, scsi_result + 32, 4);  SDpnt->removable = (0x80 & scsi_result[1]) >> 7;  SDpnt->online = TRUE;  SDpnt->lockable = SDpnt->removable;  SDpnt->changed = 0;  SDpnt->access_count = 0;  SDpnt->busy = 0;  SDpnt->has_cmdblocks = 0;  /*   * Currently, all sequential devices are assumed to be tapes, all random   * devices disk, with the appropriate read only flags set for ROM / WORM   * treated as RO.   */  switch (type = (scsi_result[0] & 0x1f)) {  case TYPE_TAPE:  case TYPE_DISK:  case TYPE_MOD:  case TYPE_PROCESSOR:  case TYPE_SCANNER:  case TYPE_MEDIUM_CHANGER:  case TYPE_ENCLOSURE:    SDpnt->writeable = 1;    break;  case TYPE_WORM:  case TYPE_ROM:    SDpnt->writeable = 0;    break;  default:    printk ("scsi: unknown type %d\n", type);  }  SDpnt->device_blocked = FALSE;  SDpnt->device_busy = 0;  SDpnt->single_lun = 0;  SDpnt->soft_reset =    (scsi_result[7] & 1) && ((scsi_result[3] & 7) == 2);  SDpnt->random = (type == TYPE_TAPE) ? 0 : 1;  SDpnt->type = (type & 0x1f);  print_inquiry (scsi_result);  for (sdtpnt = scsi_devicelist; sdtpnt;       sdtpnt = sdtpnt->next)    if (sdtpnt->detect)      SDpnt->attached +=        (*sdtpnt->detect) (SDpnt);  SDpnt->scsi_level = scsi_result[2] & 0x07;  if (SDpnt->scsi_level >= 2 ||      (SDpnt->scsi_level == 1 &&

⌨️ 快捷键说明

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