diff options
Diffstat (limited to 'drivers/ata/pata_hpt366.c')
| -rw-r--r-- | drivers/ata/pata_hpt366.c | 400 |
1 files changed, 174 insertions, 226 deletions
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index cf656ecbe50..cbc3de793d1 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -11,49 +11,45 @@ * * * TODO - * Maybe PLL mode - * Look into engine reset on timeout errors. Should not be - * required. + * Look into engine reset on timeout errors. Should not be required. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/init.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <scsi/scsi_host.h> #include <linux/libata.h> #define DRV_NAME "pata_hpt366" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.6.11" struct hpt_clock { - u8 xfer_speed; + u8 xfer_mode; u32 timing; }; /* key for bus clock timings * bit - * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file + * 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA. + * cycles = value + 1 + * 4:7 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA. + * cycles = value + 1 + * 8:11 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file + * 12:15 cmd_low_time. Active time of DIOW_/DIOR_ during task file * register access. - * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. - * during task file register access. - * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA - * xfer. - * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task + * 16:18 udma_cycle_time. Clock cycles for UDMA xfer? + * 19:21 pre_high_time. Time to initialize 1st cycle for PIO and MW DMA xfer. + * 22:24 cmd_pre_high_time. Time to initialize 1st PIO cycle for task file * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. + * 28 UDMA enable. + * 29 DMA enable. + * 30 PIO_MST enable. If set, the chip is in bus master mode during + * PIO xfer. * 31 FIFO enable. */ @@ -114,18 +110,45 @@ static const struct hpt_clock hpt366_25[] = { { 0, 0x01208585 } }; -static const char *bad_ata33[] = { - "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2", - "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", - "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", +/** + * hpt36x_find_mode - find the hpt36x timing + * @ap: ATA port + * @speed: transfer mode + * + * Return the 32bit register programming information for this channel + * that matches the speed provided. + */ + +static u32 hpt36x_find_mode(struct ata_port *ap, int speed) +{ + struct hpt_clock *clocks = ap->host->private_data; + + while (clocks->xfer_mode) { + if (clocks->xfer_mode == speed) + return clocks->timing; + clocks++; + } + BUG(); + return 0xffffffffU; /* silence compiler warning */ +} + +static const char * const bad_ata33[] = { + "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", + "Maxtor 90845U3", "Maxtor 90650U2", + "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", + "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2", + "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", + "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4", "Maxtor 90510D4", "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2", - "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", - "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", + "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", + "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4", + "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", + "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2", NULL }; -static const char *bad_ata66_4[] = { +static const char * const bad_ata66_4[] = { "IBM-DTLA-307075", "IBM-DTLA-307060", "IBM-DTLA-307045", @@ -144,31 +167,22 @@ static const char *bad_ata66_4[] = { NULL }; -static const char *bad_ata66_3[] = { +static const char * const bad_ata66_3[] = { "WDC AC310200R", NULL }; -static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, const char *list[]) +static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, + const char * const list[]) { - unsigned char model_num[40]; - char *s; - unsigned int len; + unsigned char model_num[ATA_ID_PROD_LEN + 1]; int i = 0; - ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); + ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - /* ATAPI specifies that empty space is blank-filled; remove blanks */ - while ((len > 0) && (s[len - 1] == ' ')) { - len--; - s[len] = 0; - } - - while(list[i] != NULL) { - if (!strncmp(list[i], s, len)) { - printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", + while (list[i] != NULL) { + if (!strcmp(list[i], model_num)) { + pr_warn("%s is not supported for %s\n", modestr, list[i]); return 1; } @@ -179,70 +193,66 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, cons /** * hpt366_filter - mode selection filter - * @ap: ATA interface * @adev: ATA device * * Block UDMA on devices that cause trouble with this controller. */ -static unsigned long hpt366_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) +static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask) { if (adev->class == ATA_DEV_ATA) { if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) mask &= ~ATA_MASK_UDMA; if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3)) - mask &= ~(0x07 << ATA_SHIFT_UDMA); + mask &= ~(0xF8 << ATA_SHIFT_UDMA); if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) - mask &= ~(0x0F << ATA_SHIFT_UDMA); - } - return ata_pci_default_filter(ap, adev, mask); -} + mask &= ~(0xF0 << ATA_SHIFT_UDMA); + } else if (adev->class == ATA_DEV_ATAPI) + mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); -/** - * hpt36x_find_mode - reset the hpt36x bus - * @ap: ATA port - * @speed: transfer mode - * - * Return the 32bit register programming information for this channel - * that matches the speed provided. - */ - -static u32 hpt36x_find_mode(struct ata_port *ap, int speed) -{ - struct hpt_clock *clocks = ap->host->private_data; - - while(clocks->xfer_speed) { - if (clocks->xfer_speed == speed) - return clocks->timing; - clocks++; - } - BUG(); - return 0xffffffffU; /* silence compiler warning */ + return mask; } -static int hpt36x_pre_reset(struct ata_port *ap) +static int hpt36x_cable_detect(struct ata_port *ap) { - u8 ata66; struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u8 ata66; + /* + * Each channel of pata_hpt366 occupies separate PCI function + * as the primary channel and bit1 indicates the cable type. + */ pci_read_config_byte(pdev, 0x5A, &ata66); - if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; - else - ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(ap); + if (ata66 & 2) + return ATA_CBL_PATA40; + return ATA_CBL_PATA80; } -/** - * hpt36x_error_handler - reset the hpt36x bus - * @ap: ATA port to reset - * - * Perform the reset handling for the 366/368 - */ - -static void hpt36x_error_handler(struct ata_port *ap) +static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev, + u8 mode) { - ata_bmdma_drive_eh(ap, hpt36x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); + struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u32 addr = 0x40 + 4 * adev->devno; + u32 mask, reg, t; + + /* determine timing mask and find matching clock entry */ + if (mode < XFER_MW_DMA_0) + mask = 0xc1f8ffff; + else if (mode < XFER_UDMA_0) + mask = 0x303800ff; + else + mask = 0x30070000; + + t = hpt36x_find_mode(ap, mode); + + /* + * Combine new mode bits with old config bits and disable + * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid + * problems handling I/O errors later. + */ + pci_read_config_dword(pdev, addr, ®); + reg = ((reg & ~mask) | (t & mask)) & ~0xc0000000; + pci_write_config_dword(pdev, addr, reg); } /** @@ -255,28 +265,7 @@ static void hpt36x_error_handler(struct ata_port *ap) static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - if (fast & 0x80) { - fast &= ~0x80; - pci_write_config_byte(pdev, addr2, fast); - } - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt36x_find_mode(ap, adev->pio_mode); - mode &= ~0x8000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); + hpt366_set_mode(ap, adev, adev->pio_mode); } /** @@ -290,46 +279,11 @@ static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev) static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev) { - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u32 addr1, addr2; - u32 reg; - u32 mode; - u8 fast; - - addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); - addr2 = 0x51 + 4 * ap->port_no; - - /* Fast interrupt prediction disable, hold off interrupt disable */ - pci_read_config_byte(pdev, addr2, &fast); - if (fast & 0x80) { - fast &= ~0x80; - pci_write_config_byte(pdev, addr2, fast); - } - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt36x_find_mode(ap, adev->dma_mode); - mode |= 0x8000000; /* FIFO in MWDMA or UDMA */ - mode &= ~0xC0000000; /* Leave config bits alone */ - reg &= 0xC0000000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); + hpt366_set_mode(ap, adev, adev->dma_mode); } static struct scsi_host_template hpt36x_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, - .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .emulated = ATA_SHT_EMULATED, - .use_clustering = ATA_SHT_USE_CLUSTERING, - .proc_name = DRV_NAME, - .dma_boundary = ATA_DMA_BOUNDARY, - .slave_configure = ata_scsi_slave_config, - .bios_param = ata_std_bios_param, + ATA_BMDMA_SHT(DRV_NAME), }; /* @@ -337,39 +291,34 @@ static struct scsi_host_template hpt36x_sht = { */ static struct ata_port_operations hpt366_port_ops = { - .port_disable = ata_port_disable, + .inherits = &ata_bmdma_port_ops, + .cable_detect = hpt36x_cable_detect, + .mode_filter = hpt366_filter, .set_piomode = hpt366_set_piomode, .set_dmamode = hpt366_set_dmamode, - .mode_filter = hpt366_filter, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt36x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, +}; - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, +/** + * hpt36x_init_chipset - common chip setup + * @dev: PCI device + * + * Perform the chip setup work that must be done at both init and + * resume time + */ - .data_xfer = ata_pio_data_xfer, +static void hpt36x_init_chipset(struct pci_dev *dev) +{ + u8 drive_fast; - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop -}; + pci_read_config_byte(dev, 0x51, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); +} /** * hpt36x_init_one - Initialise an HPT366/368 @@ -394,85 +343,84 @@ static struct ata_port_operations hpt366_port_ops = { static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct ata_port_info info_hpt366 = { - .sht = &hpt36x_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, + static const struct ata_port_info info_hpt366 = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &hpt366_port_ops }; - struct ata_port_info *port_info[2] = {&info_hpt366, &info_hpt366}; + const struct ata_port_info *ppi[] = { &info_hpt366, NULL }; - u32 class_rev; + void *hpriv = NULL; u32 reg1; - u8 drive_fast; + int rc; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xFF; + rc = pcim_enable_device(dev); + if (rc) + return rc; /* May be a later chip in disguise. Check */ /* Newer chips are not in the HPT36x driver. Ignore them */ - if (class_rev > 2) - return -ENODEV; - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + if (dev->revision > 2) + return -ENODEV; - pci_read_config_byte(dev, 0x51, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); + hpt36x_init_chipset(dev); pci_read_config_dword(dev, 0x40, ®1); /* PCI clocking determines the ATA timing values to use */ /* info_hpt366 is safe against re-entry so we can scribble on it */ - switch(reg1 & 0x700) { - case 5: - info_hpt366.private_data = &hpt366_40; - break; - case 9: - info_hpt366.private_data = &hpt366_25; - break; - default: - info_hpt366.private_data = &hpt366_33; - break; + switch ((reg1 & 0x700) >> 8) { + case 9: + hpriv = &hpt366_40; + break; + case 5: + hpriv = &hpt366_25; + break; + default: + hpriv = &hpt366_33; + break; } /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0); } -static struct pci_device_id hpt36x[] = { - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366), }, - { 0, }, +#ifdef CONFIG_PM_SLEEP +static int hpt36x_reinit_one(struct pci_dev *dev) +{ + struct ata_host *host = pci_get_drvdata(dev); + int rc; + + rc = ata_pci_device_do_resume(dev); + if (rc) + return rc; + hpt36x_init_chipset(dev); + ata_host_resume(host); + return 0; +} +#endif + +static const struct pci_device_id hpt36x[] = { + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), }, + { }, }; static struct pci_driver hpt36x_pci_driver = { - .name = DRV_NAME, + .name = DRV_NAME, .id_table = hpt36x, - .probe = hpt36x_init_one, - .remove = ata_pci_remove_one + .probe = hpt36x_init_one, + .remove = ata_pci_remove_one, +#ifdef CONFIG_PM_SLEEP + .suspend = ata_pci_device_suspend, + .resume = hpt36x_reinit_one, +#endif }; -static int __init hpt36x_init(void) -{ - return pci_register_driver(&hpt36x_pci_driver); -} - - -static void __exit hpt36x_exit(void) -{ - pci_unregister_driver(&hpt36x_pci_driver); -} - +module_pci_driver(hpt36x_pci_driver); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for the Highpoint HPT366/368"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, hpt36x); MODULE_VERSION(DRV_VERSION); - -module_init(hpt36x_init); -module_exit(hpt36x_exit); |
