📄 aic7xxx.c
字号:
* cause the driver to skip scanning for any VLB or EISA controllers and * only support the PCI controllers. NOTE: this means that if the kernel * os compiled with PCI support disabled, then setting this to non-0 * would result in never finding any devices :) */static int aic7xxx_no_probe = 0;/* * So that insmod can find the variable and make it point to something */#ifdef MODULEstatic char * aic7xxx = NULL;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18)MODULE_PARM(aic7xxx, "s");#endif/* * Just in case someone uses commas to separate items on the insmod * command line, we define a dummy buffer here to avoid having insmod * write wild stuff into our code segment */static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n";#endif#define VERBOSE_NORMAL 0x0000#define VERBOSE_NEGOTIATION 0x0001#define VERBOSE_SEQINT 0x0002#define VERBOSE_SCSIINT 0x0004#define VERBOSE_PROBE 0x0008#define VERBOSE_PROBE2 0x0010#define VERBOSE_NEGOTIATION2 0x0020#define VERBOSE_MINOR_ERROR 0x0040#define VERBOSE_TRACING 0x0080#define VERBOSE_ABORT 0x0f00#define VERBOSE_ABORT_MID 0x0100#define VERBOSE_ABORT_FIND 0x0200#define VERBOSE_ABORT_PROCESS 0x0400#define VERBOSE_ABORT_RETURN 0x0800#define VERBOSE_RESET 0xf000#define VERBOSE_RESET_MID 0x1000#define VERBOSE_RESET_FIND 0x2000#define VERBOSE_RESET_PROCESS 0x4000#define VERBOSE_RESET_RETURN 0x8000static int aic7xxx_verbose = VERBOSE_NORMAL | VERBOSE_NEGOTIATION | VERBOSE_PROBE; /* verbose messages *//**************************************************************************** * * We're going to start putting in function declarations so that order of * functions is no longer important. As needed, they are added here. * ***************************************************************************/static void aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd);static void aic7xxx_print_card(struct aic7xxx_host *p);static void aic7xxx_print_scratch_ram(struct aic7xxx_host *p);static void aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded);#ifdef AIC7XXX_VERBOSE_DEBUGGINGstatic void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer);#endif/**************************************************************************** * * These functions are now used. They happen to be wrapped in useless * inb/outb port read/writes around the real reads and writes because it * seems that certain very fast CPUs have a problem dealing with us when * going at full speed. * ***************************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)static inline voidmdelay(int milliseconds){ int i; for(i=0; i<milliseconds; i++) udelay(1000);}static inline inttime_after_eq(unsigned long a, unsigned long b){ return((long)((a) - (b)) >= 0L);}static inline inttimer_pending(struct timer_list *timer){ return( timer->prev != NULL );}#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075#endifstatic inline unsigned charaic_inb(struct aic7xxx_host *p, long port){#ifdef MMAPIO unsigned char x; if(p->maddr) { x = p->maddr[port]; } else { x = inb(p->base + port); } mb(); return(x);#else return(inb(p->base + port));#endif}static inline voidaic_outb(struct aic7xxx_host *p, unsigned char val, long port){#ifdef MMAPIO if(p->maddr) { p->maddr[port] = val; } else { outb(val, p->base + port); } mb();#else outb(val, p->base + port);#endif}/*+F************************************************************************* * Function: * aic7xxx_setup * * Description: * Handle Linux boot parameters. This routine allows for assigning a value * to a parameter with a ':' between the parameter and the value. * ie. aic7xxx=unpause:0x0A,extended *-F*************************************************************************/voidaic7xxx_setup(char *s, int *dummy){ int i, n; char *p; char *end; static struct { const char *name; unsigned int *flag; } options[] = { { "extended", &aic7xxx_extended }, { "no_reset", &aic7xxx_no_reset }, { "irq_trigger", &aic7xxx_irq_trigger }, { "verbose", &aic7xxx_verbose }, { "reverse_scan",&aic7xxx_reverse_scan }, { "override_term", &aic7xxx_override_term }, { "stpwlev", &aic7xxx_stpwlev }, { "no_probe", &aic7xxx_no_probe }, { "panic_on_abort", &aic7xxx_panic_on_abort }, { "pci_parity", &aic7xxx_pci_parity }, { "dump_card", &aic7xxx_dump_card }, { "dump_sequencer", &aic7xxx_dump_sequencer }, { "tag_info", NULL } }; end = strchr(s, '\0'); for (p = strtok(s, ",."); p; p = strtok(NULL, ",.")) { for (i = 0; i < NUMBER(options); i++) { n = strlen(options[i].name); if (!strncmp(options[i].name, p, n)) { if (!strncmp(p, "tag_info", n)) { if (p[n] == ':') { char *base; char *tok, *tok_end, *tok_end2; char tok_list[] = { '.', ',', '{', '}', '\0' }; int i, instance = -1, device = -1; unsigned char done = FALSE; base = p; tok = base + n + 1; /* Forward us just past the ':' */ tok_end = strchr(tok, '\0'); if (tok_end < end) *tok_end = ','; while(!done) { switch(*tok) { case '{': if (instance == -1) instance = 0; else if (device == -1) device = 0; tok++; break; case '}': if (device != -1) device = -1; else if (instance != -1) instance = -1; tok++; break; case ',': case '.': if (instance == -1) done = TRUE; else if (device >= 0) device++; else if (instance >= 0) instance++; if ( (device >= MAX_TARGETS) || (instance >= NUMBER(aic7xxx_tag_info)) ) done = TRUE; tok++; if (!done) { base = tok; } break; case '\0': done = TRUE; break; default: done = TRUE; tok_end = strchr(tok, '\0'); for(i=0; tok_list[i]; i++) { tok_end2 = strchr(tok, tok_list[i]); if ( (tok_end2) && (tok_end2 < tok_end) ) { tok_end = tok_end2; done = FALSE; } } if ( (instance >= 0) && (device >= 0) && (instance < NUMBER(aic7xxx_tag_info)) && (device < MAX_TARGETS) ) aic7xxx_tag_info[instance].tag_commands[device] = simple_strtoul(tok, NULL, 0) & 0xff; tok = tok_end; break; } } while((p != base) && (p != NULL)) p = strtok(NULL, ",."); } } else if (p[n] == ':') { *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); } else if (!strncmp(p, "verbose", n)) { *(options[i].flag) = 0xff09; } else { *(options[i].flag) = ~(*(options[i].flag)); } } } }}/*+F************************************************************************* * Function: * pause_sequencer * * Description: * Pause the sequencer and wait for it to actually stop - this * is important since the sequencer can disable pausing for critical * sections. *-F*************************************************************************/static inline voidpause_sequencer(struct aic7xxx_host *p){ aic_outb(p, p->pause, HCNTRL); while ((aic_inb(p, HCNTRL) & PAUSE) == 0) { ; }}/*+F************************************************************************* * Function: * unpause_sequencer * * Description: * Unpause the sequencer. Unremarkable, yet done often enough to * warrant an easy way to do it. *-F*************************************************************************/static inline voidunpause_sequencer(struct aic7xxx_host *p, int unpause_always){ if (unpause_always || ( !(aic_inb(p, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) && !(p->flags & AHC_HANDLING_REQINITS) ) ) { aic_outb(p, p->unpause, HCNTRL); }}/*+F************************************************************************* * Function: * restart_sequencer * * Description: * Restart the sequencer program from address zero. This assumes * that the sequencer is already paused. *-F*************************************************************************/static inline voidrestart_sequencer(struct aic7xxx_host *p){ aic_outb(p, 0, SEQADDR0); aic_outb(p, 0, SEQADDR1); aic_outb(p, FASTMODE, SEQCTL);}/* * We include the aic7xxx_seq.c file here so that the other defines have * already been made, and so that it comes before the code that actually * downloads the instructions (since we don't typically use function * prototype, our code has to be ordered that way, it's a left-over from * th
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -