📄 gdth.c
字号:
static int remapped = FALSE;static void *gdth_mmap(ulong paddr, ulong size) { if ( paddr >= high_memory) { remapped = TRUE; return vremap(paddr, size); } else { return (void *)paddr; }}static void gdth_munmap(void *addr) { if (remapped) vfree(addr); remapped = FALSE;}#elsestatic void *gdth_mmap(ulong paddr, ulong size) { return ioremap(paddr, size); }static void gdth_munmap(void *addr) { return iounmap(addr);}#endifstatic 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 char *gdth_ioctl_tab[4][MAXHA]; /* ioctl buffer */static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */static int elastidx;static int eoldidx;static struct { Scsi_Cmnd *cmnd; /* pending request */ ushort service; /* service */} gdth_cmd_tab[GDTH_MAXCMDS][MAXHA]; /* table of pend. requests */#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,DIN,DUN,DUN,DIN,DIN,DIN, DIN,DIN,DIN,DNO,DIN,DNO,DNO,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN,DIN, DIN,DIN,DIN,DIN,DIN,DNO,DUN,DNO,DNO,DNO,DUN,DNO,DIN,DIN,DUN,DUN, DUN,DUN,DUN,DUN,DUN,DIN,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,DIN,DUN,DNO,DUN,DIN,DIN, DIN,DIN,DIN,DNO,DUN,DIN,DIN,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 */#if LINUX_VERSION_CODE >= 0x020126#include <linux/init.h>#else#define __initfunc(A) A#define __initdata#define __init#endif/* /proc support */#if LINUX_VERSION_CODE >= 0x010300#include <linux/stat.h> struct proc_dir_entry proc_scsi_gdth = { PROC_SCSI_GDTH, 4, "gdth", S_IFDIR | S_IRUGO | S_IXUGO, 2};#include "gdth_proc.h"#include "gdth_proc.c"#endif#if LINUX_VERSION_CODE >= 0x020100/* notifier block to get a notify on system shutdown/halt/reboot */static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0};#endifstatic void gdth_delay(int milliseconds){ if (milliseconds == 0) { udelay(1); } else {#if LINUX_VERSION_CODE >= 0x020168 mdelay(milliseconds);#else int i; for (i = 0; i < milliseconds; ++i) udelay(1000);#endif }}/* controller search and initialization functions */__initfunc (static int gdth_search_eisa(ushort eisa_adr)){ ulong 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; }__initfunc (static int gdth_search_isa(ulong bios_adr)){ void *addr; ulong id; TRACE(("gdth_search_isa() bios adr. %lx\n",bios_adr)); if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong))) != NULL) { id = readl(addr); gdth_munmap(addr); if (id == GDT2_ID) /* GDT2000 */ return 1; } return 0;}__initfunc (static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr)){ int error; ulong base0,base1,base2; TRACE(("gdth_search_pci() device_id %d, index %d\n", device_id,index));#if LINUX_VERSION_CODE >= 0x20155 if (!pci_present()) return 0;#else if (!pcibios_present()) return 0;#endif if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index, &pcistr->bus,&pcistr->device_fn)) return 0; /* GDT PCI controller found, now read resources from config space */#if LINUX_VERSION_CODE >= 0x20155 { struct pci_dev *pdev = pci_find_slot(pcistr->bus, pcistr->device_fn); base0 = pdev->base_address[0]; base1 = pdev->base_address[1]; base2 = pdev->base_address[2]; if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, PCI_ROM_ADDRESS, (int *) &pcistr->bios))) { printk("GDT-PCI: error %d reading configuration space", error); return -1; } pcistr->irq = pdev->irq; }#else#if LINUX_VERSION_CODE >= 0x010300#define GDTH_BASEP (int *)#else#define GDTH_BASEP#endif if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, PCI_BASE_ADDRESS_0, GDTH_BASEP&base0)) || (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, PCI_BASE_ADDRESS_1, GDTH_BASEP&base1)) || (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, PCI_BASE_ADDRESS_2, GDTH_BASEP&base2)) || (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn, PCI_ROM_ADDRESS, GDTH_BASEP&pcistr->bios)) || (error = pcibios_read_config_byte(pcistr->bus,pcistr->device_fn, PCI_INTERRUPT_LINE,&pcistr->irq))) { printk("GDT-PCI: error %d reading configuration space", error); return -1; }#endif pcistr->device_id = device_id; if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000 or GDT6000B */ device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */ if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY) return -1; pcistr->dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK; } 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) return -1; pcistr->dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK; pcistr->io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK; pcistr->io = base1 & PCI_BASE_ADDRESS_IO_MASK; } return 1;}__initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)){ ulong 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=%ld\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 = (ulong)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, check IRQ table from cmd line !\n")); for (i=0,irq_found=FALSE; i<MAXHA && irqs[i]!=0xff; ++i) { if (irqs[i]!=0) { irq_found=TRUE; break; } } if (irq_found) { ha->irq = irqs[i]; irqs[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;} __initfunc (static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha)){ register gdt2_dpram_str *dp2_ptr; int i; unchar irq_drq,prot_ver; ulong retries; TRACE(("gdth_init_isa() bios adr. %lx\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; } dp2_ptr = (gdt2_dpram_str *)ha->brd; writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ /* reset interface area */ memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u)); if (readl(&dp2_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); gdth_munmap(ha->brd); return 0; } /* disable board interrupts, read DRQ and IRQ */ writeb(0xff, &dp2_ptr->io.irqdel); writeb(0x00, &dp2_ptr->io.irqen); writeb(0x00, &dp2_ptr->u.ic.S_Status); writeb(0x00, &dp2_ptr->u.ic.Cmd_Index); irq_drq = readb(&dp2_ptr->io.rq); for (i=0; i<3; ++i) { if ((irq_drq & 1)==0) break; irq_drq >>= 1; } ha->drq = gdth_drq_tab[i]; irq_drq = readb(&dp2_ptr->io.rq) >> 3; for (i=1; i<5; ++i) { if ((irq_drq & 1)==0) break; irq_drq >>= 1; } ha->irq = gdth_irq_tab[i]; /* deinitialize services */ writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]); writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx); writeb(0, &dp2_ptr->io.event); retries = INIT_RETRIES; gdth_delay(20); while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-ISA: Initialization error (DEINIT failed)\n"); gdth_munmap(ha->brd); return 0; } gdth_delay(1); } prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]); writeb(0, &dp2_ptr->u.ic.Status); writeb(0xff, &dp2_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-ISA: Illegal protocol version\n"); gdth_munmap(ha->brd); return 0; } ha->type = GDT_ISA;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -