📄 aha152x.c
字号:
unsigned char msgi[256]; /* received message bytes */ int msgo_i, msgo_len; /* number of sent bytes and length of current messages */ unsigned char msgo[256]; /* pending messages */ int data_len; /* number of sent/received bytes in dataphase */ unsigned long io_port0; unsigned long io_port1;};/* * host specific command extension * */struct aha152x_scdata { Scsi_Cmnd *next; /* next sc in queue */ Scsi_Cmnd *done; /* done command */ struct semaphore *sem; /* semaphore to block on */};/* access macros for hostdata */#define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata)#define HOSTNO ((shpnt)->host_no)#define CURRENT_SC (HOSTDATA(shpnt)->current_SC)#define DONE_SC (HOSTDATA(shpnt)->done_SC)#define ISSUE_SC (HOSTDATA(shpnt)->issue_SC)#define DISCONNECTED_SC (HOSTDATA(shpnt)->disconnected_SC)#define QLOCK (HOSTDATA(shpnt)->lock)#define QLOCKER (HOSTDATA(shpnt)->locker)#define QLOCKERL (HOSTDATA(shpnt)->lockerl)#define STATE (HOSTDATA(shpnt)->state)#define PREVSTATE (HOSTDATA(shpnt)->prevstate)#define LASTSTATE (HOSTDATA(shpnt)->laststate)#define RECONN_TARGET (HOSTDATA(shpnt)->target)#define CMD_I (HOSTDATA(shpnt)->cmd_i)#define MSGO(i) (HOSTDATA(shpnt)->msgo[i])#define MSGO_I (HOSTDATA(shpnt)->msgo_i)#define MSGOLEN (HOSTDATA(shpnt)->msgo_len)#define ADDMSGO(x) (MSGOLEN<256 ? MSGO(MSGOLEN++)=x : aha152x_error(shpnt,"MSGO overflow"))#define MSGI(i) (HOSTDATA(shpnt)->msgi[i])#define MSGILEN (HOSTDATA(shpnt)->msgi_len)#define ADDMSGI(x) (MSGILEN<256 ? MSGI(MSGILEN++)=x : aha152x_error(shpnt,"MSGI overflow"))#define DATA_LEN (HOSTDATA(shpnt)->data_len)#define SYNCRATE (HOSTDATA(shpnt)->syncrate[CURRENT_SC->target])#define SYNCNEG (HOSTDATA(shpnt)->syncneg[CURRENT_SC->target])#define DELAY (HOSTDATA(shpnt)->delay)#define EXT_TRANS (HOSTDATA(shpnt)->ext_trans)#define TC1550 (HOSTDATA(shpnt)->tc1550)#define RECONNECT (HOSTDATA(shpnt)->reconnect)#define PARITY (HOSTDATA(shpnt)->parity)#define SYNCHRONOUS (HOSTDATA(shpnt)->synchronous)#define HOSTIOPORT0 (HOSTDATA(shpnt)->io_port0)#define HOSTIOPORT1 (HOSTDATA(shpnt)->io_port1)#define SCDATA(SCpnt) ((struct aha152x_scdata *) (SCpnt)->host_scribble)#define SCNEXT(SCpnt) SCDATA(SCpnt)->next#define SCDONE(SCpnt) SCDATA(SCpnt)->done#define SCSEM(SCpnt) SCDATA(SCpnt)->sem/* state handling */static void seldi_run(struct Scsi_Host *shpnt);static void seldo_run(struct Scsi_Host *shpnt);static void selto_run(struct Scsi_Host *shpnt);static void busfree_run(struct Scsi_Host *shpnt);static void msgo_init(struct Scsi_Host *shpnt);static void msgo_run(struct Scsi_Host *shpnt);static void msgo_end(struct Scsi_Host *shpnt);static void cmd_init(struct Scsi_Host *shpnt);static void cmd_run(struct Scsi_Host *shpnt);static void cmd_end(struct Scsi_Host *shpnt);static void datai_init(struct Scsi_Host *shpnt);static void datai_run(struct Scsi_Host *shpnt);static void datai_end(struct Scsi_Host *shpnt);static void datao_init(struct Scsi_Host *shpnt);static void datao_run(struct Scsi_Host *shpnt);static void datao_end(struct Scsi_Host *shpnt);static void status_run(struct Scsi_Host *shpnt);static void msgi_run(struct Scsi_Host *shpnt);static void msgi_end(struct Scsi_Host *shpnt);static void parerr_run(struct Scsi_Host *shpnt);static void rsti_run(struct Scsi_Host *shpnt);static void complete(struct Scsi_Host *shpnt);/* * driver states * */static struct { char *name; void (*init)(struct Scsi_Host *); void (*run)(struct Scsi_Host *); void (*end)(struct Scsi_Host *); int spio;} states[] = { { "idle", 0, 0, 0, 0}, { "unknown", 0, 0, 0, 0}, { "seldo", 0, seldo_run, 0, 0}, { "seldi", 0, seldi_run, 0, 0}, { "selto", 0, selto_run, 0, 0}, { "busfree", 0, busfree_run, 0, 0}, { "msgo", msgo_init, msgo_run, msgo_end, 1}, { "cmd", cmd_init, cmd_run, cmd_end, 1}, { "msgi", 0, msgi_run, msgi_end, 1}, { "status", 0, status_run, 0, 1}, { "datai", datai_init, datai_run, datai_end, 0}, { "datao", datao_init, datao_run, datao_end, 0}, { "parerr", 0, parerr_run, 0, 0}, { "rsti", 0, rsti_run, 0, 0},};/* setup & interrupt */static void intr(int irq, void *dev_id, struct pt_regs *);static void reset_ports(struct Scsi_Host *shpnt);static void aha152x_error(struct Scsi_Host *shpnt, char *msg);static void done(struct Scsi_Host *shpnt, int error);static int checksetup(struct aha152x_setup *setup);/* diagnostics */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);/* possible i/o addresses for the AIC-6260; default first */static unsigned short ports[] = { 0x340, 0x140 };#define PORT_COUNT (sizeof(ports) / sizeof(unsigned short))#if !defined(SKIP_BIOSTEST)/* possible locations for the Adaptec BIOS; defaults first */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", 0x000b, 17 }, /* Adaptec 152x rev B */ { "Adaptec AHA-1520B", 0x0026, 17 }, /* Iomega Jaz Jet ISA (AIC6370Q) */ { "Adaptec ASW-B626 BIOS", 0x1029, 21 }, /* on-board controller */ { "Adaptec BIOS: ASW-B626", 0x000f, 22 }, /* on-board controller */ { "Adaptec ASW-B626 S2", 0x2e6c, 19 }, /* on-board controller */ { "Adaptec BIOS:AIC-6360", 0x000c, 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", 0x000c, 21 }, /* Adaptec 282x */ { "Adaptec IBM Dock II SCSI", 0x2edd, 24 }, /* IBM Thinkpad Dock II */ { "Adaptec BIOS:AHA-1532P", 0x001c, 22 }, /* IBM Thinkpad Dock II SCSI */ { "DTC3520A Host Adapter BIOS", 0x318a, 26 }, /* DTC 3520A ISA SCSI */};#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))#endif/* * queue services: * */static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC){ Scsi_Cmnd *end; SCNEXT(new_SC) = NULL; if (!*SC) *SC = new_SC; else { for (end = *SC; SCNEXT(end); end = SCNEXT(end)) ; SCNEXT(end) = new_SC; }}static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd ** SC){ Scsi_Cmnd *ptr; ptr = *SC; if (ptr) { *SC = SCNEXT(*SC); SCNEXT(ptr)=NULL; } return ptr;}static inline Scsi_Cmnd *remove_lun_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 = SCNEXT(ptr)) ; if (ptr) { if (prev) SCNEXT(prev) = SCNEXT(ptr); else *SC = SCNEXT(ptr); SCNEXT(ptr)=NULL; } return ptr;}static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp){ Scsi_Cmnd *ptr, *prev; for (ptr = *SC, prev = NULL; ptr && SCp!=ptr; prev = ptr, ptr = SCNEXT(ptr)) ; if (ptr) { if (prev) SCNEXT(prev) = SCNEXT(ptr); else *SC = SCNEXT(ptr); SCNEXT(ptr)=NULL; } return ptr;}#if defined(PCMCIA) || !defined(MODULE)void aha152x_setup(char *str, int *ints){ if(setup_count>2) { printk(KERN_ERR "aha152x: you can only configure up to two controllers\n"); return; } 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] : 1; setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT; setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;#if defined(AHA152X_DEBUG) setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT; if (ints[0] > 9) { printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>" "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>[,<DEBUG>]]]]]]]]\n");#else if (ints[0] > 8) { /*}*/ printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>" "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");#endif return; } else { setup_count++; return; }}#endif#if !defined(MODULE)static int __init do_setup(char *str){#if defined(AHA152X_DEBUG) int ints[11];#else int ints[10];#endif int count=setup_count; get_options(str, sizeof(ints)/sizeof(int), ints); aha152x_setup(str,ints); return count<setup_count;}__setup("aha152x=", do_setup);#endif/* * 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);}static int tc1550_porttest(int io_port){ int i; if (check_region(io_port, IO_RANGE)) return 0; SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */ for (i = 0; i < 16; i++) SETPORT(io_port + O_STACK, i); SETPORT(io_port + O_TC_DMACNTRL1, 0); /* reset stack pointer */ for (i = 0; i < 16 && GETPORT(io_port + O_TC_STACK) == i; i++) ; return (i == 16);}static int checksetup(struct aha152x_setup *setup){#if !defined(PCMCIA) int i; 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)) { setup->tc1550=0; } else if(tc1550_porttest(setup->io_port)) { setup->tc1550=1; } else 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;}static void swintr(int irqno, void *dev_id, struct pt_regs *regs){ struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN]; if (!shpnt) printk(KERN_ERR "aha152x%d: catched software interrupt for unknown controller.\n", HOSTNO); HOSTDATA(shpnt)->swint++;}int aha152x_detect(Scsi_Host_Template * tpnt){ int i, j, ok;#if defined(AUTOCONF) aha152x_config conf;#endif tpnt->proc_name = "aha152x"; for (i = 0; i < IRQS; i++) aha152x_host[i] = (struct Scsi_Host *) NULL; if (setup_count) { printk(KERN_INFO "aha152x: processing commandline: "); for (i = 0; i < setup_count; i++) if (!checksetup(&setup[i])) { printk(KERN_ERR "\naha152x: %s\n", setup[i].conf); printk(KERN_ERR "aha152x: invalid line\n"); } printk("ok\n"); }#if defined(SETUP0) if (setup_count < 2) { struct aha152x_setup override = SETUP0; if (setup_count == 0 || (override.io_port != setup[0].io_port)) { if (!checksetup(&override)) { printk(KERN_ERR "\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#if defined(SETUP1) if (setup_count < 2) { struct aha152x_setup override = SETUP1; if (setup_count == 0 || (override.io_port != setup[0].io_port)) { if (!checksetup(&override)) { printk(KERN_ERR "\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 || io[0]!=0 || irq[0]!=0)) { if(aha152x[0]!=0) { setup[setup_count].conf = "";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -