X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fata%2Fpata_serverworks.c;h=9524d54035f70288d2bd3f114ca69b235da2a2f6;hb=304a204ec9d4b9b31f3491e736bfbba44feaa1b0;hp=f02b6a3b0f10fed4dd1b30eecc7cf93b6cee0a88;hpb=2eab80ac0c96fb98267afeb12a4899801564c75b;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index f02b6a3..9524d54 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -1,7 +1,7 @@ /* - * ata-serverworks.c - Serverworks PATA for new ATA layer + * pata_serverworks.c - Serverworks PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox + * (C) 2010 Bartlomiej Zolnierkiewicz * * based upon * @@ -41,7 +41,7 @@ #include #define DRV_NAME "pata_serverworks" -#define DRV_VERSION "0.3.9" +#define DRV_VERSION "0.4.3" #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ #define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ @@ -102,7 +102,7 @@ static int osb4_cable(struct ata_port *ap) { } /** - * csb4_cable - CSB5/6 cable detect + * csb_cable - CSB5/6 cable detect * @ap: ATA port to check * * Serverworks default arrangement is to use the drive side detection @@ -110,7 +110,7 @@ static int osb4_cable(struct ata_port *ap) { */ static int csb_cable(struct ata_port *ap) { - return ATA_CBL_PATA80; + return ATA_CBL_PATA_UNK; } struct sv_cable_table { @@ -137,14 +137,15 @@ static struct sv_cable_table cable_detect[] = { }; /** - * serverworks_pre_reset - cable detection + * serverworks_cable_detect - cable detection * @ap: ATA port * * Perform cable detection according to the device and subvendor * identifications */ -static int serverworks_pre_reset(struct ata_port *ap) { +static int serverworks_cable_detect(struct ata_port *ap) +{ struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct sv_cable_table *cb = cable_detect; @@ -152,8 +153,7 @@ static int serverworks_pre_reset(struct ata_port *ap) { if (cb->device == pdev->device && (cb->subvendor == pdev->subsystem_vendor || cb->subvendor == PCI_ANY_ID)) { - ap->cbl = cb->cable_detect(ap); - return ata_std_prereset(ap); + return cb->cable_detect(ap); } cb++; } @@ -162,11 +162,6 @@ static int serverworks_pre_reset(struct ata_port *ap) { return -1; /* kill compiler warning */ } -static void serverworks_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, serverworks_pre_reset, ata_std_softreset, NULL, ata_std_postreset); -} - /** * serverworks_is_csb - Check for CSB or OSB * @pdev: PCI device to check @@ -191,58 +186,50 @@ static u8 serverworks_is_csb(struct pci_dev *pdev) /** * serverworks_osb4_filter - mode selection filter - * @ap: ATA interface * @adev: ATA device + * @mask: Mask of proposed modes * * Filter the offered modes for the device to apply controller * specific rules. OSB4 requires no UDMA for disks due to a FIFO * bug we hit. */ -static unsigned long serverworks_osb4_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) +static unsigned long serverworks_osb4_filter(struct ata_device *adev, unsigned long mask) { if (adev->class == ATA_DEV_ATA) mask &= ~ATA_MASK_UDMA; - return ata_pci_default_filter(ap, adev, mask); + return ata_bmdma_mode_filter(adev, mask); } /** * serverworks_csb_filter - mode selection filter - * @ap: ATA interface * @adev: ATA device + * @mask: Mask of proposed modes * * Check the blacklist and disable UDMA5 if matched */ -static unsigned long serverworks_csb_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long mask) +static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned long mask) { const char *p; - char model_num[40]; - int len, i; + char model_num[ATA_ID_PROD_LEN + 1]; + int i; /* Disk, UDMA */ if (adev->class != ATA_DEV_ATA) - return ata_pci_default_filter(ap, adev, mask); + return ata_bmdma_mode_filter(adev, mask); /* Actually do need to check */ - ata_id_string(adev->id, model_num, ATA_ID_PROD_OFS, sizeof(model_num)); - /* Precuationary - why not do this in the libata core ?? */ - - len = strlen(model_num); - while ((len > 0) && (model_num[len - 1] == ' ')) { - len--; - model_num[len] = 0; - } + ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num)); - for(i = 0; (p = csb_bad_ata100[i]) != NULL; i++) { - if (!strncmp(p, model_num, len)) - mask &= ~(0x1F << ATA_SHIFT_UDMA); + for (i = 0; (p = csb_bad_ata100[i]) != NULL; i++) { + if (!strcmp(p, model_num)) + mask &= ~(0xE0 << ATA_SHIFT_UDMA); } - return ata_pci_default_filter(ap, adev, mask); + return ata_bmdma_mode_filter(adev, mask); } - /** * serverworks_set_piomode - set initial PIO mode data * @ap: ATA interface @@ -254,7 +241,7 @@ static unsigned long serverworks_csb_filter(const struct ata_port *ap, struct at static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev) { static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; - int offset = 1 + (2 * ap->port_no) - adev->devno; + int offset = 1 + 2 * ap->port_no - adev->devno; int devbits = (2 * ap->port_no + adev->devno) * 4; u16 csb5_pio; struct pci_dev *pdev = to_pci_dev(ap->host->dev); @@ -267,7 +254,7 @@ static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev if (serverworks_is_csb(pdev)) { pci_read_config_word(pdev, 0x4A, &csb5_pio); csb5_pio &= ~(0x0F << devbits); - pci_write_config_byte(pdev, 0x4A, csb5_pio | (pio << devbits)); + pci_write_config_word(pdev, 0x4A, csb5_pio | (pio << devbits)); } } @@ -285,119 +272,45 @@ static void serverworks_set_dmamode(struct ata_port *ap, struct ata_device *adev { static const u8 dma_mode[] = { 0x77, 0x21, 0x20 }; int offset = 1 + 2 * ap->port_no - adev->devno; - int devbits = (2 * ap->port_no + adev->devno); + int devbits = 2 * ap->port_no + adev->devno; u8 ultra; u8 ultra_cfg; struct pci_dev *pdev = to_pci_dev(ap->host->dev); pci_read_config_byte(pdev, 0x54, &ultra_cfg); + pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra); + ultra &= ~(0x0F << (adev->devno * 4)); if (adev->dma_mode >= XFER_UDMA_0) { pci_write_config_byte(pdev, 0x44 + offset, 0x20); - pci_read_config_byte(pdev, 0x56 + ap->port_no, &ultra); - ultra &= ~(0x0F << (ap->port_no * 4)); ultra |= (adev->dma_mode - XFER_UDMA_0) - << (ap->port_no * 4); - pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra); - + << (adev->devno * 4); ultra_cfg |= (1 << devbits); } else { pci_write_config_byte(pdev, 0x44 + offset, dma_mode[adev->dma_mode - XFER_MW_DMA_0]); ultra_cfg &= ~(1 << devbits); } + pci_write_config_byte(pdev, 0x56 + ap->port_no, ultra); pci_write_config_byte(pdev, 0x54, ultra_cfg); } static struct scsi_host_template serverworks_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, - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, + ATA_BMDMA_SHT(DRV_NAME), }; static struct ata_port_operations serverworks_osb4_port_ops = { - .port_disable = ata_port_disable, + .inherits = &ata_bmdma_port_ops, + .cable_detect = serverworks_cable_detect, + .mode_filter = serverworks_osb4_filter, .set_piomode = serverworks_set_piomode, .set_dmamode = serverworks_set_dmamode, - .mode_filter = serverworks_osb4_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 = serverworks_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, - - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop }; static struct ata_port_operations serverworks_csb_port_ops = { - .port_disable = ata_port_disable, - .set_piomode = serverworks_set_piomode, - .set_dmamode = serverworks_set_dmamode, + .inherits = &serverworks_osb4_port_ops, .mode_filter = serverworks_csb_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 = serverworks_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, - - .data_xfer = ata_pio_data_xfer, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop }; static int serverworks_fixup_osb4(struct pci_dev *pdev) @@ -415,17 +328,14 @@ static int serverworks_fixup_osb4(struct pci_dev *pdev) pci_dev_put(isa_dev); return 0; } - printk(KERN_WARNING "ata_serverworks: Unable to find bridge.\n"); + printk(KERN_WARNING DRV_NAME ": Unable to find bridge.\n"); return -ENODEV; } static int serverworks_fixup_csb(struct pci_dev *pdev) { - u8 rev; u8 btr; - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); - /* Third Channel Test */ if (!(PCI_FUNC(pdev->devfn) & 1)) { struct pci_dev * findev = NULL; @@ -467,7 +377,7 @@ static int serverworks_fixup_csb(struct pci_dev *pdev) if (!(PCI_FUNC(pdev->devfn) & 1)) btr |= 0x2; else - btr |= (rev >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; + btr |= (pdev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; pci_write_config_byte(pdev, 0x5A, btr); return btr; @@ -486,40 +396,39 @@ static void serverworks_fixup_ht1000(struct pci_dev *pdev) static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { - int ports = 2; - static struct ata_port_info info[4] = { + static const struct ata_port_info info[4] = { { /* OSB4 */ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &serverworks_osb4_port_ops }, { /* OSB4 no UDMA */ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x00, + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + /* No UDMA */ .port_ops = &serverworks_osb4_port_ops }, { /* CSB5 */ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x1f, + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &serverworks_csb_port_ops }, { /* CSB5 - later revisions*/ - .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x3f, + .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &serverworks_csb_port_ops } }; - static struct ata_port_info *port_info[2]; - struct ata_port_info *devinfo = &info[id->driver_data]; + const struct ata_port_info *ppi[] = { &info[id->driver_data], NULL }; + int rc; + + rc = pcim_enable_device(pdev); + if (rc) + return rc; /* Force master latency timer to 64 PCI clocks */ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); @@ -528,7 +437,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { /* Select non UDMA capable OSB4 if we can't do fixups */ if ( serverworks_fixup_osb4(pdev) < 0) - devinfo = &info[1]; + ppi[0] = &info[1]; } /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ else if ((pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || @@ -538,35 +447,41 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id /* If the returned btr is the newer revision then select the right info block */ if (serverworks_fixup_csb(pdev) == 3) - devinfo = &info[3]; + ppi[0] = &info[3]; /* Is this the 3rd channel CSB6 IDE ? */ if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) - ports = 1; + ppi[1] = &ata_dummy_port_info; } /* setup HT1000E */ else if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE) serverworks_fixup_ht1000(pdev); if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) - ata_pci_clear_simplex(pdev); + ata_pci_bmdma_clear_simplex(pdev); - port_info[0] = port_info[1] = devinfo; - return ata_pci_init_one(pdev, port_info, ports); + return ata_pci_sff_init_one(pdev, ppi, &serverworks_sht, NULL, 0); } +#ifdef CONFIG_PM static int serverworks_reinit_one(struct pci_dev *pdev) { + struct ata_host *host = dev_get_drvdata(&pdev->dev); + int rc; + + rc = ata_pci_device_do_resume(pdev); + if (rc) + return rc; + /* Force master latency timer to 64 PCI clocks */ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40); - - switch (pdev->device) - { + + switch (pdev->device) { case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: serverworks_fixup_osb4(pdev); break; case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - ata_pci_clear_simplex(pdev); + ata_pci_bmdma_clear_simplex(pdev); /* fall through */ case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: @@ -576,8 +491,11 @@ static int serverworks_reinit_one(struct pci_dev *pdev) serverworks_fixup_ht1000(pdev); break; } - return ata_pci_device_resume(pdev); + + ata_host_resume(host); + return 0; } +#endif static const struct pci_device_id serverworks[] = { { PCI_VDEVICE(SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0}, @@ -594,8 +512,10 @@ static struct pci_driver serverworks_pci_driver = { .id_table = serverworks, .probe = serverworks_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM .suspend = ata_pci_device_suspend, .resume = serverworks_reinit_one, +#endif }; static int __init serverworks_init(void)