X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fata%2Fpata_hpt3x3.c;h=f11a320337c00c52415b453d8e7638e3f6bda447;hb=3a4b7886ee59e122d359e1714ed89585a06645ad;hp=d928c91050345c6834baa7d4990f77673ed972b2;hpb=5be808467347fc99bdd216883c5dbd123d6ad9d6;p=linux-2.6 diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index d928c91050..f11a320337 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -23,7 +23,7 @@ #include #define DRV_NAME "pata_hpt3x3" -#define DRV_VERSION "0.4.3" +#define DRV_VERSION "0.5.3" /** * hpt3x3_set_piomode - PIO setup @@ -52,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 @@ -59,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) @@ -76,66 +80,39 @@ 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 |= (0x10 << dn); /* Ultra mode */ else - r2 |= 0x10 << dn; /* MWDMA */ + r2 |= (0x01 << dn); /* MWDMA */ pci_write_config_dword(pdev, 0x44, r1); pci_write_config_dword(pdev, 0x48, r2); } +#endif /* CONFIG_PATA_HPT3X3_DMA */ + +/** + * hpt3x3_atapi_dma - ATAPI DMA check + * @qc: Queued command + * + * Just say no - we don't do ATAPI DMA + */ + +static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc) +{ + return 1; +} 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, - .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), }; static struct ata_port_operations hpt3x3_port_ops = { - .port_disable = ata_port_disable, + .inherits = &ata_bmdma_port_ops, + .check_atapi_dma= hpt3x3_atapi_dma, + .cable_detect = ata_cable_40wire, .set_piomode = hpt3x3_set_piomode, +#if defined(CONFIG_PATA_HPT3X3_DMA) .set_dmamode = hpt3x3_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 = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .cable_detect = ata_cable_40wire, - - .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, - - .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, +#endif }; /** @@ -158,32 +135,82 @@ static void hpt3x3_init_chipset(struct pci_dev *dev) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } - /** * hpt3x3_init_one - Initialise an HPT343/363 - * @dev: PCI device + * @pdev: 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 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 *dev, const struct pci_device_id *id) +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 = { - .sht = &hpt3x3_sht, .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, +#if defined(CONFIG_PATA_HPT3X3_DMA) + /* Further debug needed */ .mwdma_mask = 0x07, .udma_mask = 0x07, +#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 }; - - hpt3x3_init_chipset(dev); - /* Now kick off ATA set up */ - return ata_pci_init_one(dev, ppi); + 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); } #ifdef CONFIG_PM