X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fata%2Fpata_hpt37x.c;h=98b498b6907c441de3a2d95b6ce5df000a1ed943;hb=f47451c45fe0032ef491aaf3e0623fa0154e156d;hp=41d8312963474447feb7faf6284a80efaa00cc53;hpb=a473446856374668c4296db5256ca708ce8f7095;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 41d83129..98b498b 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -8,12 +8,10 @@ * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc - * Portions Copyright (C) 2005-2006 MontaVista Software, Inc. + * Portions Copyright (C) 2005-2009 MontaVista Software, Inc. * * TODO - * PLL mode - * Look into engine reset on timeout errors. Should not be - * required. + * Look into engine reset on timeout errors. Should not be required. */ #include @@ -26,7 +24,7 @@ #include #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.5" +#define DRV_VERSION "0.6.15" struct hpt_clock { u8 xfer_speed; @@ -41,25 +39,24 @@ struct hpt_chip { /* 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: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 * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file + * 13:17 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 + * 18:20 udma_cycle_time. Clock cycles for UDMA xfer. + * 21 CLK frequency for UDMA: 0=ATA clock, 1=dual ATA clock. + * 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 file * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. - * 31 FIFO enable. + * 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. Only for PIO. */ static struct hpt_clock hpt37x_timings_33[] = { @@ -283,9 +280,9 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask) if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33)) mask &= ~ATA_MASK_UDMA; if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) - mask &= ~(0x1F << ATA_SHIFT_UDMA); + mask &= ~(0xE0 << ATA_SHIFT_UDMA); } - return ata_pci_default_filter(adev, mask); + return mask; } /** @@ -297,133 +294,101 @@ static unsigned long hpt370_filter(struct ata_device *adev, unsigned long mask) static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask) { - if (adev->class != ATA_DEV_ATA) { + if (adev->class == ATA_DEV_ATA) { if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5)) - mask &= ~ (0x1F << ATA_SHIFT_UDMA); + mask &= ~(0xE0 << ATA_SHIFT_UDMA); } - return ata_pci_default_filter(adev, mask); + return mask; } /** - * hpt37x_pre_reset - reset the hpt37x bus - * @ap: ATA port to reset + * hpt37x_cable_detect - Detect the cable type + * @ap: ATA port to detect on * - * Perform the initial reset handling for the 370/372 and 374 func 0 + * Return the cable type attached to this port */ -static int hpt37x_pre_reset(struct ata_port *ap) +static int hpt37x_cable_detect(struct ata_port *ap) { - u8 scr2, ata66; struct pci_dev *pdev = to_pci_dev(ap->host->dev); - static const struct pci_bits hpt37x_enable_bits[] = { - { 0x50, 1, 0x04, 0x04 }, - { 0x54, 1, 0x04, 0x04 } - }; - if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) - return -ENOENT; + u8 scr2, ata66; pci_read_config_byte(pdev, 0x5B, &scr2); pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); + + udelay(10); /* debounce */ + /* Cable register now active */ pci_read_config_byte(pdev, 0x5A, &ata66); /* Restore state */ pci_write_config_byte(pdev, 0x5B, scr2); - if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; + if (ata66 & (2 >> ap->port_no)) + return ATA_CBL_PATA40; else - ap->cbl = ATA_CBL_PATA80; - - /* Reset the state machine */ - pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); - udelay(100); - - return ata_std_prereset(ap); + return ATA_CBL_PATA80; } /** - * hpt37x_error_handler - reset the hpt374 - * @ap: ATA port to reset + * hpt374_fn1_cable_detect - Detect the cable type + * @ap: ATA port to detect on * - * Perform probe for HPT37x, except for HPT374 channel 2 + * Return the cable type attached to this port */ -static void hpt37x_error_handler(struct ata_port *ap) +static int hpt374_fn1_cable_detect(struct ata_port *ap) { - ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - -static int hpt374_pre_reset(struct ata_port *ap) -{ - static const struct pci_bits hpt37x_enable_bits[] = { - { 0x50, 1, 0x04, 0x04 }, - { 0x54, 1, 0x04, 0x04 } - }; - u16 mcr3, mcr6; - u8 ata66; struct pci_dev *pdev = to_pci_dev(ap->host->dev); - - if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) - return -ENOENT; + unsigned int mcrbase = 0x50 + 4 * ap->port_no; + u16 mcr3; + u8 ata66; /* Do the extra channel work */ - pci_read_config_word(pdev, 0x52, &mcr3); - pci_read_config_word(pdev, 0x56, &mcr6); - /* Set bit 15 of 0x52 to enable TCBLID as input - Set bit 15 of 0x56 to enable FCBLID as input - */ - pci_write_config_word(pdev, 0x52, mcr3 | 0x8000); - pci_write_config_word(pdev, 0x56, mcr6 | 0x8000); + pci_read_config_word(pdev, mcrbase + 2, &mcr3); + /* Set bit 15 of 0x52 to enable TCBLID as input */ + pci_write_config_word(pdev, mcrbase + 2, mcr3 | 0x8000); pci_read_config_byte(pdev, 0x5A, &ata66); /* Reset TCBLID/FCBLID to output */ - pci_write_config_word(pdev, 0x52, mcr3); - pci_write_config_word(pdev, 0x56, mcr6); + pci_write_config_word(pdev, mcrbase + 2, mcr3); - if (ata66 & (1 << ap->port_no)) - ap->cbl = ATA_CBL_PATA40; + if (ata66 & (2 >> ap->port_no)) + return ATA_CBL_PATA40; else - ap->cbl = ATA_CBL_PATA80; - - /* Reset the state machine */ - pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); - udelay(100); - - return ata_std_prereset(ap); + return ATA_CBL_PATA80; } /** - * hpt374_error_handler - reset the hpt374 - * @classes: + * hpt37x_pre_reset - reset the hpt37x bus + * @link: ATA link to reset + * @deadline: deadline jiffies for the operation * - * The 374 cable detect is a little different due to the extra - * channels. The function 0 channels work like usual but function 1 - * is special + * Perform the initial reset handling for the HPT37x. */ -static void hpt374_error_handler(struct ata_port *ap) +static int hpt37x_pre_reset(struct ata_link *link, unsigned long deadline) { + struct ata_port *ap = link->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); + static const struct pci_bits hpt37x_enable_bits[] = { + { 0x50, 1, 0x04, 0x04 }, + { 0x54, 1, 0x04, 0x04 } + }; + if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) + return -ENOENT; - if (!(PCI_FUNC(pdev->devfn) & 1)) - hpt37x_error_handler(ap); - else - ata_bmdma_drive_eh(ap, hpt374_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} + /* Reset the state machine */ + pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); + udelay(100); -/** - * hpt370_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Perform PIO mode setup. - */ + return ata_sff_prereset(link, deadline); +} -static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) +static void hpt370_set_mode(struct ata_port *ap, struct ata_device *adev, + u8 mode) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, timing, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -435,63 +400,44 @@ static void hpt370_set_piomode(struct ata_port *ap, struct ata_device *adev) fast |= 0x01; pci_write_config_byte(pdev, addr2, fast); + /* Determine timing mask and find matching mode entry */ + if (mode < XFER_MW_DMA_0) + mask = 0xcfc3ffff; + else if (mode < XFER_UDMA_0) + mask = 0x31c001ff; + else + mask = 0x303c0000; + + timing = hpt37x_find_mode(ap, mode); + pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_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); + reg = (reg & ~mask) | (timing & mask); + pci_write_config_dword(pdev, addr1, reg); } - /** - * hpt370_set_dmamode - DMA timing setup + * hpt370_set_piomode - PIO setup * @ap: ATA interface - * @adev: Device being configured + * @adev: device on the interface * - * Set up the channel for MWDMA or UDMA modes. Much the same as with - * PIO, load the mode number and then set MWDMA or UDMA flag. + * Perform PIO mode setup. */ -static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) +static void hpt370_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); - fast &= ~0x02; - fast |= 0x01; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_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); + hpt370_set_mode(ap, adev, adev->pio_mode); } /** - * hpt370_bmdma_start - DMA engine begin - * @qc: ATA command + * hpt370_set_dmamode - DMA timing setup + * @ap: ATA interface + * @adev: Device being configured * - * The 370 and 370A want us to reset the DMA engine each time we - * use it. The 372 and later are fine. + * Set up the channel for MWDMA or UDMA modes. */ -static void hpt370_bmdma_start(struct ata_queued_cmd *qc) +static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev) { - struct ata_port *ap = qc->ap; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); - pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); - udelay(10); - ata_bmdma_start(qc); + hpt370_set_mode(ap, adev, adev->dma_mode); } /** @@ -505,24 +451,25 @@ static void hpt370_bmdma_stop(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); - u8 dma_stat = ioread8(ap->ioaddr.bmdma_addr + 2); - u8 dma_cmd; void __iomem *bmdma = ap->ioaddr.bmdma_addr; + u8 dma_stat = ioread8(bmdma + ATA_DMA_STATUS); + u8 dma_cmd; - if (dma_stat & 0x01) { + if (dma_stat & ATA_DMA_ACTIVE) { udelay(20); - dma_stat = ioread8(bmdma + 2); + dma_stat = ioread8(bmdma + ATA_DMA_STATUS); } - if (dma_stat & 0x01) { + if (dma_stat & ATA_DMA_ACTIVE) { /* Clear the engine */ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); udelay(10); /* Stop DMA */ - dma_cmd = ioread8(bmdma ); - iowrite8(dma_cmd & 0xFE, bmdma); + dma_cmd = ioread8(bmdma + ATA_DMA_CMD); + iowrite8(dma_cmd & ~ATA_DMA_START, bmdma + ATA_DMA_CMD); /* Clear Error */ - dma_stat = ioread8(bmdma + 2); - iowrite8(dma_stat | 0x06 , bmdma + 2); + dma_stat = ioread8(bmdma + ATA_DMA_STATUS); + iowrite8(dma_stat | ATA_DMA_INTR | ATA_DMA_ERR, + bmdma + ATA_DMA_STATUS); /* Clear the engine */ pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37); udelay(10); @@ -530,20 +477,12 @@ static void hpt370_bmdma_stop(struct ata_queued_cmd *qc) ata_bmdma_stop(qc); } -/** - * hpt372_set_piomode - PIO setup - * @ap: ATA interface - * @adev: device on the interface - * - * Perform PIO mode setup. - */ - -static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) +static void hpt372_set_mode(struct ata_port *ap, struct ata_device *adev, + u8 mode) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 addr1, addr2; - u32 reg; - u32 mode; + u32 reg, timing, mask; u8 fast; addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no); @@ -554,14 +493,32 @@ static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) fast &= ~0x07; pci_write_config_byte(pdev, addr2, fast); + /* Determine timing mask and find matching mode entry */ + if (mode < XFER_MW_DMA_0) + mask = 0xcfc3ffff; + else if (mode < XFER_UDMA_0) + mask = 0x31c001ff; + else + mask = 0x303c0000; + + timing = hpt37x_find_mode(ap, mode); + pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_find_mode(ap, adev->pio_mode); + reg = (reg & ~mask) | (timing & mask); + pci_write_config_dword(pdev, addr1, reg); +} - printk("Find mode for %d reports %X\n", adev->pio_mode, mode); - mode &= ~0x80000000; /* No FIFO in PIO */ - mode &= ~0x30070000; /* Leave config bits alone */ - reg &= 0x30070000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); +/** + * hpt372_set_piomode - PIO setup + * @ap: ATA interface + * @adev: device on the interface + * + * Perform PIO mode setup. + */ + +static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) +{ + hpt372_set_mode(ap, adev, adev->pio_mode); } /** @@ -569,33 +526,12 @@ static void hpt372_set_piomode(struct ata_port *ap, struct ata_device *adev) * @ap: ATA interface * @adev: Device being configured * - * Set up the channel for MWDMA or UDMA modes. Much the same as with - * PIO, load the mode number and then set MWDMA or UDMA flag. + * Set up the channel for MWDMA or UDMA modes. */ static void hpt372_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); - fast &= ~0x07; - pci_write_config_byte(pdev, addr2, fast); - - pci_read_config_dword(pdev, addr1, ®); - mode = hpt37x_find_mode(ap, adev->dma_mode); - printk("Find mode for DMA %d reports %X\n", adev->dma_mode, mode); - mode &= ~0xC0000000; /* Leave config bits alone */ - mode |= 0x80000000; /* FIFO in MWDMA or UDMA */ - reg &= 0xC0000000; /* Strip timing bits */ - pci_write_config_dword(pdev, addr1, reg | mode); + hpt372_set_mode(ap, adev, adev->dma_mode); } /** @@ -621,21 +557,7 @@ static void hpt37x_bmdma_stop(struct ata_queued_cmd *qc) static struct scsi_host_template hpt37x_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, - .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, - .slave_destroy = ata_scsi_slave_destroy, - .bios_param = ata_std_bios_param, + ATA_BMDMA_SHT(DRV_NAME), }; /* @@ -643,38 +565,15 @@ static struct scsi_host_template hpt37x_sht = { */ static struct ata_port_operations hpt370_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt370_set_piomode, - .set_dmamode = hpt370_set_dmamode, - .mode_filter = hpt370_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 = hpt37x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, + .inherits = &ata_bmdma_port_ops, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = hpt370_bmdma_start, .bmdma_stop = hpt370_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - - .data_xfer = ata_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .irq_ack = ata_irq_ack, - - .port_start = ata_port_start, + .mode_filter = hpt370_filter, + .cable_detect = hpt37x_cable_detect, + .set_piomode = hpt370_set_piomode, + .set_dmamode = hpt370_set_dmamode, + .prereset = hpt37x_pre_reset, }; /* @@ -682,38 +581,8 @@ static struct ata_port_operations hpt370_port_ops = { */ static struct ata_port_operations hpt370a_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt370_set_piomode, - .set_dmamode = hpt370_set_dmamode, + .inherits = &hpt370_port_ops, .mode_filter = hpt370a_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 = hpt37x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = hpt370_bmdma_start, - .bmdma_stop = hpt370_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - - .data_xfer = ata_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .irq_ack = ata_irq_ack, - - .port_start = ata_port_start, }; /* @@ -722,82 +591,29 @@ static struct ata_port_operations hpt370a_port_ops = { */ static struct ata_port_operations hpt372_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt372_set_piomode, - .set_dmamode = hpt372_set_dmamode, - .mode_filter = ata_pci_default_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 = hpt37x_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, + .inherits = &ata_bmdma_port_ops, - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, .bmdma_stop = hpt37x_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - - .data_xfer = ata_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .irq_ack = ata_irq_ack, - .port_start = ata_port_start, + .cable_detect = hpt37x_cable_detect, + .set_piomode = hpt372_set_piomode, + .set_dmamode = hpt372_set_dmamode, + .prereset = hpt37x_pre_reset, }; /* * Configuration for HPT374. Mode setting works like 372 and friends - * but we have a different cable detection procedure. + * but we have a different cable detection procedure for function 1. */ -static struct ata_port_operations hpt374_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt372_set_piomode, - .set_dmamode = hpt372_set_dmamode, - .mode_filter = ata_pci_default_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 = hpt374_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = hpt37x_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - - .data_xfer = ata_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .irq_ack = ata_irq_ack, - - .port_start = ata_port_start, +static struct ata_port_operations hpt374_fn1_port_ops = { + .inherits = &hpt372_port_ops, + .cable_detect = hpt374_fn1_cable_detect, + .prereset = hpt37x_pre_reset, }; /** - * htp37x_clock_slot - Turn timing to PC clock entry + * hpt37x_clock_slot - Turn timing to PC clock entry * @freq: Reported frequency timing * @base: Base timing * @@ -851,6 +667,26 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev) /* Never went stable */ return 0; } + +static u32 hpt374_read_freq(struct pci_dev *pdev) +{ + u32 freq; + unsigned long io_base = pci_resource_start(pdev, 4); + if (PCI_FUNC(pdev->devfn) & 1) { + struct pci_dev *pdev_0; + + pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1); + /* Someone hot plugged the controller on us ? */ + if (pdev_0 == NULL) + return 0; + io_base = pci_resource_start(pdev_0, 4); + freq = inl(io_base + 0x90); + pci_dev_put(pdev_0); + } else + freq = inl(io_base + 0x90); + return freq; +} + /** * hpt37x_init_one - Initialise an HPT37X/302 * @dev: PCI device @@ -886,137 +722,130 @@ static int hpt37x_calibrate_dpll(struct pci_dev *dev) static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { /* HPT370 - UDMA100 */ - static struct ata_port_info info_hpt370 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, + static const struct ata_port_info info_hpt370 = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ - static struct ata_port_info info_hpt370a = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, + static const struct ata_port_info info_hpt370a = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &hpt370a_port_ops }; /* HPT370 - UDMA100 */ - static struct ata_port_info info_hpt370_33 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x0f, + static const struct ata_port_info info_hpt370_33 = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ - static struct ata_port_info info_hpt370a_33 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x0f, + static const struct ata_port_info info_hpt370a_33 = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &hpt370a_port_ops }; /* HPT371, 372 and friends - UDMA133 */ - static struct ata_port_info info_hpt372 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, + static const struct ata_port_info info_hpt372 = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &hpt372_port_ops }; - /* HPT371, 372 and friends - UDMA100 at 50MHz clock */ - static struct ata_port_info info_hpt372_50 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, + /* HPT374 - UDMA100, function 1 uses different prereset method */ + static const struct ata_port_info info_hpt374_fn0 = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &hpt372_port_ops }; - /* HPT374 - UDMA133 */ - static struct ata_port_info info_hpt374 = { - .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, - .port_ops = &hpt374_port_ops + static const struct ata_port_info info_hpt374_fn1 = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + .port_ops = &hpt374_fn1_port_ops }; static const int MHz[4] = { 33, 40, 50, 66 }; - - struct ata_port_info *port_info[2]; - struct ata_port_info *port; - + void *private_data = NULL; + const struct ata_port_info *ppi[] = { NULL, NULL }; + u8 rev = dev->revision; u8 irqmask; - u32 class_rev; u8 mcr1; u32 freq; int prefer_dpll = 1; - + unsigned long iobase = pci_resource_start(dev, 4); const struct hpt_chip *chip_table; int clock_slot; + int rc; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xFF; + rc = pcim_enable_device(dev); + if (rc) + return rc; if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { /* May be a later chip in disguise. Check */ /* Older chips are in the HPT366 driver. Ignore them */ - if (class_rev < 3) + if (rev < 3) return -ENODEV; /* N series chips have their own driver. Ignore */ - if (class_rev == 6) + if (rev == 6) return -ENODEV; - switch(class_rev) { + switch(rev) { case 3: - port = &info_hpt370; + ppi[0] = &info_hpt370; chip_table = &hpt370; prefer_dpll = 0; break; case 4: - port = &info_hpt370a; + ppi[0] = &info_hpt370a; chip_table = &hpt370a; prefer_dpll = 0; break; case 5: - port = &info_hpt372; + ppi[0] = &info_hpt372; chip_table = &hpt372; break; default: - printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype please report (%d).\n", class_rev); + printk(KERN_ERR "pata_hpt37x: Unknown HPT366 " + "subtype, please report (%d).\n", rev); return -ENODEV; } } else { switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT372: /* 372N if rev >= 2*/ - if (class_rev >= 2) + if (rev >= 2) return -ENODEV; - port = &info_hpt372; + ppi[0] = &info_hpt372; chip_table = &hpt372a; break; case PCI_DEVICE_ID_TTI_HPT302: /* 302N if rev > 1 */ - if (class_rev > 1) + if (rev > 1) return -ENODEV; - port = &info_hpt372; + ppi[0] = &info_hpt372; /* Check this */ chip_table = &hpt302; break; case PCI_DEVICE_ID_TTI_HPT371: - if (class_rev > 1) + if (rev > 1) return -ENODEV; - port = &info_hpt372; + ppi[0] = &info_hpt372; chip_table = &hpt371; /* Single channel device, master is not present but the BIOS (or us for non x86) must mark it @@ -1027,7 +856,10 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) break; case PCI_DEVICE_ID_TTI_HPT374: chip_table = &hpt374; - port = &info_hpt374; + if (!(PCI_FUNC(dev->devfn) & 1)) + *ppi = &info_hpt374_fn0; + else + *ppi = &info_hpt374_fn1; break; default: printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device); @@ -1053,7 +885,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) */ pci_write_config_byte(dev, 0x5b, 0x23); - + /* * HighPoint does this for HPT372A. * NOTE: This register is only writeable via I/O space. @@ -1062,9 +894,16 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) outb(0x0e, iobase + 0x9c); /* Some devices do not let this value be accessed via PCI space - according to the old driver */ + according to the old driver. In addition we must use the value + from FN 0 on the HPT374 */ + + if (chip_table == &hpt374) { + freq = hpt374_read_freq(dev); + if (freq == 0) + return -ENODEV; + } else + freq = inl(iobase + 0x90); - freq = inl(iobase + 0x90); if ((freq >> 12) != 0xABCDE) { int i; u8 sr; @@ -1086,7 +925,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) * Turn the frequency check into a band and then find a timing * table to match it. */ - + clock_slot = hpt37x_clock_slot(freq, chip_table->base); if (chip_table->clocks[clock_slot] == NULL || prefer_dpll) { /* @@ -1096,56 +935,59 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) * use a 50MHz DPLL by choice */ unsigned int f_low, f_high; - int adjust; - - clock_slot = 2; - if (port->udma_mask & 0xE0) - clock_slot = 3; - - f_low = (MHz[clock_slot] * chip_table->base) / 192; + int dpll, adjust; + + /* Compute DPLL */ + dpll = (ppi[0]->udma_mask & 0xC0) ? 3 : 2; + + f_low = (MHz[clock_slot] * 48) / MHz[dpll]; f_high = f_low + 2; + if (clock_slot > 1) + f_high += 2; /* Select the DPLL clock. */ pci_write_config_byte(dev, 0x5b, 0x21); + pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); for(adjust = 0; adjust < 8; adjust++) { if (hpt37x_calibrate_dpll(dev)) break; /* See if it'll settle at a fractionally different clock */ - if ((adjust & 3) == 3) { - f_low --; - f_high ++; - } - pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); + if (adjust & 1) + f_low -= adjust >> 1; + else + f_high += adjust >> 1; + pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low | 0x100); } if (adjust == 8) { - printk(KERN_WARNING "hpt37x: DPLL did not stabilize.\n"); + printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n"); return -ENODEV; } - if (clock_slot == 3) - port->private_data = (void *)hpt37x_timings_66; + if (dpll == 3) + private_data = (void *)hpt37x_timings_66; else - port->private_data = (void *)hpt37x_timings_50; + private_data = (void *)hpt37x_timings_50; - printk(KERN_INFO "hpt37x: Bus clock %dMHz, using DPLL.\n", MHz[clock_slot]); + printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n", + MHz[clock_slot], MHz[dpll]); } else { - port->private_data = (void *)chip_table->clocks[clock_slot]; + private_data = (void *)chip_table->clocks[clock_slot]; /* * Perform a final fixup. Note that we will have used the * DPLL on the HPT372 which means we don't have to worry * about lack of UDMA133 support on lower clocks */ - if (clock_slot < 2 && port == &info_hpt370) - port = &info_hpt370_33; - if (clock_slot < 2 && port == &info_hpt370a) - port = &info_hpt370a_33; - printk(KERN_INFO "hpt37x: %s: Bus clock %dMHz.\n", chip_table->name, MHz[clock_slot]); + if (clock_slot < 2 && ppi[0] == &info_hpt370) + ppi[0] = &info_hpt370_33; + if (clock_slot < 2 && ppi[0] == &info_hpt370a) + ppi[0] = &info_hpt370a_33; + printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n", + chip_table->name, MHz[clock_slot]); } - port_info[0] = port_info[1] = port; /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); + return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data, 0); } static const struct pci_device_id hpt37x[] = {