📄 aha152x.c
字号:
Scsi_Cmnd *issue_SC; Scsi_Cmnd *current_SC; Scsi_Cmnd *disconnected_SC; int aborting; int abortion_complete; int abort_result; int commands; int reconnect; int parity; int synchronous; int delay; int ext_trans; int swint; int service; unsigned char syncrate[8]; unsigned char message[256]; int message_len;#ifdef DEBUG_AHA152X int debug;#endif};static void aha152x_intr(int irq, void *dev_id, struct pt_regs *);void aha152x_done(struct Scsi_Host *shpnt, int error);void aha152x_setup(char *str, int *ints);int aha152x_checksetup(struct aha152x_setup *setup);static void aha152x_reset_ports(struct Scsi_Host *shpnt);static void aha152x_panic(struct Scsi_Host *shpnt, char *msg);static void disp_ports(struct Scsi_Host *shpnt);static void show_command(Scsi_Cmnd * ptr);static void show_queues(struct Scsi_Host *shpnt);static void disp_enintr(struct Scsi_Host *shpnt);#if defined(DEBUG_RACE)static void enter_driver(const char *);static void leave_driver(const char *);#endif/* possible i/o addresses for the AIC-6260 */static unsigned short ports[] ={ 0x340, /* default first */ 0x140};#define PORT_COUNT (sizeof(ports) / sizeof(unsigned short))#if !defined(SKIP_BIOSTEST)/* possible locations for the Adaptec BIOS */static unsigned int addresses[] ={ 0xdc000, /* default first */ 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0xd8000, 0xe0000, 0xeb800, /* VTech Platinum SMP */ 0xf0000,};#define ADDRESS_COUNT (sizeof(addresses) / sizeof(unsigned int))/* signatures for various AIC-6[23]60 based controllers. The point in detecting signatures is to avoid useless and maybe harmful probes on ports. I'm not sure that all listed boards pass auto-configuration. For those which fail the BIOS signature is obsolete, because user intervention to supply the configuration is needed anyway. May be an information whether or not the BIOS supports extended translation could be also useful here. */static struct signature { unsigned char *signature; int sig_offset; int sig_length;} signatures[] ={ { "Adaptec AHA-1520 BIOS", 0x102e, 21 }, /* Adaptec 152x */ { "Adaptec AHA-1520B", 0x0b, 19 }, /* Adaptec 152x rev B */ { "Adaptec ASW-B626 BIOS", 0x1029, 21 }, /* on-board controller */ { "Adaptec BIOS: ASW-B626", 0x0f, 22 }, /* on-board controller */ { "Adaptec ASW-B626 S2", 0x2e6c, 19 }, /* on-board controller */ { "Adaptec BIOS:AIC-6360", 0xc, 21 }, /* on-board controller */ { "ScsiPro SP-360 BIOS", 0x2873, 19 }, /* ScsiPro-Controller */ { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 }, /* Gigabyte Local-Bus-SCSI */ { "Adaptec BIOS:AVA-282X", 0xc, 21 }, /* Adaptec 282x */ { "Adaptec IBM Dock II SCSI", 0x2edd, 24 }, /* IBM Thinkpad Dock II */ { "Adaptec BIOS:AHA-1532P", 0x1c, 22 }, /* IBM Thinkpad Dock II SCSI */ { "DTC3520A Host Adapter BIOS", 0x318a, 26 }, /* DTC 3520A ISA SCSI */};#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))#endifstatic void do_pause(unsigned amount){ /* Pause for amount*10 milliseconds */ unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ while (time_before(jiffies, the_time)) barrier();}/* * queue services: */static inline void append_SC(Scsi_Cmnd ** SC, Scsi_Cmnd * new_SC){ Scsi_Cmnd *end; new_SC->host_scribble = (unsigned char *) NULL; if (!*SC) *SC = new_SC; else { for (end = *SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble); end->host_scribble = (unsigned char *) new_SC; }}static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd ** SC){ Scsi_Cmnd *ptr; ptr = *SC; if (ptr) *SC = (Scsi_Cmnd *) (*SC)->host_scribble; return ptr;}static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd ** SC, int target, int lun){ Scsi_Cmnd *ptr, *prev; for (ptr = *SC, prev = NULL; ptr && ((ptr->target != target) || (ptr->lun != lun)); prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble); if (ptr) { if (prev) prev->host_scribble = ptr->host_scribble; else *SC = (Scsi_Cmnd *) ptr->host_scribble; } return ptr;}/* * read inbound byte and wait for ACK to get low */static void make_acklow(struct Scsi_Host *shpnt){ SETPORT(SXFRCTL0, CH1 | SPIOEN); GETPORT(SCSIDAT); SETPORT(SXFRCTL0, CH1); while (TESTHI(SCSISIG, ACKI)) barrier();}/* * detect current phase more reliable: * phase is valid, when the target asserts REQ after we've deasserted ACK. * * return value is a valid phase or an error code. * * errorcodes: * P_BUSFREE BUS FREE phase detected * P_PARITY parity error in DATA phase */static int getphase(struct Scsi_Host *shpnt){ int phase, sstat1; while (1) { do { while (!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE | SCSIRSTI | REQINIT))) barrier(); if (sstat1 & BUSFREE) return P_BUSFREE; if (sstat1 & SCSIRSTI) { printk("aha152x: RESET IN\n"); SETPORT(SSTAT1, SCSIRSTI); } } while (TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT)); SETPORT(SSTAT1, CLRSCSIPERR); phase = GETPORT(SCSISIG) & P_MASK; if (TESTHI(SSTAT1, SCSIPERR)) { if ((phase & (CDO | MSGO)) == 0) /* DATA phase */ return P_PARITY; make_acklow(shpnt); } else return phase; }}/* called from init/main.c */void aha152x_setup(char *str, int *ints){ if (setup_count > 2) panic("aha152x: you can only configure up to two controllers\n"); setup[setup_count].conf = str; setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340; setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11; setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7; setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1; setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1; setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */ ; setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT; setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;#ifdef DEBUG_AHA152X setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT; if (ints[0] > 9) { printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>" "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>[,<DEBUG>]]]]]]]]\n");#else if (ints[0] > 8) { printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>" "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");#endif } else setup_count++;}/* * Test, if port_base is valid. */static int aha152x_porttest(int io_port){ int i; if (check_region(io_port, IO_RANGE)) return 0; SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */ for (i = 0; i < 16; i++) SETPORT(io_port + O_STACK, i); SETPORT(io_port + O_DMACNTRL1, 0); /* reset stack pointer */ for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++); return (i == 16);}int aha152x_checksetup(struct aha152x_setup *setup){ int i;#ifndef PCMCIA for (i = 0; i < PORT_COUNT && (setup->io_port != ports[i]); i++); if (i == PORT_COUNT) return 0;#endif if (!aha152x_porttest(setup->io_port)) return 0; if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX)) return 0; if ((setup->scsiid < 0) || (setup->scsiid > 7)) return 0; if ((setup->reconnect < 0) || (setup->reconnect > 1)) return 0; if ((setup->parity < 0) || (setup->parity > 1)) return 0; if ((setup->synchronous < 0) || (setup->synchronous > 1)) return 0; if ((setup->ext_trans < 0) || (setup->ext_trans > 1)) return 0; return 1;}void aha152x_swintr(int irqno, void *dev_id, struct pt_regs *regs){ struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN]; if (!shpnt) panic("aha152x: catched software interrupt for unknown controller.\n"); HOSTDATA(shpnt)->swint++;}int aha152x_detect(Scsi_Host_Template * tpnt){ int i, j, ok;#if defined(AUTOCONF) aha152x_config conf;#endif tpnt->proc_dir = &proc_scsi_aha152x; for (i = 0; i < IRQS; i++) aha152x_host[i] = (struct Scsi_Host *) NULL; if (setup_count) { printk("aha152x: processing commandline: "); for (i = 0; i < setup_count; i++) if (!aha152x_checksetup(&setup[i])) { printk("\naha152x: %s\n", setup[i].conf); printk("aha152x: invalid line (controller=%d)\n", i + 1); } printk("ok\n"); }#ifdef SETUP0 if (setup_count < 2) { struct aha152x_setup override = SETUP0; if (setup_count == 0 || (override.io_port != setup[0].io_port)) if (!aha152x_checksetup(&override)) { printk("\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", override.io_port, override.irq, override.scsiid, override.reconnect, override.parity, override.synchronous, override.delay, override.ext_trans); } else setup[setup_count++] = override; }#endif#ifdef SETUP1 if (setup_count < 2) { struct aha152x_setup override = SETUP1; if (setup_count == 0 || (override.io_port != setup[0].io_port)) if (!aha152x_checksetup(&override)) { printk("\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", override.io_port, override.irq, override.scsiid, override.reconnect, override.parity, override.synchronous, override.delay, override.ext_trans); } else setup[setup_count++] = override; }#endif#if defined(MODULE) if (setup_count < 2 && aha152x[0] != 0) { setup[setup_count].conf = ""; setup[setup_count].io_port = aha152x[0]; setup[setup_count].irq = aha152x[1]; setup[setup_count].scsiid = aha152x[2]; setup[setup_count].reconnect = aha152x[3]; setup[setup_count].parity = aha152x[4]; setup[setup_count].synchronous = aha152x[5]; setup[setup_count].delay = aha152x[6]; setup[setup_count].ext_trans = aha152x[7];#ifdef DEBUG_AHA152X setup[setup_count].debug = aha152x[8];#endif if (aha152x_checksetup(&setup[setup_count])) setup_count++; else printk("\naha152x: invalid module argument aha152x=0x%x,%d,%d,%d,%d,%d,%d,%d\n", setup[setup_count].io_port, setup[setup_count].irq, setup[setup_count].scsiid, setup[setup_count].reconnect, setup[setup_count].parity, setup[setup_count].synchronous, setup[setup_count].delay, setup[setup_count].ext_trans); } if (setup_count < 2 && aha152x1[0] != 0) { setup[setup_count].conf = ""; setup[setup_count].io_port = aha152x1[0]; setup[setup_count].irq = aha152x1[1]; setup[setup_count].scsiid = aha152x1[2]; setup[setup_count].reconnect = aha152x1[3]; setup[setup_count].parity = aha152x1[4]; setup[setup_count].synchronous = aha152x1[5]; setup[setup_count].delay = aha152x1[6]; setup[setup_count].ext_trans = aha152x1[7];#ifdef DEBUG_AHA152X setup[setup_count].debug = aha152x1[8];#endif if (aha152x_checksetup(&setup[setup_count])) setup_count++; else printk("\naha152x: invalid module argument aha152x1=0x%x,%d,%d,%d,%d,%d,%d,%d\n", setup[setup_count].io_port, setup[setup_count].irq, setup[setup_count].scsiid, setup[setup_count].reconnect, setup[setup_count].parity, setup[setup_count].synchronous, setup[setup_count].delay, setup[setup_count].ext_trans); }#endif#if defined(AUTOCONF) if (setup_count < 2) {#if !defined(SKIP_BIOSTEST) ok = 0; for (i = 0; i < ADDRESS_COUNT && !ok; i++) for (j = 0; (j < SIGNATURE_COUNT) && !ok; j++) ok = check_signature(addresses[i] + signatures[j].sig_offset, signatures[j].signature, signatures[j].sig_length); if (!ok && setup_count == 0) return 0; printk("aha152x: BIOS test: passed, ");#else printk("aha152x: ");#endif /* !SKIP_BIOSTEST */ ok = 0; for (i = 0; i < PORT_COUNT && setup_count < 2; i++) { if ((setup_count == 1) && (setup[0].io_port == ports[i])) continue; if (aha152x_porttest(ports[i])) { ok++; setup[setup_count].io_port = ports[i]; conf.cf_port = (GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB); setup[setup_count].irq = IRQ_MIN + conf.cf_irq; setup[setup_count].scsiid = conf.cf_id; setup[setup_count].reconnect = conf.cf_tardisc; setup[setup_count].parity = !conf.cf_parity; setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */ ; setup[setup_count].delay = DELAY_DEFAULT; setup[setup_count].ext_trans = 0;#ifdef DEBUG_AHA152X setup[setup_count].debug = DEBUG_DEFAULT;#endif setup_count++; } } if (ok) printk("auto configuration: ok, ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -