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 + -
显示快捷键?