wd33c93.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,078 行 · 第 1/5 页
C
2,078 行
/* * Case 3: If the command is currently disconnected from the bus, * we're not going to expend much effort here: Let's just return * an ABORT_SNOOZE and hope for the best... */ tmp = (struct scsi_cmnd *) hostdata->disconnected_Q; while (tmp) { if (tmp == cmd) { printk ("scsi%d: Abort - command %ld found on disconnected_Q - ", instance->host_no, cmd->pid); printk("Abort SNOOZE. "); enable_irq(cmd->device->host->irq); return FAILED; } tmp = (struct scsi_cmnd *) tmp->host_scribble; }/* * Case 4 : If we reached this point, the command was not found in any of * the queues. * * We probably reached this point because of an unlikely race condition * between the command completing successfully and the abortion code, * so we won't panic, but we will notify the user in case something really * broke. *//* sti();*/ wd33c93_execute(instance); enable_irq(cmd->device->host->irq); printk("scsi%d: warning : SCSI command probably completed successfully" " before abortion. ", instance->host_no); return FAILED;}#define MAX_WD33C93_HOSTS 4#define MAX_SETUP_ARGS ((int)(sizeof(setup_args) / sizeof(char *)))#define SETUP_BUFFER_SIZE 200static char setup_buffer[SETUP_BUFFER_SIZE];static char setup_used[MAX_SETUP_ARGS];static int done_setup = 0;intwd33c93_setup(char *str){ int i; char *p1, *p2; /* The kernel does some processing of the command-line before calling * this function: If it begins with any decimal or hex number arguments, * ints[0] = how many numbers found and ints[1] through [n] are the values * themselves. str points to where the non-numeric arguments (if any) * start: We do our own parsing of those. We construct synthetic 'nosync' * keywords out of numeric args (to maintain compatibility with older * versions) and then add the rest of the arguments. */ p1 = setup_buffer; *p1 = '\0'; if (str) strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer)); setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0'; p1 = setup_buffer; i = 0; while (*p1 && (i < MAX_SETUP_ARGS)) { p2 = strchr(p1, ','); if (p2) { *p2 = '\0'; if (p1 != p2) setup_args[i] = p1; p1 = p2 + 1; i++; } else { setup_args[i] = p1; break; } } for (i = 0; i < MAX_SETUP_ARGS; i++) setup_used[i] = 0; done_setup = 1; return 1;}__setup("wd33c93=", wd33c93_setup);/* check_setup_args() returns index if key found, 0 if not */static intcheck_setup_args(char *key, int *flags, int *val, char *buf){ int x; char *cp; for (x = 0; x < MAX_SETUP_ARGS; x++) { if (setup_used[x]) continue; if (!strncmp(setup_args[x], key, strlen(key))) break; if (!strncmp(setup_args[x], "next", strlen("next"))) return 0; } if (x == MAX_SETUP_ARGS) return 0; setup_used[x] = 1; cp = setup_args[x] + strlen(key); *val = -1; if (*cp != ':') return ++x; cp++; if ((*cp >= '0') && (*cp <= '9')) { *val = simple_strtoul(cp, NULL, 0); } return ++x;}voidwd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs, dma_setup_t setup, dma_stop_t stop, int clock_freq){ struct WD33C93_hostdata *hostdata; int i; int flags; int val; char buf[32]; if (!done_setup && setup_strings) wd33c93_setup(setup_strings); hostdata = (struct WD33C93_hostdata *) instance->hostdata; hostdata->regs = regs; hostdata->clock_freq = clock_freq; hostdata->dma_setup = setup; hostdata->dma_stop = stop; hostdata->dma_bounce_buffer = NULL; hostdata->dma_bounce_len = 0; for (i = 0; i < 8; i++) { hostdata->busy[i] = 0; hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */#ifdef PROC_STATISTICS hostdata->cmd_cnt[i] = 0; hostdata->disc_allowed_cnt[i] = 0; hostdata->disc_done_cnt[i] = 0;#endif } hostdata->input_Q = NULL; hostdata->selecting = NULL; hostdata->connected = NULL; hostdata->disconnected_Q = NULL; hostdata->state = S_UNCONNECTED; hostdata->dma = D_DMA_OFF; hostdata->level2 = L2_BASIC; hostdata->disconnect = DIS_ADAPTIVE; hostdata->args = DEBUG_DEFAULTS; hostdata->incoming_ptr = 0; hostdata->outgoing_len = 0; hostdata->default_sx_per = DEFAULT_SX_PER; hostdata->no_sync = 0xff; /* sync defaults to off */ hostdata->no_dma = 0; /* default is DMA enabled */#ifdef PROC_INTERFACE hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS | PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP;#ifdef PROC_STATISTICS hostdata->dma_cnt = 0; hostdata->pio_cnt = 0; hostdata->int_cnt = 0;#endif#endif if (check_setup_args("nosync", &flags, &val, buf)) hostdata->no_sync = val; if (check_setup_args("nodma", &flags, &val, buf)) hostdata->no_dma = (val == -1) ? 1 : val; if (check_setup_args("period", &flags, &val, buf)) hostdata->default_sx_per = sx_table[round_period((unsigned int) val)].period_ns; if (check_setup_args("disconnect", &flags, &val, buf)) { if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) hostdata->disconnect = val; else hostdata->disconnect = DIS_ADAPTIVE; } if (check_setup_args("level2", &flags, &val, buf)) hostdata->level2 = val; if (check_setup_args("debug", &flags, &val, buf)) hostdata->args = val & DB_MASK; if (check_setup_args("clock", &flags, &val, buf)) { if (val > 7 && val < 11) val = WD33C93_FS_8_10; else if (val > 11 && val < 16) val = WD33C93_FS_12_15; else if (val > 15 && val < 21) val = WD33C93_FS_16_20; else val = WD33C93_FS_8_10; hostdata->clock_freq = val; } if ((i = check_setup_args("next", &flags, &val, buf))) { while (i) setup_used[--i] = 1; }#ifdef PROC_INTERFACE if (check_setup_args("proc", &flags, &val, buf)) hostdata->proc = val;#endif spin_lock_irq(&hostdata->lock); reset_wd33c93(instance); spin_unlock_irq(&hostdata->lock); printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d", instance->host_no, (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip == C_WD33C93A) ? "WD33c93A" : (hostdata->chip == C_WD33C93B) ? "WD33c93B" : "unknown", hostdata->microcode, hostdata->no_sync, hostdata->no_dma);#ifdef DEBUGGING_ON printk(" debug_flags=0x%02x\n", hostdata->args);#else printk(" debugging=OFF\n");#endif printk(" setup_args="); for (i = 0; i < MAX_SETUP_ARGS; i++) printk("%s,", setup_args[i]); printk("\n"); printk(" Version %s - %s, Compiled %s at %s\n", WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);}intwd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in){#ifdef PROC_INTERFACE char *bp; char tbuf[128]; struct WD33C93_hostdata *hd; struct scsi_cmnd *cmd; int x, i; static int stop = 0; hd = (struct WD33C93_hostdata *) instance->hostdata;/* If 'in' is TRUE we need to _read_ the proc file. We accept the following * keywords (same format as command-line, but only ONE per read): * debug * disconnect * period * resync * proc * nodma */ if (in) { buf[len] = '\0'; bp = buf; if (!strncmp(bp, "debug:", 6)) { bp += 6; hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK; } else if (!strncmp(bp, "disconnect:", 11)) { bp += 11; x = simple_strtoul(bp, NULL, 0); if (x < DIS_NEVER || x > DIS_ALWAYS) x = DIS_ADAPTIVE; hd->disconnect = x; } else if (!strncmp(bp, "period:", 7)) { bp += 7; x = simple_strtoul(bp, NULL, 0); hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns; } else if (!strncmp(bp, "resync:", 7)) { bp += 7; x = simple_strtoul(bp, NULL, 0); for (i = 0; i < 7; i++) if (x & (1 << i)) hd->sync_stat[i] = SS_UNSET; } else if (!strncmp(bp, "proc:", 5)) { bp += 5; hd->proc = simple_strtoul(bp, NULL, 0); } else if (!strncmp(bp, "nodma:", 6)) { bp += 6; hd->no_dma = simple_strtoul(bp, NULL, 0); } else if (!strncmp(bp, "level2:", 7)) { bp += 7; hd->level2 = simple_strtoul(bp, NULL, 0); } return len; } spin_lock_irq(&hd->lock); bp = buf; *bp = '\0'; if (hd->proc & PR_VERSION) { sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s", WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__); strcat(bp, tbuf); } if (hd->proc & PR_INFO) { sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d", hd->clock_freq, hd->no_sync, hd->no_dma); strcat(bp, tbuf); strcat(bp, "\nsync_xfer[] = "); for (x = 0; x < 7; x++) { sprintf(tbuf, "\t%02x", hd->sync_xfer[x]); strcat(bp, tbuf); } strcat(bp, "\nsync_stat[] = "); for (x = 0; x < 7; x++) { sprintf(tbuf, "\t%02x", hd->sync_stat[x]); strcat(bp, tbuf); } }#ifdef PROC_STATISTICS if (hd->proc & PR_STATISTICS) { strcat(bp, "\ncommands issued: "); for (x = 0; x < 7; x++) { sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]); strcat(bp, tbuf); } strcat(bp, "\ndisconnects allowed:"); for (x = 0; x < 7; x++) { sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]); strcat(bp, tbuf); } strcat(bp, "\ndisconnects done: "); for (x = 0; x < 7; x++) { sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]); strcat(bp, tbuf); } sprintf(tbuf, "\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO", hd->int_cnt, hd->dma_cnt, hd->pio_cnt); strcat(bp, tbuf); }#endif if (hd->proc & PR_CONNECTED) { strcat(bp, "\nconnected: "); if (hd->connected) { cmd = (struct scsi_cmnd *) hd->connected; sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); } } if (hd->proc & PR_INPUTQ) { strcat(bp, "\ninput_Q: "); cmd = (struct scsi_cmnd *) hd->input_Q; while (cmd) { sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (struct scsi_cmnd *) cmd->host_scribble; } } if (hd->proc & PR_DISCQ) { strcat(bp, "\ndisconnected_Q:"); cmd = (struct scsi_cmnd *) hd->disconnected_Q; while (cmd) { sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (struct scsi_cmnd *) cmd->host_scribble; } } strcat(bp, "\n"); spin_unlock_irq(&hd->lock); *start = buf; if (stop) { stop = 0; return 0; } if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */ stop = 1; if (hd->proc & PR_STOP) /* stop every other time */ stop = 1; return strlen(bp);#else /* PROC_INTERFACE */ return 0;#endif /* PROC_INTERFACE */}voidwd33c93_release(void){}EXPORT_SYMBOL(wd33c93_host_reset);EXPORT_SYMBOL(wd33c93_init);EXPORT_SYMBOL(wd33c93_release);EXPORT_SYMBOL(wd33c93_abort);EXPORT_SYMBOL(wd33c93_queuecommand);EXPORT_SYMBOL(wd33c93_intr);EXPORT_SYMBOL(wd33c93_proc_info);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?