Blame view
drivers/ata/pata_acpi.c
6.81 KB
025621f9a pata_acpi: ACPI d... |
1 2 3 |
/* * ACPI PATA driver * |
ab7716300 ata: Switch all m... |
4 |
* (c) 2007 Red Hat |
025621f9a pata_acpi: ACPI d... |
5 6 7 8 9 10 11 12 13 |
*/ #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/init.h> #include <linux/blkdev.h> #include <linux/delay.h> #include <linux/device.h> |
5a0e3ad6a include cleanup: ... |
14 |
#include <linux/gfp.h> |
025621f9a pata_acpi: ACPI d... |
15 16 |
#include <scsi/scsi_host.h> #include <acpi/acpi_bus.h> |
025621f9a pata_acpi: ACPI d... |
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <linux/libata.h> #include <linux/ata.h> #define DRV_NAME "pata_acpi" #define DRV_VERSION "0.2.3" struct pata_acpi { struct ata_acpi_gtm gtm; void *last; unsigned long mask[2]; }; /** * pacpi_pre_reset - check for 40/80 pin * @ap: Port * @deadline: deadline jiffies for the operation * * Perform the PATA port setup we need. */ static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline) { struct ata_port *ap = link->ap; struct pata_acpi *acpi = ap->private_data; if (ap->acpi_handle == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0) return -ENODEV; |
9363c3825 libata: rename SF... |
44 |
return ata_sff_prereset(link, deadline); |
025621f9a pata_acpi: ACPI d... |
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
} /** * pacpi_cable_detect - cable type detection * @ap: port to detect * * Perform device specific cable detection */ static int pacpi_cable_detect(struct ata_port *ap) { struct pata_acpi *acpi = ap->private_data; if ((acpi->mask[0] | acpi->mask[1]) & (0xF8 << ATA_SHIFT_UDMA)) return ATA_CBL_PATA80; else return ATA_CBL_PATA40; } /** |
025621f9a pata_acpi: ACPI d... |
65 66 67 68 69 70 71 72 73 74 |
* pacpi_discover_modes - filter non ACPI modes * @adev: ATA device * @mask: proposed modes * * Try the modes available and see which ones the ACPI method will * set up sensibly. From this we get a mask of ACPI modes we can use */ static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev) { |
025621f9a pata_acpi: ACPI d... |
75 |
struct pata_acpi *acpi = ap->private_data; |
025621f9a pata_acpi: ACPI d... |
76 |
struct ata_acpi_gtm probe; |
7c77fa4d5 libata: separate ... |
77 |
unsigned int xfer_mask; |
025621f9a pata_acpi: ACPI d... |
78 79 |
probe = acpi->gtm; |
025621f9a pata_acpi: ACPI d... |
80 |
ata_acpi_gtm(ap, &probe); |
7c77fa4d5 libata: separate ... |
81 |
xfer_mask = ata_acpi_gtm_xfermask(adev, &probe); |
025621f9a pata_acpi: ACPI d... |
82 |
|
7c77fa4d5 libata: separate ... |
83 |
if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA)) |
025621f9a pata_acpi: ACPI d... |
84 |
ap->cbl = ATA_CBL_PATA80; |
7c77fa4d5 libata: separate ... |
85 86 |
return xfer_mask; |
025621f9a pata_acpi: ACPI d... |
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
} /** * pacpi_mode_filter - mode filter for ACPI * @adev: device * @mask: mask of valid modes * * Filter the valid mode list according to our own specific rules, in * this case the list of discovered valid modes obtained by ACPI probing */ static unsigned long pacpi_mode_filter(struct ata_device *adev, unsigned long mask) { struct pata_acpi *acpi = adev->link->ap->private_data; |
c7087652e libata-sff: clean... |
101 |
return mask & acpi->mask[adev->devno]; |
025621f9a pata_acpi: ACPI d... |
102 103 104 105 106 107 108 109 110 111 112 113 |
} /** * pacpi_set_piomode - set initial PIO mode data * @ap: ATA interface * @adev: ATA device */ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev) { int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; |
a0f79b929 libata: implement... |
114 |
const struct ata_timing *t; |
025621f9a pata_acpi: ACPI d... |
115 |
|
b447916e2 [libata] fix 'if(... |
116 |
if (!(acpi->gtm.flags & 0x10)) |
025621f9a pata_acpi: ACPI d... |
117 118 119 |
unit = 0; /* Now stuff the nS values into the structure */ |
a0f79b929 libata: implement... |
120 121 |
t = ata_timing_find_mode(adev->pio_mode); acpi->gtm.drive[unit].pio = t->cycle; |
025621f9a pata_acpi: ACPI d... |
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
ata_acpi_stm(ap, &acpi->gtm); /* See what mode we actually got */ ata_acpi_gtm(ap, &acpi->gtm); } /** * pacpi_set_dmamode - set initial DMA mode data * @ap: ATA interface * @adev: ATA device */ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev) { int unit = adev->devno; struct pata_acpi *acpi = ap->private_data; |
a0f79b929 libata: implement... |
137 |
const struct ata_timing *t; |
025621f9a pata_acpi: ACPI d... |
138 |
|
b447916e2 [libata] fix 'if(... |
139 |
if (!(acpi->gtm.flags & 0x10)) |
025621f9a pata_acpi: ACPI d... |
140 141 142 |
unit = 0; /* Now stuff the nS values into the structure */ |
a0f79b929 libata: implement... |
143 |
t = ata_timing_find_mode(adev->dma_mode); |
025621f9a pata_acpi: ACPI d... |
144 |
if (adev->dma_mode >= XFER_UDMA_0) { |
a0f79b929 libata: implement... |
145 |
acpi->gtm.drive[unit].dma = t->udma; |
025621f9a pata_acpi: ACPI d... |
146 147 |
acpi->gtm.flags |= (1 << (2 * unit)); } else { |
a0f79b929 libata: implement... |
148 |
acpi->gtm.drive[unit].dma = t->cycle; |
025621f9a pata_acpi: ACPI d... |
149 150 151 152 153 154 155 156 |
acpi->gtm.flags &= ~(1 << (2 * unit)); } ata_acpi_stm(ap, &acpi->gtm); /* See what mode we actually got */ ata_acpi_gtm(ap, &acpi->gtm); } /** |
9363c3825 libata: rename SF... |
157 |
* pacpi_qc_issue - command issue |
025621f9a pata_acpi: ACPI d... |
158 159 160 161 |
* @qc: command pending * * Called when the libata layer is about to issue a command. We wrap * this interface so that we can load the correct ATA timings if |
3ad2f3fbb tree-wide: Assort... |
162 |
* necessary. |
025621f9a pata_acpi: ACPI d... |
163 |
*/ |
9363c3825 libata: rename SF... |
164 |
static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc) |
025621f9a pata_acpi: ACPI d... |
165 166 167 168 169 170 |
{ struct ata_port *ap = qc->ap; struct ata_device *adev = qc->dev; struct pata_acpi *acpi = ap->private_data; if (acpi->gtm.flags & 0x10) |
360ff7833 libata-sff: separ... |
171 |
return ata_bmdma_qc_issue(qc); |
025621f9a pata_acpi: ACPI d... |
172 173 174 |
if (adev != acpi->last) { pacpi_set_piomode(ap, adev); |
b15b3ebae libata: Fix a lar... |
175 |
if (ata_dma_enabled(adev)) |
025621f9a pata_acpi: ACPI d... |
176 177 178 |
pacpi_set_dmamode(ap, adev); acpi->last = adev; } |
360ff7833 libata-sff: separ... |
179 |
return ata_bmdma_qc_issue(qc); |
025621f9a pata_acpi: ACPI d... |
180 181 182 183 184 185 186 187 188 189 190 191 192 |
} /** * pacpi_port_start - port setup * @ap: ATA port being set up * * Use the port_start hook to maintain private control structures */ static int pacpi_port_start(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host->dev); struct pata_acpi *acpi; |
025621f9a pata_acpi: ACPI d... |
193 194 195 196 197 198 199 200 |
if (ap->acpi_handle == NULL) return -ENODEV; acpi = ap->private_data = devm_kzalloc(&pdev->dev, sizeof(struct pata_acpi), GFP_KERNEL); if (ap->private_data == NULL) return -ENOMEM; acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]); acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]); |
47db477e4 ata: remove unnec... |
201 |
return ata_bmdma_port_start(ap); |
025621f9a pata_acpi: ACPI d... |
202 203 204 |
} static struct scsi_host_template pacpi_sht = { |
68d1d07b5 libata: implement... |
205 |
ATA_BMDMA_SHT(DRV_NAME), |
025621f9a pata_acpi: ACPI d... |
206 |
}; |
029cfd6b7 libata: implement... |
207 208 |
static struct ata_port_operations pacpi_ops = { .inherits = &ata_bmdma_port_ops, |
9363c3825 libata: rename SF... |
209 |
.qc_issue = pacpi_qc_issue, |
029cfd6b7 libata: implement... |
210 211 |
.cable_detect = pacpi_cable_detect, .mode_filter = pacpi_mode_filter, |
025621f9a pata_acpi: ACPI d... |
212 213 |
.set_piomode = pacpi_set_piomode, .set_dmamode = pacpi_set_dmamode, |
887125e37 libata: stop over... |
214 |
.prereset = pacpi_pre_reset, |
025621f9a pata_acpi: ACPI d... |
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
.port_start = pacpi_port_start, }; /** * pacpi_init_one - Register ACPI ATA PCI device with kernel services * @pdev: PCI device to register * @ent: Entry in pacpi_pci_tbl matching with @pdev * * Called from kernel PCI layer. * * LOCKING: * Inherited from PCI layer (may sleep). * * RETURNS: * Zero on success, or -ERRNO value. */ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { |
c10f97b9d libata: remove AT... |
236 |
.flags = ATA_FLAG_SLAVE_POSS, |
025621f9a pata_acpi: ACPI d... |
237 |
|
14bdef982 [libata] convert ... |
238 239 240 |
.pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, |
025621f9a pata_acpi: ACPI d... |
241 242 243 244 |
.port_ops = &pacpi_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; |
05177f178 pata_atiixp: Don'... |
245 246 247 248 249 250 |
if (pdev->vendor == PCI_VENDOR_ID_ATI) { int rc = pcim_enable_device(pdev); if (rc < 0) return rc; pcim_pin_device(pdev); } |
1c5afdf7a libata-sff: separ... |
251 |
return ata_pci_bmdma_init_one(pdev, ppi, &pacpi_sht, NULL, 0); |
025621f9a pata_acpi: ACPI d... |
252 253 254 255 256 257 258 259 260 261 262 263 |
} static const struct pci_device_id pacpi_pci_tbl[] = { { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1}, { } /* terminate list */ }; static struct pci_driver pacpi_pci_driver = { .name = DRV_NAME, .id_table = pacpi_pci_tbl, .probe = pacpi_init_one, .remove = ata_pci_remove_one, |
8e2840e06 pata_acpi: fix bu... |
264 |
#ifdef CONFIG_PM |
025621f9a pata_acpi: ACPI d... |
265 266 |
.suspend = ata_pci_device_suspend, .resume = ata_pci_device_resume, |
8e2840e06 pata_acpi: fix bu... |
267 |
#endif |
025621f9a pata_acpi: ACPI d... |
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
}; static int __init pacpi_init(void) { return pci_register_driver(&pacpi_pci_driver); } static void __exit pacpi_exit(void) { pci_unregister_driver(&pacpi_pci_driver); } module_init(pacpi_init); module_exit(pacpi_exit); MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("SCSI low-level driver for ATA in ACPI mode"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, pacpi_pci_tbl); MODULE_VERSION(DRV_VERSION); |