📄 gdth.c
字号:
static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */static unchar gdth_polling; /* polling if TRUE */static unchar gdth_from_wait = FALSE; /* gdth_wait() */static int wait_index,wait_hanum; /* gdth_wait() */static int gdth_ctr_count = 0; /* controller count */static int gdth_ctr_vcount = 0; /* virt. ctr. count */static int gdth_ctr_released = 0; /* gdth_release() */static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS]; /* virt. ctr. table */static unchar gdth_write_through = FALSE; /* write through */static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */static int elastidx;static int eoldidx;#define DIN 1 /* IN data direction */#define DOU 2 /* OUT data direction */#define DNO DIN /* no data transfer */#define DUN DIN /* unknown data direction */static unchar gdth_direction_tab[0x100] = { DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN, DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN, DIN,DUN,DIN,DUN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU, DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU, DOU,DOU,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU, DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN};/* __initfunc, __initdata macros */#include <linux/init.h>#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags)#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags)#define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock)#define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock)/* LILO and modprobe/insmod parameters *//* IRQ list for GDT3000/3020 EISA controllers */static int irq[MAXHA] __initdata = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};/* disable driver flag */static int disable __initdata = 0;/* reserve flag */static int reserve_mode = 1; /* reserve list */static int reserve_list[MAX_RES_ARGS] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};/* scan order for PCI controllers */static int reverse_scan = 0;/* virtual channel for the host drives */static int hdr_channel = 0;/* max. IDs per channel */static int max_ids = MAXID;/* rescan all IDs */static int rescan = 0;#ifdef MODULE/* parameters for modprobe/insmod */MODULE_PARM(irq, "i");MODULE_PARM(disable, "i");MODULE_PARM(reserve_mode, "i");MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");MODULE_PARM(reverse_scan, "i");MODULE_PARM(hdr_channel, "i");MODULE_PARM(max_ids, "i");MODULE_PARM(rescan, "i");MODULE_AUTHOR("Achim Leubner");#endif/* /proc support */#include <linux/stat.h> #include "gdth_proc.h"#include "gdth_proc.c"/* notifier block to get a notify on system shutdown/halt/reboot */static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0};static void gdth_delay(int milliseconds){ if (milliseconds == 0) { udelay(1); } else { mdelay(milliseconds); }}static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs){ *cyls = size /HEADS/SECS; if (*cyls <= MAXCYLS) { *heads = HEADS; *secs = SECS; } else { /* too high for 64*32 */ *cyls = size /MEDHEADS/MEDSECS; if (*cyls <= MAXCYLS) { *heads = MEDHEADS; *secs = MEDSECS; } else { /* too high for 127*63 */ *cyls = size /BIGHEADS/BIGSECS; *heads = BIGHEADS; *secs = BIGSECS; } }}/* controller search and initialization functions */static int __init gdth_search_eisa(ushort eisa_adr){ ulong32 id; TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr)); id = inl(eisa_adr+ID0REG); if (id == GDT3A_ID || id == GDT3B_ID) { /* GDT3000A or GDT3000B */ if ((inb(eisa_adr+EISAREG) & 8) == 0) return 0; /* not EISA configured */ return 1; } if (id == GDT3_ID) /* GDT3000 */ return 1; return 0; }static int __init gdth_search_isa(ulong32 bios_adr){ void *addr; ulong32 id; TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr)); if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { id = gdth_readl(addr); gdth_munmap(addr); if (id == GDT2_ID) /* GDT2000 */ return 1; } return 0;}static int __init gdth_search_pci(gdth_pci_str *pcistr){ ulong32 base0, base1, base2; ushort device_id, cnt; struct pci_dev *pdev; TRACE(("gdth_search_pci()\n")); cnt = 0; for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device_id) { if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 && device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP) continue; pdev = NULL; while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) != NULL) { if (pci_enable_device(pdev)) continue; if (cnt >= MAXHA) return cnt; /* GDT PCI controller found, resources are already in pdev */ pcistr[cnt].pdev = pdev; pcistr[cnt].device_id = device_id; pcistr[cnt].bus = pdev->bus->number; pcistr[cnt].device_fn = pdev->devfn; pcistr[cnt].irq = pdev->irq; base0 = pdev->resource[0].flags; base1 = pdev->resource[1].flags; base2 = pdev->resource[2].flags; if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */ device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ if ((base0 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) continue; pcistr[cnt].dpmem = pdev->resource[0].start; } else { /* GDT6110, GDT6120, .. */ if ((base0 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY || (base2 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY || (base1 & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; pcistr[cnt].dpmem = pdev->resource[2].start; pcistr[cnt].io_mm = pdev->resource[0].start; pcistr[cnt].io = pdev->resource[1].start; } TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n", pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), pcistr[cnt].irq, pcistr[cnt].dpmem)); cnt++; } } return cnt;}static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt){ gdth_pci_str temp; int i, changed; TRACE(("gdth_sort_pci() cnt %d\n",cnt)); if (cnt == 0) return; do { changed = FALSE; for (i = 0; i < cnt-1; ++i) { if (!reverse_scan) { if ((pcistr[i].bus > pcistr[i+1].bus) || (pcistr[i].bus == pcistr[i+1].bus && PCI_SLOT(pcistr[i].device_fn) > PCI_SLOT(pcistr[i+1].device_fn))) { temp = pcistr[i]; pcistr[i] = pcistr[i+1]; pcistr[i+1] = temp; changed = TRUE; } } else { if ((pcistr[i].bus < pcistr[i+1].bus) || (pcistr[i].bus == pcistr[i+1].bus && PCI_SLOT(pcistr[i].device_fn) < PCI_SLOT(pcistr[i+1].device_fn))) { temp = pcistr[i]; pcistr[i] = pcistr[i+1]; pcistr[i+1] = temp; changed = TRUE; } } } } while (changed);}static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha){ ulong32 retries,id; unchar prot_ver,eisacf,i,irq_found; TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr)); /* disable board interrupts, deinitialize services */ outb(0xff,eisa_adr+EDOORREG); outb(0x00,eisa_adr+EDENABREG); outb(0x00,eisa_adr+EINTENABREG); outb(0xff,eisa_adr+LDOORREG); retries = INIT_RETRIES; gdth_delay(20); while (inb(eisa_adr+EDOORREG) != 0xff) { if (--retries == 0) { printk("GDT-EISA: Initialization error (DEINIT failed)\n"); return 0; } gdth_delay(1); TRACE2(("wait for DEINIT: retries=%d\n",retries)); } prot_ver = inb(eisa_adr+MAILBOXREG); outb(0xff,eisa_adr+EDOORREG); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-EISA: Illegal protocol version\n"); return 0; } ha->bmic = eisa_adr; ha->brd_phys = (ulong32)eisa_adr >> 12; outl(0,eisa_adr+MAILBOXREG); outl(0,eisa_adr+MAILBOXREG+4); outl(0,eisa_adr+MAILBOXREG+8); outl(0,eisa_adr+MAILBOXREG+12); /* detect IRQ */ if ((id = inl(eisa_adr+ID0REG)) == GDT3_ID) { ha->type = GDT_EISA; ha->stype = id; outl(1,eisa_adr+MAILBOXREG+8); outb(0xfe,eisa_adr+LDOORREG); retries = INIT_RETRIES; gdth_delay(20); while (inb(eisa_adr+EDOORREG) != 0xfe) { if (--retries == 0) { printk("GDT-EISA: Initialization error (get IRQ failed)\n"); return 0; } gdth_delay(1); } ha->irq = inb(eisa_adr+MAILBOXREG); outb(0xff,eisa_adr+EDOORREG); TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq)); /* check the result */ if (ha->irq == 0) { TRACE2(("Unknown IRQ, use IRQ table from cmd line !\n")); for (i = 0, irq_found = FALSE; i < MAXHA && irq[i] != 0xff; ++i) { if (irq[i]==10 || irq[i]==11 || irq[i]==12 || irq[i]==14) { irq_found = TRUE; break; } } if (irq_found) { ha->irq = irq[i]; irq[i] = 0; printk("GDT-EISA: Can not detect controller IRQ,\n"); printk("Use IRQ setting from command line (IRQ = %d)\n", ha->irq); } else { printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n"); printk("the controller BIOS or use command line parameters\n"); return 0; } } } else { eisacf = inb(eisa_adr+EISAREG) & 7; if (eisacf > 4) /* level triggered */ eisacf -= 4; ha->irq = gdth_irq_tab[eisacf]; ha->type = GDT_EISA; ha->stype = id; } return 1;} static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha){ register gdt2_dpram_str *dp2_ptr; int i; unchar irq_drq,prot_ver; ulong32 retries; TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr)); ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str)); if (ha->brd == NULL) { printk("GDT-ISA: Initialization error (DPMEM remap error)\n"); return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -