diff options
Diffstat (limited to 'drivers/ide/pci/hpt366.c')
-rw-r--r-- | drivers/ide/pci/hpt366.c | 302 |
1 files changed, 154 insertions, 148 deletions
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index c929dadaaaf..9cf171cb937 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -122,7 +122,6 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/blkdev.h> -#include <linux/hdreg.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/init.h> @@ -131,6 +130,8 @@ #include <asm/uaccess.h> #include <asm/io.h> +#define DRV_NAME "hpt366" + /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE #undef HPT_DELAY_INTERRUPT @@ -603,14 +604,22 @@ static const struct hpt_info hpt371n __devinitdata = { static int check_in_drive_list(ide_drive_t *drive, const char **list) { - struct hd_driveid *id = drive->id; + char *m = (char *)&drive->id[ATA_ID_PROD]; while (*list) - if (!strcmp(*list++,id->model)) + if (!strcmp(*list++, m)) return 1; return 0; } +static struct hpt_info *hpt3xx_get_info(struct device *dev) +{ + struct ide_host *host = dev_get_drvdata(dev); + struct hpt_info *info = (struct hpt_info *)host->host_priv; + + return dev == host->dev[1] ? info + 1 : info; +} + /* * The Marvell bridge chips used on the HighPoint SATA cards do not seem * to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes... @@ -619,8 +628,7 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) static u8 hpt3xx_udma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = pci_get_drvdata(dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); u8 mask = hwif->ultra_mask; switch (info->chip_type) { @@ -646,7 +654,7 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) case HPT372A: case HPT372N: case HPT374 : - if (ide_dev_is_sata(drive->id)) + if (ata_id_is_sata(drive->id)) mask &= ~0x0e; /* Fall thru */ default: @@ -659,15 +667,14 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) static u8 hpt3xx_mdma_filter(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = pci_get_drvdata(dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); switch (info->chip_type) { case HPT372 : case HPT372A: case HPT372N: case HPT374 : - if (ide_dev_is_sata(drive->id)) + if (ata_id_is_sata(drive->id)) return 0x00; /* Fall thru */ default: @@ -694,8 +701,9 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info) static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed) { - struct pci_dev *dev = to_pci_dev(drive->hwif->dev); - struct hpt_info *info = pci_get_drvdata(dev); + ide_hwif_t *hwif = drive->hwif; + struct pci_dev *dev = to_pci_dev(hwif->dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); struct hpt_timings *t = info->timings; u8 itr_addr = 0x40 + (drive->dn * 4); u32 old_itr = 0; @@ -722,11 +730,11 @@ static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio) static void hpt3xx_quirkproc(ide_drive_t *drive) { - struct hd_driveid *id = drive->id; + char *m = (char *)&drive->id[ATA_ID_PROD]; const char **list = quirk_drives; while (*list) - if (strstr(id->model, *list++)) { + if (strstr(m, *list++)) { drive->quirk_list = 1; return; } @@ -738,7 +746,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = pci_get_drvdata(dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); if (drive->quirk_list) { if (info->chip_type >= HPT370) { @@ -759,8 +767,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask) enable_irq (hwif->irq); } } else - outb(mask ? (drive->ctl | 2) : (drive->ctl & ~2), - hwif->io_ports.ctl_addr); + outb(ATA_DEVCTL_OBS | (mask ? 2 : 0), hwif->io_ports.ctl_addr); } /* @@ -802,9 +809,9 @@ static void hpt370_irq_timeout(ide_drive_t *drive) printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff); /* get DMA command mode */ - dma_cmd = inb(hwif->dma_command); + dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); /* stop DMA */ - outb(dma_cmd & ~0x1, hwif->dma_command); + outb(dma_cmd & ~0x1, hwif->dma_base + ATA_DMA_CMD); hpt370_clear_engine(drive); } @@ -819,16 +826,16 @@ static void hpt370_dma_start(ide_drive_t *drive) static int hpt370_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat = inb(hwif->dma_status); + u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); if (dma_stat & 0x01) { /* wait a little */ udelay(20); - dma_stat = inb(hwif->dma_status); + dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); if (dma_stat & 0x01) hpt370_irq_timeout(drive); } - return __ide_dma_end(drive); + return ide_dma_end(drive); } static void hpt370_dma_timeout(ide_drive_t *drive) @@ -851,14 +858,11 @@ static int hpt374_dma_test_irq(ide_drive_t *drive) return 0; } - dma_stat = inb(hwif->dma_status); + dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); /* return 1 if INTR asserted */ if (dma_stat & 4) return 1; - if (!drive->waiting_for_dma) - printk(KERN_WARNING "%s: (%s) called while not waiting\n", - drive->name, __func__); return 0; } @@ -873,7 +877,7 @@ static int hpt374_dma_end(ide_drive_t *drive) pci_read_config_byte(dev, mcr_addr, &mcr); if (bwsr & mask) pci_write_config_byte(dev, mcr_addr, mcr | 0x30); - return __ide_dma_end(drive); + return ide_dma_end(drive); } /** @@ -936,7 +940,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) * Perform a calibration cycle on the DPLL. * Returns 1 if this succeeds */ -static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) +static int hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) { u32 dpll = (f_high << 16) | f_low | 0x100; u8 scr2; @@ -964,24 +968,45 @@ static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f return 1; } -static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) +static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct hpt_info *info = host->host_priv + (&dev->dev == host->dev[1]); + u8 chip_type = info->chip_type; + u8 new_mcr, old_mcr = 0; + + /* + * Disable the "fast interrupt" prediction. Don't hold off + * on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, mcr_addr + 1, &old_mcr); + + if (chip_type >= HPT374) + new_mcr = old_mcr & ~0x07; + else if (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, mcr_addr + 1, new_mcr); +} + +static unsigned int init_chipset_hpt366(struct pci_dev *dev) { - struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); unsigned long io_base = pci_resource_start(dev, 4); + struct hpt_info *info = hpt3xx_get_info(&dev->dev); + const char *name = DRV_NAME; u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ u8 chip_type; enum ata_clock clock; - if (info == NULL) { - printk(KERN_ERR "%s: out of memory!\n", name); - return -ENOMEM; - } - - /* - * Copy everything from a static "template" structure - * to just allocated per-chip hpt_info structure. - */ - memcpy(info, pci_get_drvdata(dev), sizeof(struct hpt_info)); chip_type = info->chip_type; pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); @@ -1049,8 +1074,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha if ((temp & 0xFFFFF000) != 0xABCDE000) { int i; - printk(KERN_WARNING "%s: no clock data saved by BIOS\n", - name); + printk(KERN_WARNING "%s %s: no clock data saved by " + "BIOS\n", name, pci_name(dev)); /* Calculate the average value of f_CNT. */ for (temp = i = 0; i < 128; i++) { @@ -1075,8 +1100,9 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha else pci_clk = 66; - printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, " - "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk); + printk(KERN_INFO "%s %s: DPLL base: %d MHz, f_CNT: %d, " + "assuming %d MHz PCI\n", name, pci_name(dev), + dpll_clk, f_cnt, pci_clk); } else { u32 itr1 = 0; @@ -1142,8 +1168,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha } if (info->timings->clock_table[clock] == NULL) { - printk(KERN_ERR "%s: unknown bus timing!\n", name); - kfree(info); + printk(KERN_ERR "%s %s: unknown bus timing!\n", + name, pci_name(dev)); return -EIO; } @@ -1169,17 +1195,19 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha f_low += adjust >> 1; } if (adjust == 8) { - printk(KERN_ERR "%s: DPLL did not stabilize!\n", name); - kfree(info); + printk(KERN_ERR "%s %s: DPLL did not stabilize!\n", + name, pci_name(dev)); return -EIO; } - printk("%s: using %d MHz DPLL clock\n", name, dpll_clk); + printk(KERN_INFO "%s %s: using %d MHz DPLL clock\n", + name, pci_name(dev), 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); + printk(KERN_INFO "%s %s: using %d MHz PCI clock\n", + name, pci_name(dev), pci_clk); } /* Store the clock frequencies. */ @@ -1187,9 +1215,6 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha info->pci_clk = pci_clk; info->clock = clock; - /* Point to this chip's own instance of the hpt_info structure. */ - pci_set_drvdata(dev, info); - if (chip_type >= HPT370) { u8 mcr1, mcr4; @@ -1210,16 +1235,18 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha * 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); + hpt3xx_disable_fast_irq(dev, 0x50); + hpt3xx_disable_fast_irq(dev, 0x54); + return dev->irq; } -static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif) +static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = pci_get_drvdata(dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); u8 chip_type = info->chip_type; u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02; @@ -1263,10 +1290,9 @@ static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif) static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - struct hpt_info *info = pci_get_drvdata(dev); + struct hpt_info *info = hpt3xx_get_info(hwif->dev); int serialize = HPT_SERIALIZE_IO; 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; @@ -1289,29 +1315,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) /* 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); } static int __devinit init_dma_hpt366(ide_hwif_t *hwif, @@ -1321,7 +1324,15 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long flags, base = ide_pci_dma_base(hwif, d); u8 dma_old, dma_new, masterdma = 0, slavedma = 0; - if (base == 0 || ide_pci_set_master(dev, d->name) < 0) + if (base == 0) + return -1; + + hwif->dma_base = base; + + if (ide_pci_check_simplex(hwif, d) < 0) + return -1; + + if (ide_pci_set_master(dev, d->name) < 0) return -1; dma_old = inb(base + 2); @@ -1347,7 +1358,7 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif, if (ide_allocate_dma_engine(hwif)) return -1; - ide_setup_dma(hwif, base); + hwif->dma_ops = &sff_dma_ops; return 0; } @@ -1357,7 +1368,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"); + printk(KERN_INFO DRV_NAME " %s: PCI config space interrupt " + "fixed\n", pci_name(dev2)); } } @@ -1392,8 +1404,8 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) 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); + printk(KERN_INFO DRV_NAME " %s: onboard version of chipset, " + "pin1=%d pin2=%d\n", pci_name(dev), pin1, pin2); return 1; } @@ -1402,7 +1414,6 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2) #define IDE_HFLAGS_HPT3XX \ (IDE_HFLAG_NO_ATAPI_DMA | \ - IDE_HFLAG_ABUSE_SET_DMA_MODE | \ IDE_HFLAG_OFF_BOARD) static const struct ide_port_ops hpt3xx_port_ops = { @@ -1442,15 +1453,15 @@ static const struct ide_dma_ops hpt36x_dma_ops = { .dma_setup = ide_dma_setup, .dma_exec_cmd = ide_dma_exec_cmd, .dma_start = ide_dma_start, - .dma_end = __ide_dma_end, + .dma_end = ide_dma_end, .dma_test_irq = ide_dma_test_irq, .dma_lost_irq = hpt366_dma_lost_irq, .dma_timeout = ide_dma_timeout, }; static const struct ide_port_info hpt366_chipsets[] __devinitdata = { - { /* 0 */ - .name = "HPT36x", + { /* 0: HPT36x */ + .name = DRV_NAME, .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, @@ -1466,53 +1477,9 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { .host_flags = IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE, .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}}, - .port_ops = &hpt3xx_port_ops, - .dma_ops = &hpt37x_dma_ops, - .host_flags = IDE_HFLAGS_HPT3XX, - .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}}, - .port_ops = &hpt3xx_port_ops, - .dma_ops = &hpt37x_dma_ops, - .host_flags = IDE_HFLAGS_HPT3XX, - .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}}, - .port_ops = &hpt3xx_port_ops, - .dma_ops = &hpt37x_dma_ops, - .host_flags = IDE_HFLAGS_HPT3XX, - .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, - .port_ops = &hpt3xx_port_ops, - .dma_ops = &hpt37x_dma_ops, - .host_flags = IDE_HFLAGS_HPT3XX, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - },{ /* 5 */ - .name = "HPT372N", + }, + { /* 1: HPT3xx */ + .name = DRV_NAME, .init_chipset = init_chipset_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, @@ -1536,10 +1503,12 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = { static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) { const struct hpt_info *info = NULL; + struct hpt_info *dyn_info; struct pci_dev *dev2 = NULL; struct ide_port_info d; u8 idx = id->driver_data; u8 rev = dev->revision; + int ret; if ((idx == 0 || idx == 4) && (PCI_FUNC(dev->devfn) & 1)) return -ENODEV; @@ -1576,24 +1545,35 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic break; } - d = hpt366_chipsets[idx]; + printk(KERN_INFO DRV_NAME ": %s chipset detected\n", info->chip_name); + + d = hpt366_chipsets[min_t(u8, idx, 1)]; - d.name = info->chip_name; d.udma_mask = info->udma_mask; /* fixup ->dma_ops for HPT370/HPT370A */ if (info == &hpt370 || info == &hpt370a) d.dma_ops = &hpt370_dma_ops; - pci_set_drvdata(dev, (void *)info); - if (info == &hpt36x || info == &hpt374) dev2 = pci_get_slot(dev->bus, dev->devfn + 1); - if (dev2) { - int ret; + dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL); + if (dyn_info == NULL) { + printk(KERN_ERR "%s %s: out of memory!\n", + d.name, pci_name(dev)); + pci_dev_put(dev2); + return -ENOMEM; + } - pci_set_drvdata(dev2, (void *)info); + /* + * Copy everything from a static "template" structure + * to just allocated per-chip hpt_info structure. + */ + memcpy(dyn_info, info, sizeof(*dyn_info)); + + if (dev2) { + memcpy(dyn_info + 1, info, sizeof(*dyn_info)); if (info == &hpt374) hpt374_init(dev, dev2); @@ -1602,13 +1582,30 @@ static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_devic d.host_flags &= ~IDE_HFLAG_NON_BOOTABLE; } - ret = ide_setup_pci_devices(dev, dev2, &d); - if (ret < 0) + ret = ide_pci_init_two(dev, dev2, &d, dyn_info); + if (ret < 0) { pci_dev_put(dev2); + kfree(dyn_info); + } return ret; } - return ide_setup_pci_device(dev, &d); + ret = ide_pci_init_one(dev, &d, dyn_info); + if (ret < 0) + kfree(dyn_info); + + return ret; +} + +static void __devexit hpt366_remove(struct pci_dev *dev) +{ + struct ide_host *host = pci_get_drvdata(dev); + struct ide_info *info = host->host_priv; + struct pci_dev *dev2 = host->dev[1] ? to_pci_dev(host->dev[1]) : NULL; + + ide_pci_remove(dev); + pci_dev_put(dev2); + kfree(info); } static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = { @@ -1622,18 +1619,27 @@ static const struct pci_device_id hpt366_pci_tbl[] __devinitconst = { }; MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl); -static struct pci_driver driver = { +static struct pci_driver hpt366_pci_driver = { .name = "HPT366_IDE", .id_table = hpt366_pci_tbl, .probe = hpt366_init_one, + .remove = __devexit_p(hpt366_remove), + .suspend = ide_pci_suspend, + .resume = ide_pci_resume, }; static int __init hpt366_ide_init(void) { - return ide_pci_register_driver(&driver); + return ide_pci_register_driver(&hpt366_pci_driver); +} + +static void __exit hpt366_ide_exit(void) +{ + pci_unregister_driver(&hpt366_pci_driver); } module_init(hpt366_ide_init); +module_exit(hpt366_ide_exit); MODULE_AUTHOR("Andre Hedrick"); MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE"); |