X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fata%2Fpata_hpt3x3.c;h=c86c71639a95bef1c16e8b2ec312070aa479d74f;hb=d7f81c4416a2246c8f03441d52a219af7c109850;hp=1f084ab1ccc6a65d6081c056ef7565b994e4895e;hpb=bda3028813bd07f34f30288a492fbf6f7b8712dd;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index 1f084ab..c86c716 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -23,26 +23,7 @@ #include #define DRV_NAME "pata_hpt3x3" -#define DRV_VERSION "0.4.1" - -static int hpt3x3_probe_init(struct ata_port *ap) -{ - ap->cbl = ATA_CBL_PATA40; - return ata_std_prereset(ap); -} - -/** - * hpt3x3_probe_reset - reset the hpt3x3 bus - * @ap: ATA port to reset - * - * Perform the housekeeping when doing an ATA bus reeset. We just - * need to force the cable type. - */ - -static void hpt3x3_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, hpt3x3_probe_init, ata_std_softreset, NULL, ata_std_postreset); -} +#define DRV_VERSION "0.6.1" /** * hpt3x3_set_piomode - PIO setup @@ -71,6 +52,7 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev) pci_write_config_dword(pdev, 0x48, r2); } +#if defined(CONFIG_PATA_HPT3X3_DMA) /** * hpt3x3_set_dmamode - DMA timing setup * @ap: ATA interface @@ -78,6 +60,9 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev) * * 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. + * + * 0x44 : bit 0-2 master mode, 3-5 slave mode, etc + * 0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc */ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) @@ -95,90 +80,90 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev) r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */ if (adev->dma_mode >= XFER_UDMA_0) - r2 |= 0x01 << dn; /* Ultra mode */ + r2 |= (0x01 << dn); /* Ultra mode */ else - r2 |= 0x10 << dn; /* MWDMA */ + r2 |= (0x10 << dn); /* MWDMA */ pci_write_config_dword(pdev, 0x44, r1); pci_write_config_dword(pdev, 0x48, r2); } -static struct scsi_host_template hpt3x3_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, -}; +/** + * hpt3x3_freeze - DMA workaround + * @ap: port to freeze + * + * When freezing an HPT3x3 we must stop any pending DMA before + * writing to the control register or the chip will hang + */ -static struct ata_port_operations hpt3x3_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = hpt3x3_set_piomode, - .set_dmamode = hpt3x3_set_dmamode, - .mode_filter = ata_pci_default_filter, +static void hpt3x3_freeze(struct ata_port *ap) +{ + void __iomem *mmio = ap->ioaddr.bmdma_addr; - .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, + iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ ATA_DMA_START, + mmio + ATA_DMA_CMD); + ata_sff_dma_pause(ap); + ata_sff_freeze(ap); +} - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = hpt3x3_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, +/** + * hpt3x3_bmdma_setup - DMA workaround + * @qc: Queued command + * + * When issuing BMDMA we must clean up the error/active bits in + * software on this device + */ - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, +static void hpt3x3_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + u8 r = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + r |= ATA_DMA_INTR | ATA_DMA_ERR; + iowrite8(r, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + return ata_bmdma_setup(qc); +} - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, +/** + * hpt3x3_atapi_dma - ATAPI DMA check + * @qc: Queued command + * + * Just say no - we don't do ATAPI DMA + */ - .data_xfer = ata_pio_data_xfer, +static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc) +{ + return 1; +} + +#endif /* CONFIG_PATA_HPT3X3_DMA */ - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, +static struct scsi_host_template hpt3x3_sht = { + ATA_BMDMA_SHT(DRV_NAME), +}; - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop +static struct ata_port_operations hpt3x3_port_ops = { + .inherits = &ata_bmdma_port_ops, + .cable_detect = ata_cable_40wire, + .set_piomode = hpt3x3_set_piomode, +#if defined(CONFIG_PATA_HPT3X3_DMA) + .set_dmamode = hpt3x3_set_dmamode, + .bmdma_setup = hpt3x3_bmdma_setup, + .check_atapi_dma= hpt3x3_atapi_dma, + .freeze = hpt3x3_freeze, +#endif + }; /** - * hpt3x3_init_one - Initialise an HPT343/363 + * hpt3x3_init_chipset - chip setup * @dev: PCI device - * @id: Entry in match table * - * Perform basic initialisation. The chip has a quirk that it won't - * function unless it is at XX00. The old ATA driver touched this up - * but we leave it for pci quirks to do properly. + * Perform the setup required at boot and on resume. */ -static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) +static void hpt3x3_init_chipset(struct pci_dev *dev) { - static struct ata_port_info info = { - .sht = &hpt3x3_sht, - .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, - .port_ops = &hpt3x3_port_ops - }; - static struct ata_port_info *port_info[2] = { &info, &info }; u16 cmd; - /* Initialize the board */ pci_write_config_word(dev, 0x80, 0x00); /* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */ @@ -187,21 +172,118 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); else pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); +} - /* Now kick off ATA set up */ - return ata_pci_init_one(dev, port_info, 2); +/** + * hpt3x3_init_one - Initialise an HPT343/363 + * @pdev: PCI device + * @id: Entry in match table + * + * Perform basic initialisation. We set the device up so we access all + * ports via BAR4. This is neccessary to work around errata. + */ + +static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + static int printed_version; + static const struct ata_port_info info = { + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, +#if defined(CONFIG_PATA_HPT3X3_DMA) + /* Further debug needed */ + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, +#endif + .port_ops = &hpt3x3_port_ops + }; + /* Register offsets of taskfiles in BAR4 area */ + static const u8 offset_cmd[2] = { 0x20, 0x28 }; + static const u8 offset_ctl[2] = { 0x36, 0x3E }; + const struct ata_port_info *ppi[] = { &info, NULL }; + struct ata_host *host; + int i, rc; + void __iomem *base; + + hpt3x3_init_chipset(pdev); + + if (!printed_version++) + dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); + + host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2); + if (!host) + return -ENOMEM; + /* acquire resources and fill host */ + rc = pcim_enable_device(pdev); + if (rc) + return rc; + + /* Everything is relative to BAR4 if we set up this way */ + rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME); + if (rc == -EBUSY) + pcim_pin_device(pdev); + if (rc) + return rc; + host->iomap = pcim_iomap_table(pdev); + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + return rc; + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + return rc; + + base = host->iomap[4]; /* Bus mastering base */ + + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + struct ata_ioports *ioaddr = &ap->ioaddr; + + ioaddr->cmd_addr = base + offset_cmd[i]; + ioaddr->altstatus_addr = + ioaddr->ctl_addr = base + offset_ctl[i]; + ioaddr->scr_addr = NULL; + ata_sff_std_ports(ioaddr); + ioaddr->bmdma_addr = base + 8 * i; + + ata_port_pbar_desc(ap, 4, -1, "ioport"); + ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd"); + } + pci_set_master(pdev); + return ata_host_activate(host, pdev->irq, ata_sff_interrupt, + IRQF_SHARED, &hpt3x3_sht); } -static struct pci_device_id hpt3x3[] = { - { PCI_DEVICE(PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343), }, - { 0, }, +#ifdef CONFIG_PM +static int hpt3x3_reinit_one(struct pci_dev *dev) +{ + struct ata_host *host = dev_get_drvdata(&dev->dev); + int rc; + + rc = ata_pci_device_do_resume(dev); + if (rc) + return rc; + + hpt3x3_init_chipset(dev); + + ata_host_resume(host); + return 0; +} +#endif + +static const struct pci_device_id hpt3x3[] = { + { PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), }, + + { }, }; static struct pci_driver hpt3x3_pci_driver = { - .name = DRV_NAME, + .name = DRV_NAME, .id_table = hpt3x3, .probe = hpt3x3_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, +#ifdef CONFIG_PM + .suspend = ata_pci_device_suspend, + .resume = hpt3x3_reinit_one, +#endif }; static int __init hpt3x3_init(void)