eata.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,842 行 · 第 1/5 页

C
1,842
字号
      io_port[MAX_INT_PARAM + (rev_scan ? (MAX_PCI - k) : (1 + k))] =             addr + PCI_BASE_ADDRESS_0;      }#endif /* end CONFIG_PCI */   return;}static int eata2x_detect(Scsi_Host_Template *tpnt) {   unsigned int j = 0, k;   tpnt->proc_name = "eata2x";   if(strlen(boot_options)) option_setup(boot_options);#if defined(MODULE)   /* io_port could have been modified when loading as a module */   if(io_port[0] != SKIP) {      setup_done = TRUE;      io_port[MAX_INT_PARAM] = 0;      }#endif   for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL;   for (k = MAX_INT_PARAM; io_port[k]; k++)      if (io_port[k] == SKIP) continue;      else if (io_port[k] <= MAX_ISA_ADDR) {         if (!isa_probe) io_port[k] = SKIP;         }      else if (io_port[k] >= MIN_EISA_ADDR && io_port[k] <= MAX_EISA_ADDR) {         if (!eisa_probe) io_port[k] = SKIP;         }   if (pci_probe) {      if (!setup_done) add_pci_ports();      else          enable_pci_ports();      }   for (k = 0; io_port[k]; k++) {      if (io_port[k] == SKIP) continue;      if (j < MAX_BOARDS && port_detect(io_port[k], j, tpnt)) j++;      }   num_boards = j;   return j;}static void map_dma(unsigned int i, unsigned int j) {   unsigned int k, count, pci_dir;   struct scatterlist *sgpnt;   struct mscp *cpp;   Scsi_Cmnd *SCpnt;   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);   if (SCpnt->sense_buffer)      cpp->sense_addr = H2DEV(pci_map_single(HD(j)->pdev, SCpnt->sense_buffer,                           sizeof SCpnt->sense_buffer, PCI_DMA_FROMDEVICE));   cpp->sense_len = sizeof SCpnt->sense_buffer;   if (!SCpnt->use_sg) {      /* If we get here with PCI_DMA_NONE, pci_map_single triggers a BUG() */      if (!SCpnt->request_bufflen) pci_dir = PCI_DMA_BIDIRECTIONAL;      if (SCpnt->request_buffer)         cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev,                  SCpnt->request_buffer, SCpnt->request_bufflen, pci_dir));      cpp->data_len = H2DEV(SCpnt->request_bufflen);      return;      }   sgpnt = (struct scatterlist *) SCpnt->request_buffer;   count = pci_map_sg(HD(j)->pdev, sgpnt, SCpnt->use_sg, pci_dir);   for (k = 0; k < count; k++) {      cpp->sglist[k].address = H2DEV(sg_dma_address(&sgpnt[k]));      cpp->sglist[k].num_bytes = H2DEV(sg_dma_len(&sgpnt[k]));      }   cpp->sg = TRUE;   cpp->data_address = H2DEV(pci_map_single(HD(j)->pdev, cpp->sglist,                             SCpnt->use_sg * sizeof(struct sg_list), pci_dir));   cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));}static void unmap_dma(unsigned int i, unsigned int j) {   unsigned int pci_dir;   struct mscp *cpp;   Scsi_Cmnd *SCpnt;   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);   if (DEV2H(cpp->sense_addr))      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->sense_addr),                       DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);   if (SCpnt->use_sg)      pci_unmap_sg(HD(j)->pdev, SCpnt->request_buffer, SCpnt->use_sg, pci_dir);   if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;   if (DEV2H(cpp->data_address))      pci_unmap_single(HD(j)->pdev, DEV2H(cpp->data_address),                       DEV2H(cpp->data_len), pci_dir);}static void sync_dma(unsigned int i, unsigned int j) {   unsigned int pci_dir;   struct mscp *cpp;   Scsi_Cmnd *SCpnt;   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;   pci_dir = scsi_to_pci_dma_dir(SCpnt->sc_data_direction);   if (DEV2H(cpp->sense_addr))      pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->sense_addr),                          DEV2H(cpp->sense_len), PCI_DMA_FROMDEVICE);   if (SCpnt->use_sg)      pci_dma_sync_sg_for_cpu(HD(j)->pdev, SCpnt->request_buffer,                         SCpnt->use_sg, pci_dir);   if (!DEV2H(cpp->data_len)) pci_dir = PCI_DMA_BIDIRECTIONAL;   if (DEV2H(cpp->data_address))      pci_dma_sync_single_for_cpu(HD(j)->pdev, DEV2H(cpp->data_address),                       DEV2H(cpp->data_len), pci_dir);}static void scsi_to_dev_dir(unsigned int i, unsigned int j) {   unsigned int k;   static const unsigned char data_out_cmds[] = {      0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e,      0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40,      0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b, 0x5d      };   static const unsigned char data_none_cmds[] = {      0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e,      0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47,      0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5, 0x00      };   struct mscp *cpp;   Scsi_Cmnd *SCpnt;   cpp = &HD(j)->cp[i]; SCpnt = cpp->SCpnt;   if (SCpnt->sc_data_direction == SCSI_DATA_READ) {      cpp->din  = TRUE;      cpp->dout = FALSE;      return;      }   else if (SCpnt->sc_data_direction == SCSI_DATA_WRITE) {      cpp->din  = FALSE;      cpp->dout = TRUE;      return;      }   else if (SCpnt->sc_data_direction == SCSI_DATA_NONE) {      cpp->din  = FALSE;      cpp->dout = FALSE;      return;      }   if (SCpnt->sc_data_direction != SCSI_DATA_UNKNOWN)      panic("%s: qcomm, invalid SCpnt->sc_data_direction.\n", BN(j));   for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)      if (SCpnt->cmnd[0] == data_out_cmds[k]) {         cpp->dout = TRUE;         break;         }   if ((cpp->din = !cpp->dout))      for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++)         if (SCpnt->cmnd[0] == data_none_cmds[k]) {            cpp->din = FALSE;            break;            }}static int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {   unsigned int i, j, k;   struct mscp *cpp;   /* j is the board number */   j = ((struct hostdata *) SCpnt->device->host->hostdata)->board_number;   if (SCpnt->host_scribble)      panic("%s: qcomm, pid %ld, SCpnt %p already active.\n",            BN(j), SCpnt->pid, SCpnt);   /* i is the mailbox number, look for the first free mailbox      starting from last_cp_used */   i = HD(j)->last_cp_used + 1;   for (k = 0; k < sh[j]->can_queue; k++, i++) {      if (i >= sh[j]->can_queue) i = 0;      if (HD(j)->cp_stat[i] == FREE) {         HD(j)->last_cp_used = i;         break;         }      }   if (k == sh[j]->can_queue) {      printk("%s: qcomm, no free mailbox.\n", BN(j));      return 1;      }   /* Set pointer to control packet structure */   cpp = &HD(j)->cp[i];   memset(cpp, 0, sizeof(struct mscp) - CP_TAIL_SIZE);   /* Set pointer to status packet structure, Big Endian format */   cpp->sp_dma_addr = H2DEV(HD(j)->sp_dma_addr);   SCpnt->scsi_done = done;   cpp->cpp_index = i;   SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index;   if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",                        BN(j), i, SCpnt->device->channel, SCpnt->device->id,                        SCpnt->device->lun, SCpnt->pid);   cpp->reqsen = TRUE;   cpp->dispri = TRUE;#if 0   if (SCpnt->device->type == TYPE_TAPE) cpp->hbaci = TRUE;#endif   cpp->one = TRUE;   cpp->channel = SCpnt->device->channel;   cpp->target = SCpnt->device->id;   cpp->lun = SCpnt->device->lun;   cpp->SCpnt = SCpnt;   memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);   /* Use data transfer direction SCpnt->sc_data_direction */   scsi_to_dev_dir(i, j);   /* Map DMA buffers and SG list */   map_dma(i, j);   if (linked_comm && SCpnt->device->queue_depth > 2                                     && TLDEV(SCpnt->device->type)) {      HD(j)->cp_stat[i] = READY;      flush_dev(SCpnt->device, SCpnt->request->sector, j, FALSE);      return 0;      }   /* Send control packet to the board */   if (do_dma(sh[j]->io_port, cpp->cp_dma_addr, SEND_CP_DMA)) {      unmap_dma(i, j);      SCpnt->host_scribble = NULL;      printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n",             BN(j), SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, SCpnt->pid);      return 1;      }   HD(j)->cp_stat[i] = IN_USE;   return 0;}static int eata2x_eh_abort(Scsi_Cmnd *SCarg) {   unsigned int i, j;   j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number;   if (SCarg->host_scribble == NULL) {      printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",             BN(j), SCarg->device->channel, SCarg->device->id, SCarg->device->lun, SCarg->pid);      return SUCCESS;      }   i = *(unsigned int *)SCarg->host_scribble;   printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",          BN(j), i, SCarg->device->channel, SCarg->device->id, SCarg->device->lun, SCarg->pid);   if (i >= sh[j]->can_queue)      panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {      printk("%s: abort, timeout error.\n", BN(j));      return FAILED;      }   if (HD(j)->cp_stat[i] == FREE) {      printk("%s: abort, mbox %d is free.\n", BN(j), i);      return SUCCESS;      }   if (HD(j)->cp_stat[i] == IN_USE) {      printk("%s: abort, mbox %d is in use.\n", BN(j), i);      if (SCarg != HD(j)->cp[i].SCpnt)         panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n",               BN(j), i, SCarg, HD(j)->cp[i].SCpnt);      if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED)         printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i);      if (SCarg->eh_state == SCSI_STATE_TIMEOUT) {         unmap_dma(i, j);         SCarg->host_scribble = NULL;         HD(j)->cp_stat[i] = FREE;         printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n",                BN(j), i, SCarg->pid);         return SUCCESS;         }      return FAILED;      }   if (HD(j)->cp_stat[i] == IN_RESET) {      printk("%s: abort, mbox %d is in reset.\n", BN(j), i);      return FAILED;      }   if (HD(j)->cp_stat[i] == LOCKED) {      printk("%s: abort, mbox %d is locked.\n", BN(j), i);      return SUCCESS;      }   if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) {      unmap_dma(i, j);      SCarg->result = DID_ABORT << 16;      SCarg->host_scribble = NULL;      HD(j)->cp_stat[i] = FREE;      printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n",             BN(j), i, SCarg->pid);      SCarg->scsi_done(SCarg);      return SUCCESS;      }   panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);}static int eata2x_eh_host_reset(Scsi_Cmnd *SCarg) {   unsigned int i, j, time, k, c, limit = 0;   int arg_done = FALSE;   Scsi_Cmnd *SCpnt;   j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number;   printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n",          BN(j), SCarg->device->channel, SCarg->device->id, SCarg->device->lun, SCarg->pid);   if (SCarg->host_scribble == NULL)      printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);   if (HD(j)->in_reset) {      printk("%s: reset, exit, already in reset.\n", BN(j));      return FAILED;      

⌨️ 快捷键说明

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