eata.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,842 行 · 第 1/5 页
C
1,842 行
protocol_rev = 'B'; else protocol_rev = 'C'; if (protocol_rev != 'A' && info.forcaddr) { printk("%s: warning, port address has been forced.\n", name); bus_type = "PCI"; is_pci = TRUE; subversion = ESA; } else if (port_base > MAX_EISA_ADDR || (protocol_rev == 'C' && info.pci)) { bus_type = "PCI"; is_pci = TRUE; 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"; is_pci = TRUE; 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); goto freelock; } 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 (is_pci) { pdev = get_pci_dev(port_base); if (!pdev) printk("%s: warning, failed to get pci_dev structure.\n", name); } else pdev = NULL; if (pdev && (irq != pdev->irq)) { printk("%s: IRQ %u mapped to IO-APIC IRQ %u.\n", name, irq, pdev->irq); irq = pdev->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); goto freelock; } if (subversion == ISA && request_dma(dma_channel, driver_name)) { printk("%s: unable to allocate DMA channel %u, detaching.\n", name, dma_channel); goto freeirq; }#if defined(FORCE_CONFIG) { struct eata_config *cf; dma_addr_t cf_dma_addr; cf = pci_alloc_consistent(pdev, sizeof(struct eata_config), &cf_dma_addr); if (!cf) { printk("%s: config, pci_alloc_consistent failed, detaching.\n", name); goto freedma; } /* Set board configuration */ memset((char *)cf, 0, sizeof(struct eata_config)); cf->len = (ushort) H2DEV16((ushort)510); cf->ocena = TRUE; if (do_dma(port_base, cf_dma_addr, SET_CONFIG_DMA)) { printk("%s: busy timeout sending configuration, detaching.\n", name); pci_free_consistent(pdev, sizeof(struct eata_config), cf, cf_dma_addr); goto freedma; } }#endif spin_unlock_irq(&driver_lock); sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); spin_lock_irq(&driver_lock); if (sh[j] == NULL) { printk("%s: unable to register host, detaching.\n", name); goto freedma; } 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) info.scatt_size; sh[j]->this_id = (ushort) info.host_addr[3]; sh[j]->can_queue = (ushort) info.queue_size; sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; memset(HD(j), 0, sizeof(struct hostdata)); HD(j)->subversion = subversion; HD(j)->protocol_rev = protocol_rev; HD(j)->is_pci = is_pci; HD(j)->pdev = pdev; HD(j)->board_number = j; if (HD(j)->subversion == ESA) sh[j]->unchecked_isa_dma = FALSE; else { unsigned long flags; sh[j]->unchecked_isa_dma = TRUE; flags=claim_dma_lock(); disable_dma(dma_channel); clear_dma_ff(dma_channel); set_dma_mode(dma_channel, DMA_MODE_CASCADE); enable_dma(dma_channel); release_dma_lock(flags); } 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); spin_unlock_irq(&driver_lock); for (i = 0; i < sh[j]->can_queue; i++) HD(j)->cp[i].cp_dma_addr = pci_map_single(HD(j)->pdev, &HD(j)->cp[i], sizeof(struct mscp), PCI_DMA_BIDIRECTIONAL); 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); goto release; } if (! (HD(j)->sp_cpu_addr = pci_alloc_consistent(HD(j)->pdev, sizeof(struct mssp), &HD(j)->sp_dma_addr))) { printk("%s: pci_alloc_consistent failed, detaching.\n", BN(j)); goto release; } 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 (tag_mode != TAG_DISABLED && tag_mode != TAG_SIMPLE) tag_mode = TAG_ORDERED; if (j == 0) { printk("EATA/DMA 2.0x: Copyright (C) 1994-2003 Dario Ballabio.\n"); printk("%s config options -> tm:%d, lc:%c, mq:%d, rs:%c, et:%c, "\ "ip:%c, ep:%c, pp:%c.\n", driver_name, tag_mode, YESNO(linked_comm), max_queue_depth, YESNO(rev_scan), YESNO(ext_tran), YESNO(isa_probe), YESNO(eisa_probe), YESNO(pci_probe)); } 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 %d, cpl %d spl %d.\n", name, info.version, info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync, info.second, info.data_len, info.cp_len, 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 if (HD(j)->pdev) { pci_set_master(HD(j)->pdev); if (pci_set_dma_mask(HD(j)->pdev, 0xffffffff)) printk("%s: warning, pci_set_dma_mask failed.\n", BN(j)); } return TRUE;freedma: if (subversion == ISA) free_dma(dma_channel);freeirq: free_irq(irq, &sha[j]);freelock: spin_unlock_irq(&driver_lock); release_region(port_base, REGION_SIZE);fail: return FALSE;release: eata2x_release(sh[j]); return FALSE;}static void internal_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; else if (c == 'y' || c == 'Y') val = TRUE; else val = (int) simple_strtoul(pc, NULL, 0); if (!strncmp(cur, "lc:", 3)) linked_comm = val; else if (!strncmp(cur, "tm:", 3)) tag_mode = val; else if (!strncmp(cur, "tc:", 3)) tag_mode = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; else if (!strncmp(cur, "rs:", 3)) rev_scan = val; else if (!strncmp(cur, "ip:", 3)) isa_probe = val; else if (!strncmp(cur, "ep:", 3)) eisa_probe = val; else if (!strncmp(cur, "pp:", 3)) pci_probe = val; if ((cur = strchr(cur, ','))) ++cur; } return;}static int option_setup(char *str) { int ints[MAX_INT_PARAM]; char *cur = str; int i = 1; while (cur && isdigit(*cur) && i <= MAX_INT_PARAM) { ints[i++] = simple_strtoul(cur, NULL, 0); if ((cur = strchr(cur, ',')) != NULL) cur++; } ints[0] = i - 1; internal_setup(cur, ints); return 1;}static void add_pci_ports(void) {#if defined(CONFIG_PCI) unsigned int addr, k; struct pci_dev *dev = NULL; for (k = 0; k < MAX_PCI; k++) { if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break; if (pci_enable_device (dev)) {#if defined(DEBUG_PCI_DETECT) printk("%s: detect, bus %d, devfn 0x%x, pci_enable_device failed.\n", driver_name, dev->bus->number, dev->devfn);#endif continue; } addr = pci_resource_start (dev, 0);#if defined(DEBUG_PCI_DETECT) printk("%s: detect, seq. %d, bus %d, devfn 0x%x, addr 0x%x.\n", driver_name, k, dev->bus->number, dev->devfn, addr);#endif /* Order addresses according to rev_scan value */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?