diff options
Diffstat (limited to 'drivers/ata/pata_pcmcia.c')
-rw-r--r-- | drivers/ata/pata_pcmcia.c | 77 |
1 files changed, 56 insertions, 21 deletions
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 103720f873c8..75dc84797ff3 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
@@ -42,7 +42,7 @@ | |||
42 | 42 | ||
43 | 43 | ||
44 | #define DRV_NAME "pata_pcmcia" | 44 | #define DRV_NAME "pata_pcmcia" |
45 | #define DRV_VERSION "0.3.0" | 45 | #define DRV_VERSION "0.3.1" |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Private data structure to glue stuff together | 48 | * Private data structure to glue stuff together |
@@ -54,6 +54,39 @@ struct ata_pcmcia_info { | |||
54 | dev_node_t node; | 54 | dev_node_t node; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | /** | ||
58 | * pcmcia_set_mode - PCMCIA specific mode setup | ||
59 | * @ap: Port | ||
60 | * @r_failed_dev: Return pointer for failed device | ||
61 | * | ||
62 | * Perform the tuning and setup of the devices and timings, which | ||
63 | * for PCMCIA is the same as any other controller. We wrap it however | ||
64 | * as we need to spot hardware with incorrect or missing master/slave | ||
65 | * decode, which alas is embarrassingly common in the PC world | ||
66 | */ | ||
67 | |||
68 | static int pcmcia_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) | ||
69 | { | ||
70 | struct ata_device *master = &ap->device[0]; | ||
71 | struct ata_device *slave = &ap->device[1]; | ||
72 | |||
73 | if (!ata_dev_enabled(master) || !ata_dev_enabled(slave)) | ||
74 | return ata_do_set_mode(ap, r_failed_dev); | ||
75 | |||
76 | if (memcmp(master->id + ATA_ID_FW_REV, slave->id + ATA_ID_FW_REV, | ||
77 | ATA_ID_FW_REV_LEN + ATA_ID_PROD_LEN) == 0) | ||
78 | { | ||
79 | /* Suspicious match, but could be two cards from | ||
80 | the same vendor - check serial */ | ||
81 | if (memcmp(master->id + ATA_ID_SERNO, slave->id + ATA_ID_SERNO, | ||
82 | ATA_ID_SERNO_LEN) == 0 && master->id[ATA_ID_SERNO] >> 8) { | ||
83 | ata_dev_printk(slave, KERN_WARNING, "is a ghost device, ignoring.\n"); | ||
84 | ata_dev_disable(slave); | ||
85 | } | ||
86 | } | ||
87 | return ata_do_set_mode(ap, r_failed_dev); | ||
88 | } | ||
89 | |||
57 | static struct scsi_host_template pcmcia_sht = { | 90 | static struct scsi_host_template pcmcia_sht = { |
58 | .module = THIS_MODULE, | 91 | .module = THIS_MODULE, |
59 | .name = DRV_NAME, | 92 | .name = DRV_NAME, |
@@ -73,6 +106,7 @@ static struct scsi_host_template pcmcia_sht = { | |||
73 | }; | 106 | }; |
74 | 107 | ||
75 | static struct ata_port_operations pcmcia_port_ops = { | 108 | static struct ata_port_operations pcmcia_port_ops = { |
109 | .set_mode = pcmcia_set_mode, | ||
76 | .port_disable = ata_port_disable, | 110 | .port_disable = ata_port_disable, |
77 | .tf_load = ata_tf_load, | 111 | .tf_load = ata_tf_load, |
78 | .tf_read = ata_tf_read, | 112 | .tf_read = ata_tf_read, |
@@ -84,13 +118,13 @@ static struct ata_port_operations pcmcia_port_ops = { | |||
84 | .thaw = ata_bmdma_thaw, | 118 | .thaw = ata_bmdma_thaw, |
85 | .error_handler = ata_bmdma_error_handler, | 119 | .error_handler = ata_bmdma_error_handler, |
86 | .post_internal_cmd = ata_bmdma_post_internal_cmd, | 120 | .post_internal_cmd = ata_bmdma_post_internal_cmd, |
121 | .cable_detect = ata_cable_40wire, | ||
87 | 122 | ||
88 | .qc_prep = ata_qc_prep, | 123 | .qc_prep = ata_qc_prep, |
89 | .qc_issue = ata_qc_issue_prot, | 124 | .qc_issue = ata_qc_issue_prot, |
90 | 125 | ||
91 | .data_xfer = ata_data_xfer_noirq, | 126 | .data_xfer = ata_data_xfer_noirq, |
92 | 127 | ||
93 | .irq_handler = ata_interrupt, | ||
94 | .irq_clear = ata_bmdma_irq_clear, | 128 | .irq_clear = ata_bmdma_irq_clear, |
95 | .irq_on = ata_irq_on, | 129 | .irq_on = ata_irq_on, |
96 | .irq_ack = ata_irq_ack, | 130 | .irq_ack = ata_irq_ack, |
@@ -111,7 +145,8 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
111 | 145 | ||
112 | static int pcmcia_init_one(struct pcmcia_device *pdev) | 146 | static int pcmcia_init_one(struct pcmcia_device *pdev) |
113 | { | 147 | { |
114 | struct ata_probe_ent ae; | 148 | struct ata_host *host; |
149 | struct ata_port *ap; | ||
115 | struct ata_pcmcia_info *info; | 150 | struct ata_pcmcia_info *info; |
116 | tuple_t tuple; | 151 | tuple_t tuple; |
117 | struct { | 152 | struct { |
@@ -255,24 +290,24 @@ next_entry: | |||
255 | * Having done the PCMCIA plumbing the ATA side is relatively | 290 | * Having done the PCMCIA plumbing the ATA side is relatively |
256 | * sane. | 291 | * sane. |
257 | */ | 292 | */ |
258 | 293 | ret = -ENOMEM; | |
259 | memset(&ae, 0, sizeof(struct ata_probe_ent)); | 294 | host = ata_host_alloc(&pdev->dev, 1); |
260 | INIT_LIST_HEAD(&ae.node); | 295 | if (!host) |
261 | ae.dev = &pdev->dev; | 296 | goto failed; |
262 | ae.port_ops = &pcmcia_port_ops; | 297 | ap = host->ports[0]; |
263 | ae.sht = &pcmcia_sht; | 298 | |
264 | ae.n_ports = 1; | 299 | ap->ops = &pcmcia_port_ops; |
265 | ae.pio_mask = 1; /* ISA so PIO 0 cycles */ | 300 | ap->pio_mask = 1; /* ISA so PIO 0 cycles */ |
266 | ae.irq = pdev->irq.AssignedIRQ; | 301 | ap->flags |= ATA_FLAG_SLAVE_POSS; |
267 | ae.irq_flags = IRQF_SHARED; | 302 | ap->ioaddr.cmd_addr = io_addr; |
268 | ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; | 303 | ap->ioaddr.altstatus_addr = ctl_addr; |
269 | ae.port[0].cmd_addr = io_addr; | 304 | ap->ioaddr.ctl_addr = ctl_addr; |
270 | ae.port[0].altstatus_addr = ctl_addr; | 305 | ata_std_ports(&ap->ioaddr); |
271 | ae.port[0].ctl_addr = ctl_addr; | 306 | |
272 | ata_std_ports(&ae.port[0]); | 307 | /* activate */ |
273 | 308 | ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt, | |
274 | ret = -ENODEV; | 309 | IRQF_SHARED, &pcmcia_sht); |
275 | if (ata_device_add(&ae) == 0) | 310 | if (ret) |
276 | goto failed; | 311 | goto failed; |
277 | 312 | ||
278 | info->ndev = 1; | 313 | info->ndev = 1; |