hpt366.c
来自「linux 内核源代码」· C语言 代码 · 共 1,677 行 · 第 1/4 页
C
1,677 行
printk("%s: using %d MHz DPLL clock\n", name, dpll_clk); } else { /* Mark the fact that we're not using the DPLL. */ dpll_clk = 0; printk("%s: using %d MHz PCI clock\n", name, pci_clk); } /* * Advance the table pointer to a slot which points to the list * of the register values settings matching the clock being used. */ info->settings += clock; /* Store the clock frequencies. */ info->dpll_clk = dpll_clk; info->pci_clk = pci_clk; /* Point to this chip's own instance of the hpt_info structure. */ pci_set_drvdata(dev, info); if (chip_type >= HPT370) { u8 mcr1, mcr4; /* * Reset the state engines. * NOTE: Avoid accidentally enabling the disabled channels. */ pci_read_config_byte (dev, 0x50, &mcr1); pci_read_config_byte (dev, 0x54, &mcr4); pci_write_config_byte(dev, 0x50, (mcr1 | 0x32)); pci_write_config_byte(dev, 0x54, (mcr4 | 0x32)); udelay(100); } /* * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in * the MISC. register to stretch the UltraDMA Tss timing. * NOTE: This register is only writeable via I/O space. */ if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); return dev->irq;}static void __devinit init_hwif_hpt366(ide_hwif_t *hwif){ struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = pci_get_drvdata(dev); int serialize = HPT_SERIALIZE_IO; u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02; u8 chip_type = info->chip_type; u8 new_mcr, old_mcr = 0; /* Cache the channel's MISC. control registers' offset */ hwif->select_data = hwif->channel ? 0x54 : 0x50; hwif->set_pio_mode = &hpt3xx_set_pio_mode; hwif->set_dma_mode = &hpt3xx_set_mode; hwif->quirkproc = &hpt3xx_quirkproc; hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; hwif->busproc = &hpt3xx_busproc; hwif->udma_filter = &hpt3xx_udma_filter; hwif->mdma_filter = &hpt3xx_mdma_filter; /* * HPT3xxN chips have some complications: * * - on 33 MHz PCI we must clock switch * - on 66 MHz PCI we must NOT use the PCI clock */ if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) { /* * Clock is shared between the channels, * so we'll have to serialize them... :-( */ serialize = 1; hwif->rw_disk = &hpt3xxn_rw_disk; } /* Serialize access to this device if needed */ if (serialize && hwif->mate) hwif->serialized = hwif->mate->serialized = 1; /* * Disable the "fast interrupt" prediction. Don't hold off * on interrupts. (== 0x01 despite what the docs say) */ pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr); if (info->chip_type >= HPT374) new_mcr = old_mcr & ~0x07; else if (info->chip_type >= HPT370) { new_mcr = old_mcr; new_mcr &= ~0x02;#ifdef HPT_DELAY_INTERRUPT new_mcr &= ~0x01;#else new_mcr |= 0x01;#endif } else /* HPT366 and HPT368 */ new_mcr = old_mcr & ~0x80; if (new_mcr != old_mcr) pci_write_config_byte(dev, hwif->select_data + 1, new_mcr); if (hwif->dma_base == 0) return; /* * The HPT37x uses the CBLID pins as outputs for MA15/MA16 * address lines to access an external EEPROM. To read valid * cable detect state the pins must be enabled as inputs. */ if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { /* * HPT374 PCI function 1 * - set bit 15 of reg 0x52 to enable TCBLID as input * - set bit 15 of reg 0x56 to enable FCBLID as input */ u8 mcr_addr = hwif->select_data + 2; u16 mcr; pci_read_config_word (dev, mcr_addr, &mcr); pci_write_config_word(dev, mcr_addr, (mcr | 0x8000)); /* now read cable id register */ pci_read_config_byte (dev, 0x5a, &scr1); pci_write_config_word(dev, mcr_addr, mcr); } else if (chip_type >= HPT370) { /* * HPT370/372 and 374 pcifn 0 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs */ u8 scr2 = 0; pci_read_config_byte (dev, 0x5b, &scr2); pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); /* now read cable id register */ pci_read_config_byte (dev, 0x5a, &scr1); pci_write_config_byte(dev, 0x5b, scr2); } else pci_read_config_byte (dev, 0x5a, &scr1); if (hwif->cbl != ATA_CBL_PATA40_SHORT) hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80; if (chip_type >= HPT374) { hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; } else if (chip_type >= HPT370) { hwif->dma_start = &hpt370_ide_dma_start; hwif->ide_dma_end = &hpt370_ide_dma_end; hwif->dma_timeout = &hpt370_dma_timeout; } else hwif->dma_lost_irq = &hpt366_dma_lost_irq;}static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase){ struct pci_dev *dev = hwif->pci_dev; u8 masterdma = 0, slavedma = 0; u8 dma_new = 0, dma_old = 0; unsigned long flags; dma_old = inb(dmabase + 2); local_irq_save(flags); dma_new = dma_old; pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma); pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47, &slavedma); if (masterdma & 0x30) dma_new |= 0x20; if ( slavedma & 0x30) dma_new |= 0x40; if (dma_new != dma_old) outb(dma_new, dmabase + 2); local_irq_restore(flags); ide_setup_dma(hwif, dmabase, 8);}static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2){ if (dev2->irq != dev->irq) { /* FIXME: we need a core pci_set_interrupt() */ dev2->irq = dev->irq; printk(KERN_INFO "HPT374: PCI config space interrupt fixed\n"); }}static void __devinit hpt371_init(struct pci_dev *dev){ u8 mcr1 = 0; /* * HPT371 chips physically have only one channel, the secondary one, * but the primary channel registers do exist! Go figure... * So, we manually disable the non-existing channel here * (if the BIOS hasn't done this already). */ pci_read_config_byte(dev, 0x50, &mcr1); if (mcr1 & 0x04) pci_write_config_byte(dev, 0x50, mcr1 & ~0x04);}static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2){ u8 mcr1 = 0, pin1 = 0, pin2 = 0; /* * Now we'll have to force both channels enabled if * at least one of them has been enabled by BIOS... */ pci_read_config_byte(dev, 0x50, &mcr1); if (mcr1 & 0x30) pci_write_config_byte(dev, 0x50, mcr1 | 0x30); pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); if (pin1 != pin2 && dev->irq == dev2->irq) { printk(KERN_INFO "HPT36x: onboard version of chipset, " "pin1=%d pin2=%d\n", pin1, pin2); return 1; } return 0;}static const struct ide_port_info hpt366_chipsets[] __devinitdata = { { /* 0 */ .name = "HPT36x", .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, /* * HPT36x chips have one channel per function and have * both channel enable bits located differently and visible * to both functions -- really stupid design decision... :-( * Bit 4 is for the primary channel, bit 5 for the secondary. */ .enablebits = {{0x50,0x10,0x10}, {0x54,0x04,0x04}}, .extra = 240, .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 1 */ .name = "HPT372A", .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 2 */ .name = "HPT302", .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 3 */ .name = "HPT371", .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 4 */ .name = "HPT374", .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .udma_mask = ATA_UDMA5, .extra = 240, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, },{ /* 5 */ .name = "HPT372N", .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .extra = 240, .host_flags = IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, }};/** * hpt366_init_one - called when an HPT366 is found * @dev: the hpt366 device * @id: the matching pci id * * Called when the PCI registration layer (or the IDE initialization) * finds a device matching our IDE device tables. */static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id){ const struct hpt_info *info = NULL; struct pci_dev *dev2 = NULL; struct ide_port_info d; u8 idx = id->driver_data; u8 rev = dev->revision; if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1)) return -ENODEV; switch (idx) { case 0: if (rev < 3) info = &hpt36x; else { static const struct hpt_info *hpt37x_info[] = { &hpt370, &hpt370a, &hpt372, &hpt372n }; info = hpt37x_info[min_t(u8, rev, 6) - 3]; idx++; } break; case 1: info = (rev > 1) ? &hpt372n : &hpt372a; break; case 2: info = (rev > 1) ? &hpt302n : &hpt302; break; case 3: hpt371_init(dev); info = (rev > 1) ? &hpt371n : &hpt371; break; case 4: info = &hpt374; break; case 5: info = &hpt372n; break; } d = hpt366_chipsets[idx]; d.name = info->chip_name; d.udma_mask = info->udma_mask; pci_set_drvdata(dev, (void *)info); if (info == &hpt36x || info == &hpt374) dev2 = pci_get_slot(dev->bus, dev->devfn + 1); if (dev2) { int ret; pci_set_drvdata(dev2, (void *)info); if (info == &hpt374) hpt374_init(dev, dev2); else { if (hpt36x_init(dev, dev2)) d.host_flags |= IDE_HFLAG_BOOTABLE; } ret = ide_setup_pci_devices(dev, dev2, &d); if (ret < 0) pci_dev_put(dev2); return ret; } return ide_setup_pci_device(dev, &d);}static const struct pci_device_id hpt366_pci_tbl[] = { { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), 0 }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372), 1 }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT302), 2 }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT371), 3 }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT374), 4 }, { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT372N), 5 }, { 0, },};MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);static struct pci_driver driver = { .name = "HPT366_IDE", .id_table = hpt366_pci_tbl, .probe = hpt366_init_one,};static int __init hpt366_ide_init(void){ return ide_pci_register_driver(&driver);}module_init(hpt366_ide_init);MODULE_AUTHOR("Andre Hedrick");MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?