📄 eata.c
字号:
else if (c == 'y' || c == 'Y') val = TRUE; else val = (int) simple_strtoul(pc, NULL, 0); if (!strncmp(cur, "lc:", 3)) linked_comm = val; else if (!strncmp(cur, "tc:", 3)) tagged_comm = val; else if (!strncmp(cur, "tm:", 3)) tag_mode = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; else if (!strncmp(cur, "rs:", 3)) rev_scan = val; if ((cur = strchr(cur, ','))) ++cur; } return;}__initfunc (static void add_pci_ports(void)) {#if defined(CONFIG_PCI) unsigned int addr, k;#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) struct pci_dev *dev = NULL; if (!pci_present()) return; for (k = 0; k < MAX_PCI; k++) { if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break; if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;#if defined(DEBUG_PCI_DETECT) printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n", driver_name, k, dev->bus->number, dev->devfn, addr);#endif if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; /* Order addresses according to rev_scan value */ io_port[MAX_INT_PARAM + (rev_scan ? (MAX_PCI - k) : (1 + k))] = (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0; }#else /* else old style PCI code */ unsigned short i = 0; unsigned char bus, devfn; if (!pcibios_present()) return; for (k = 0; k < MAX_PCI; k++) { if (pcibios_find_class(PCI_CLASS_STORAGE_SCSI << 8, i++, &bus, &devfn) != PCIBIOS_SUCCESSFUL) break; if (pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &addr) != PCIBIOS_SUCCESSFUL) continue;#if defined(DEBUG_PCI_DETECT) printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n", driver_name, k, bus, devfn, addr);#endif if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; /* Order addresses according to rev_scan value */ io_port[MAX_INT_PARAM + (rev_scan ? (MAX_PCI - k) : (1 + k))] = (addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0; }#endif /* end old style PCI code */#endif /* end CONFIG_PCI */ return;}__initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) { unsigned int j = 0, k; IRQ_FLAGS IRQ_LOCK_SAVE tpnt->proc_dir = &proc_scsi_eata2x;#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; if (!setup_done) add_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; IRQ_UNLOCK_RESTORE return j;}static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { unsigned int k; struct scatterlist *sgpnt; sgpnt = (struct scatterlist *) SCpnt->request_buffer; for (k = 0; k < SCpnt->use_sg; k++) { cpp->sglist[k].address = V2DEV(sgpnt[k].address); cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length); } cpp->data_address = V2DEV(cpp->sglist); cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));}static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unsigned int i, j, k; struct mscp *cpp; struct mssp *spp; 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 }; 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 }; /* j is the board number */ j = ((struct hostdata *) SCpnt->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) - sizeof(struct sg_list *)); /* Set pointer to status packet structure */ spp = &HD(j)->sp[0]; /* The EATA protocol uses Big Endian format */ cpp->sp_addr = V2DEV(spp); cpp->cpp = cpp; SCpnt->scsi_done = done; cpp->index = i; SCpnt->host_scribble = (unsigned char *) &cpp->index; if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", BN(j), i, SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); 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; } cpp->reqsen = TRUE; cpp->dispri = TRUE;#if 0 if (SCpnt->device->type == TYPE_TAPE) cpp->hbaci = TRUE;#endif cpp->one = TRUE; cpp->channel = SCpnt->channel; cpp->target = SCpnt->target; cpp->lun = SCpnt->lun; cpp->SCpnt = SCpnt; cpp->sense_addr = V2DEV(SCpnt->sense_buffer); cpp->sense_len = sizeof SCpnt->sense_buffer; if (SCpnt->device->tagged_queue) { if (HD(j)->target_redo[SCpnt->target][SCpnt->channel] || HD(j)->target_to[SCpnt->target][SCpnt->channel]) cpp->mess[0] = ORDERED_QUEUE_TAG; else if (tag_mode == TAG_SIMPLE) cpp->mess[0] = SIMPLE_QUEUE_TAG; else if (tag_mode == TAG_HEAD) cpp->mess[0] = HEAD_OF_QUEUE_TAG; else if (tag_mode == TAG_ORDERED) cpp->mess[0] = ORDERED_QUEUE_TAG; else if (SCpnt->device->current_tag == 0) cpp->mess[0] = ORDERED_QUEUE_TAG; else if (SCpnt->device->current_tag == 1) cpp->mess[0] = HEAD_OF_QUEUE_TAG; else cpp->mess[0] = SIMPLE_QUEUE_TAG; cpp->mess[1] = SCpnt->device->current_tag++; } if (SCpnt->use_sg) { cpp->sg = TRUE; build_sg_list(cpp, SCpnt); } else { cpp->data_address = V2DEV(SCpnt->request_buffer); cpp->data_len = H2DEV(SCpnt->request_bufflen); } memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); 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, (unsigned int) cpp, SEND_CP_DMA)) { SCpnt->host_scribble = NULL; printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); return 1; } HD(j)->cp_stat[i] = IN_USE; return 0;}int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { int rtn; IRQ_FLAGS IRQ_LOCK_SAVE rtn = do_qcomm(SCpnt, done); IRQ_UNLOCK_RESTORE return rtn;}static inline int do_old_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; j = ((struct hostdata *) SCarg->host->hostdata)->board_number; if (SCarg->host_scribble == NULL || (SCarg->serial_number_at_timeout && (SCarg->serial_number != SCarg->serial_number_at_timeout))) { printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); return SCSI_ABORT_NOT_RUNNING; } i = *(unsigned int *)SCarg->host_scribble; printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", BN(j), i, SCarg->channel, SCarg->target, SCarg->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 SCSI_ABORT_ERROR; } if (HD(j)->cp_stat[i] == FREE) { printk("%s: abort, mbox %d is free.\n", BN(j), i); return SCSI_ABORT_NOT_RUNNING; } 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); return SCSI_ABORT_SNOOZE; } if (HD(j)->cp_stat[i] == IN_RESET) { printk("%s: abort, mbox %d is in reset.\n", BN(j), i); return SCSI_ABORT_ERROR; } if (HD(j)->cp_stat[i] == LOCKED) { printk("%s: abort, mbox %d is locked.\n", BN(j), i); return SCSI_ABORT_NOT_RUNNING; } if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { 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 SCSI_ABORT_SUCCESS; } panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);}int eata2x_old_abort(Scsi_Cmnd *SCarg) { int rtn; IRQ_FLAGS IRQ_LOCK_SAVE rtn = do_old_abort(SCarg); IRQ_UNLOCK_RESTORE return rtn;}#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)static inline int do_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; j = ((struct hostdata *) SCarg->host->hostdata)->board_number; if (SCarg->host_scribble == NULL) { printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", BN(j), SCarg->channel, SCarg->target, SCarg->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->channel, SCarg->target, SCarg->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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -