📄 u14-34f.c
字号:
max_queue_depth, YESNO(ext_tran)); } printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d.\n", BN(j), bus_type, (unsigned long)sh[j]->io_port, (int)sh[j]->base, sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", BN(j), sh[j]->max_id, sh[j]->max_lun); for (i = 0; i <= sh[j]->max_channel; i++) printk("%s: SCSI channel %u enabled, host target ID %d.\n", BN(j), i, sh[j]->this_id); return TRUE;}static void internal_setup(char *str, int *ints) { int i, argc = ints[0]; char *cur = str, *pc; if (argc > 0) { if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM; for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; io_port[i] = 0; setup_done = TRUE; } while (cur && (pc = strchr(cur, ':'))) { int val = 0, c = *++pc; if (c == 'n' || c == 'N') val = FALSE; 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, "of:", 3)) have_old_firmware = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; if ((cur = strchr(cur, ','))) ++cur; } return;}static int option_setup(char *str) { int ints[MAX_INT_PARAM]; char *cur = str; int i = 1; while (cur && isdigit(*cur) && i <= MAX_INT_PARAM) { ints[i++] = simple_strtoul(cur, NULL, 0); if ((cur = strchr(cur, ',')) != NULL) cur++; } ints[0] = i - 1; internal_setup(cur, ints); return 1;}int u14_34f_detect(Scsi_Host_Template *tpnt){ unsigned int j = 0, k; tpnt->proc_name = "u14-34f"; if(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 = 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 inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { unsigned int k, data_len = 0; 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); data_len += sgpnt[k].length; } cpp->use_sg = SCpnt->use_sg; cpp->data_address = V2DEV(cpp->sglist); cpp->data_len = H2DEV(data_len);}static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unsigned int i, j, k; struct mscp *cpp; 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 *)); 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); cpp->xdir = DTD_IN; for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++) if (SCpnt->cmnd[0] == data_out_cmds[k]) { cpp->xdir = DTD_OUT; break; } if (cpp->xdir == DTD_IN) for (k = 0; k < ARRAY_SIZE(data_none_cmds); k++) if (SCpnt->cmnd[0] == data_none_cmds[k]) { cpp->xdir = DTD_NONE; break; } cpp->opcode = OP_SCSI; 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->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); } cpp->scsi_cdbs_len = SCpnt->cmd_len; memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_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; } if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { 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; } /* Store pointer in OGM address bytes */ outl(V2DEV(cpp), sh[j]->io_port + REG_OGM); /* Issue OGM interrupt */ outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); HD(j)->cp_stat[i] = IN_USE; return 0;}int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { int rtn; rtn = do_qcomm(SCpnt, done); return rtn;}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); if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); if (SCarg->eh_state == SCSI_STATE_TIMEOUT) { 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) { 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);}int u14_34f_abort(Scsi_Cmnd *SCarg) { return do_abort(SCarg);}static inline int do_reset(Scsi_Cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; j = ((struct hostdata *) SCarg->host->hostdata)->board_number; printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", BN(j), SCarg->channel, SCarg->target, SCarg->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; } if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: reset, exit, timeout error.\n", BN(j)); return FAILED; } HD(j)->retries = 0; for (c = 0; c <= sh[j]->max_channel; c++) for (k = 0; k < sh[j]->max_id; k++) { HD(j)->target_redo[k][c] = TRUE; HD(j)->target_to[k][c] = 0; } for (i = 0; i < sh[j]->can_queue; i++) { if (HD(j)->cp_stat[i] == FREE) continue; if (HD(j)->cp_stat[i] == LOCKED) { HD(j)->cp_stat[i] = FREE; printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); continue; } if (!(SCpnt = HD(j)->cp[i].SCpnt)) panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { HD(j)->cp_stat[i] = ABORTING; printk("%s: reset, mbox %d aborting, pid %ld.\n", BN(j), i, SCpnt->pid); } else { HD(j)->cp_stat[i] = IN_RESET; printk("%s: reset, mbox %d in reset, pid %ld.\n", BN(j), i, SCpnt->pid); } if (SCpnt->host_scribble == NULL) panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); if (SCpnt->scsi_done == NULL) panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); if (SCpnt == SCarg) arg_done = TRUE; } if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: reset, cannot reset, timeout error.\n", BN(j)); return FAILED; } outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR); printk("%s: reset, board reset done, enabling interrupts.\n", BN(j));#if defined(DEBUG_RESET) do_trace = TRUE;#endif HD(j)->in_reset = TRUE; SPIN_UNLOCK time = jiffies; while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); SPIN_LOCK printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); for (i = 0; i < sh[j]->can_queue; i++) { if (HD(j)->cp_stat[i] == IN_RESET) { SCpnt = HD(j)->cp[i].SCpnt; SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; /* This mailbox is still waiting for its interrupt */ HD(j)->cp_stat[i] = LOCKED; printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", BN(j), i, SCpnt->pid); } else if (HD(j)->cp_stat[i] == ABORTING) { SCpnt = HD(j)->cp[i].SCpnt; SCpnt->result = DID_RESET << 16; SCpnt->host_scribble = NULL; /* This mailbox was never queued to the adapter */ HD(j)->cp_stat[i] = FREE; printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", BN(j), i, SCpnt->pid); } else /* Any other mailbox has already been set free by interrupt */ continue; SCpnt->scsi_done(SCpnt); } HD(j)->in_reset = FALSE; do_trace = FALSE; if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid); else printk("%s: reset, exit.\n", BN(j)); return SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -