📄 eata.c
字号:
printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", BN(j), host->host_no, dev->channel, dev->id, dev->lun, dev->queue_depth, link_suffix, tag_suffix); } IRQ_UNLOCK_RESTORE return;}static inline int wait_on_busy(unsigned long iobase, unsigned int loop) { while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) { udelay(1L); if (--loop == 0) return TRUE; } return FALSE;}static inline int do_dma(unsigned long iobase, unsigned int addr, unchar cmd) { if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE; if ((addr = V2DEV(addr))) { outb((char) (addr >> 24), iobase + REG_LOW); outb((char) (addr >> 16), iobase + REG_LM); outb((char) (addr >> 8), iobase + REG_MID); outb((char) addr, iobase + REG_MSB); } outb(cmd, iobase + REG_CMD); return FALSE;}static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) { unsigned int loop = MAXLOOP; ushort *p; for (p = start; p <= end; p++) { while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) { udelay(1L); if (--loop == 0) return TRUE; } loop = MAXLOOP; *p = inw(iobase); } return FALSE;}__initfunc (static inline int get_pci_irq(unsigned long port_base, unsigned char *apic_irq)) {#if defined(CONFIG_PCI)#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) unsigned int addr; struct pci_dev *dev = NULL; if (!pci_present()) return FALSE; while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { if (pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &addr)) continue;#if defined(DEBUG_PCI_DETECT) printk("%s: get_pci_irq, bus %d, devfn 0x%x, addr 0x%x, apic_irq %u.\n", driver_name, dev->bus->number, dev->devfn, addr, dev->irq);#endif if ((addr & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO) continue; if ((addr & PCI_BASE_ADDRESS_IO_MASK) + PCI_BASE_ADDRESS_0 == port_base) { *apic_irq = dev->irq; return TRUE; } }#endif /* end new style PCI code */#endif /* end CONFIG_PCI */ return FALSE;}__initfunc (static inline int port_detect \ (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) { unsigned char irq, dma_channel, subversion, i; unsigned char protocol_rev, apic_irq; struct eata_info info; char *bus_type, dma_name[16], tag_type; /* Allowed DMA channels for ISA (0 indicates reserved) */ unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; char name[16]; sprintf(name, "%s%d", driver_name, j); if(check_region(port_base, REGION_SIZE)) { printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base); return FALSE; } if (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE; /* Read the info structure */ if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) return FALSE; /* Check the controller "EATA" signature */ if (info.sign != EATA_SIGNATURE) return FALSE; if (DEV2H(info.data_len) < EATA_2_0A_SIZE) { printk("%s: config structure size (%ld bytes) too short, detaching.\n", name, DEV2H(info.data_len)); return FALSE; } else if (DEV2H(info.data_len) == EATA_2_0A_SIZE) protocol_rev = 'A'; else if (DEV2H(info.data_len) == EATA_2_0B_SIZE) protocol_rev = 'B'; else protocol_rev = 'C'; if (!setup_done && j > 0 && j <= MAX_PCI) { bus_type = "PCI"; subversion = ESA; } else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) { bus_type = "PCI"; subversion = ESA; } else if (port_base >= MIN_EISA_ADDR || (protocol_rev == 'C' && info.eisa)) { bus_type = "EISA"; subversion = ESA; } else if (protocol_rev == 'C' && !info.eisa && !info.pci) { bus_type = "ISA"; subversion = ISA; } else if (port_base > MAX_ISA_ADDR) { bus_type = "PCI"; subversion = ESA; } else { bus_type = "ISA"; subversion = ISA; } if (!info.haaval || info.ata) { printk("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n", name, port_base, bus_type, info.haaval, info.ata); return FALSE; } if (info.drqvld) { if (subversion == ESA) printk("%s: warning, weird %s board using DMA.\n", name, bus_type); subversion = ISA; dma_channel = dma_channel_table[3 - info.drqx]; } else { if (subversion == ISA) printk("%s: warning, weird %s board not using DMA.\n", name, bus_type); subversion = ESA; dma_channel = NO_DMA; } if (!info.dmasup) printk("%s: warning, DMA protocol support not asserted.\n", name); irq = info.irq; if (subversion == ESA && !info.irq_tr) printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n", name, irq); if (get_pci_irq(port_base, &apic_irq) && (irq != apic_irq)) { printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, apic_irq); irq = apic_irq; } /* Board detected, allocate its IRQ */ if (request_irq(irq, do_interrupt_handler, SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0), driver_name, (void *) &sha[j])) { printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); return FALSE; } if (subversion == ISA && request_dma(dma_channel, driver_name)) { printk("%s: unable to allocate DMA channel %u, detaching.\n", name, dma_channel); free_irq(irq, &sha[j]); return FALSE; }#if defined(FORCE_CONFIG) { struct eata_config config; /* Set board configuration */ memset((char *)&config, 0, sizeof(struct eata_config)); config.len = (ushort) htons((ushort)510); config.ocena = TRUE; if (do_dma(port_base, (unsigned int)&config, SET_CONFIG_DMA)) { printk("%s: busy timeout sending configuration, detaching.\n", name); return FALSE; } }#endif sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); free_irq(irq, &sha[j]); if (subversion == ISA) free_dma(dma_channel); return FALSE; } sh[j]->io_port = port_base; sh[j]->unique_id = port_base; sh[j]->n_io_port = REGION_SIZE; sh[j]->dma_channel = dma_channel; sh[j]->irq = irq; sh[j]->sg_tablesize = (ushort) ntohs(info.scatt_size); sh[j]->this_id = (ushort) info.host_addr[3]; sh[j]->can_queue = (ushort) ntohs(info.queue_size); sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; sh[j]->select_queue_depths = select_queue_depths; /* Register the I/O space that we use */ request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name); memset(HD(j), 0, sizeof(struct hostdata)); HD(j)->subversion = subversion; HD(j)->protocol_rev = protocol_rev; HD(j)->board_number = j; if (HD(j)->subversion == ESA) sh[j]->unchecked_isa_dma = FALSE; else { sh[j]->wish_block = TRUE; sh[j]->unchecked_isa_dma = TRUE; disable_dma(dma_channel); clear_dma_ff(dma_channel); set_dma_mode(dma_channel, DMA_MODE_CASCADE); enable_dma(dma_channel); } strcpy(BN(j), name); /* DPT PM2012 does not allow to detect sg_tablesize correctly */ if (sh[j]->sg_tablesize > MAX_SGLIST || sh[j]->sg_tablesize < 2) { printk("%s: detect, wrong n. of SG lists %d, fixed.\n", BN(j), sh[j]->sg_tablesize); sh[j]->sg_tablesize = MAX_SGLIST; } /* DPT PM2012 does not allow to detect can_queue correctly */ if (sh[j]->can_queue > MAX_MAILBOXES || sh[j]->can_queue < 2) { printk("%s: detect, wrong n. of mbox %d, fixed.\n", BN(j), sh[j]->can_queue); sh[j]->can_queue = MAX_MAILBOXES; } if (protocol_rev != 'A') { if (info.max_chan > 0 && info.max_chan < MAX_CHANNEL) sh[j]->max_channel = info.max_chan; if (info.max_id > 7 && info.max_id < MAX_TARGET) sh[j]->max_id = info.max_id + 1; if (info.large_sg && sh[j]->sg_tablesize == MAX_SGLIST) sh[j]->sg_tablesize = MAX_LARGE_SGLIST; } if (protocol_rev == 'C') { if (info.max_lun > 7 && info.max_lun < MAX_LUN) sh[j]->max_lun = info.max_lun + 1; } if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST"); else sprintf(dma_name, "DMA %u", dma_channel); for (i = 0; i < sh[j]->can_queue; i++) if (! ((&HD(j)->cp[i])->sglist = kmalloc( sh[j]->sg_tablesize * sizeof(struct sg_list), (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) { printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i); eata2x_release(sh[j]); return FALSE; } if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN) max_queue_depth = MAX_TAGGED_CMD_PER_LUN; if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; if (tagged_comm) { if (tag_mode == TAG_SIMPLE) tag_type = '1'; else if (tag_mode == TAG_HEAD) tag_type = '2'; else if (tag_mode == TAG_ORDERED) tag_type = '3'; else tag_type = 'y'; } else tag_type = 'n';#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101) sh[j]->hostt->use_new_eh_code = use_new_eh_code;#else use_new_eh_code = FALSE;#endif if (j == 0) { printk("EATA/DMA 2.0x: Copyright (C) 1994-1998 Dario Ballabio.\n"); printk("%s config options -> tc:%c, lc:%c, mq:%d, eh:%c, rs:%c, et:%c.\n", driver_name, tag_type, YESNO(linked_comm), max_queue_depth, YESNO(use_new_eh_code), YESNO(rev_scan), YESNO(ext_tran)); } printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d.\n", BN(j), HD(j)->protocol_rev, bus_type, (unsigned long)sh[j]->io_port, sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", BN(j), sh[j]->max_id, sh[j]->max_lun); for (i = 0; i <= sh[j]->max_channel; i++) printk("%s: SCSI channel %u enabled, host target ID %d.\n", BN(j), i, info.host_addr[3 - i]);#if defined(DEBUG_DETECT) printk("%s: Vers. 0x%x, ocs %u, tar %u, trnxfr %u, more %u, SYNC 0x%x, "\ "sec. %u, infol %ld, cpl %ld spl %ld.\n", name, info.version, info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync, info.second, DEV2H(info.data_len), DEV2H(info.cp_len), DEV2H(info.sp_len)); if (protocol_rev == 'B' || protocol_rev == 'C') printk("%s: isaena %u, forcaddr %u, max_id %u, max_chan %u, "\ "large_sg %u, res1 %u.\n", name, info.isaena, info.forcaddr, info.max_id, info.max_chan, info.large_sg, info.res1); if (protocol_rev == 'C') printk("%s: max_lun %u, m1 %u, idquest %u, pci %u, eisa %u, "\ "raidnum %u.\n", name, info.max_lun, info.m1, info.idquest, info.pci, info.eisa, info.raidnum);#endif return TRUE;}__initfunc (void eata2x_setup(char *str, int *ints)) { int i, argc = ints[0]; char *cur = str, *pc; if (argc > 0) { if (argc > MAX_INT_PARAM) argc = MAX_INT_PARAM; for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; io_port[i] = 0; setup_done = TRUE; } while (cur && (pc = strchr(cur, ':'))) { int val = 0, c = *++pc; if (c == 'n' || c == 'N') val = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -