Deleted Added
full compact
ata-pci.c (123361) ata-pci.c (124403)
1/*-
1/*-
2 * Copyright (c) 1998 - 2003 S�ren Schmidt <sos@FreeBSD.org>
2 * Copyright (c) 1998 - 2004 S�ren Schmidt <sos@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/dev/ata/ata-pci.c 123361 2003-12-09 19:13:50Z sos $");
30__FBSDID("$FreeBSD: head/sys/dev/ata/ata-pci.c 124403 2004-01-11 22:08:34Z sos $");
31
32#include "opt_ata.h"
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/module.h>
37#include <sys/bus.h>
38#include <sys/malloc.h>
31
32#include "opt_ata.h"
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/module.h>
37#include <sys/bus.h>
38#include <sys/malloc.h>
39#include <sys/sema.h>
39#include <sys/taskqueue.h>
40#include <machine/stdarg.h>
41#include <machine/resource.h>
42#include <machine/bus.h>
43#ifdef __alpha__
44#include <machine/md_var.h>
45#endif
46#include <sys/rman.h>
47#include <dev/pci/pcivar.h>
48#include <dev/pci/pcireg.h>
49#include <dev/ata/ata-all.h>
50#include <dev/ata/ata-pci.h>
51
52/* local vars */
53static MALLOC_DEFINE(M_ATAPCI, "ATA PCI", "ATA driver PCI");
54
55/* misc defines */
56#define IOMASK 0xfffffffc
57
58/* prototypes */
59static int ata_pci_allocate(device_t, struct ata_channel *);
60static void ata_pci_dmainit(struct ata_channel *);
61static void ata_pci_locknoop(struct ata_channel *, int);
62
63static int
64ata_pci_probe(device_t dev)
65{
66 if (pci_get_class(dev) != PCIC_STORAGE)
67 return ENXIO;
68
69 switch (pci_get_vendor(dev)) {
70 case ATA_ACARD_ID:
71 if (!ata_acard_ident(dev))
72 return 0;
73 break;
74 case ATA_ACER_LABS_ID:
75 if (!ata_ali_ident(dev))
76 return 0;
77 break;
78 case ATA_AMD_ID:
79 if (!ata_amd_ident(dev))
80 return 0;
81 break;
82 case ATA_CYRIX_ID:
83 if (!ata_cyrix_ident(dev))
84 return 0;
85 break;
86 case ATA_CYPRESS_ID:
87 if (!ata_cypress_ident(dev))
88 return 0;
89 break;
90 case ATA_HIGHPOINT_ID:
91 if (!ata_highpoint_ident(dev))
92 return 0;
93 break;
94 case ATA_INTEL_ID:
95 if (!ata_intel_ident(dev))
96 return 0;
97 break;
98 case ATA_NATIONAL_ID:
99 if (!ata_national_ident(dev))
100 return 0;
101 break;
102 case ATA_NVIDIA_ID:
103 if (!ata_nvidia_ident(dev))
104 return 0;
105 break;
106 case ATA_PROMISE_ID:
107 if (!ata_promise_ident(dev))
108 return 0;
109 break;
110 case ATA_SERVERWORKS_ID:
111 if (!ata_serverworks_ident(dev))
112 return 0;
113 break;
114 case ATA_SILICON_IMAGE_ID:
115 if (!ata_sii_ident(dev))
116 return 0;
117 break;
118 case ATA_SIS_ID:
119 if (!ata_sis_ident(dev))
120 return 0;
121 break;
122 case ATA_VIA_ID:
123 if (!ata_via_ident(dev))
124 return 0;
125 break;
126 case 0x16ca:
127 if (pci_get_devid(dev) == 0x000116ca) {
128 ata_generic_ident(dev);
129 device_set_desc(dev, "Cenatek Rocket Drive controller");
130 return 0;
131 }
132 break;
133 case 0x1042:
134 if (pci_get_devid(dev)==0x10001042 || pci_get_devid(dev)==0x10011042) {
135 ata_generic_ident(dev);
136 device_set_desc(dev,
137 "RZ 100? ATA controller !WARNING! buggy HW data loss possible");
138 return 0;
139 }
140 break;
141 }
142
143 /* unknown chipset, try generic DMA if it seems possible */
144 if ((pci_get_class(dev) == PCIC_STORAGE) &&
145 (pci_get_subclass(dev) == PCIS_STORAGE_IDE))
146 return ata_generic_ident(dev);
147
148 return ENXIO;
149}
150
151static int
152ata_pci_attach(device_t dev)
153{
154 struct ata_pci_controller *ctlr = device_get_softc(dev);
155 u_int8_t class, subclass;
156 u_int32_t type, cmd;
157 int unit;
158
159 /* set up vendor-specific stuff */
160 type = pci_get_devid(dev);
161 class = pci_get_class(dev);
162 subclass = pci_get_subclass(dev);
163 cmd = pci_read_config(dev, PCIR_COMMAND, 2);
164
165 if (!(cmd & PCIM_CMD_PORTEN)) {
166 device_printf(dev, "ATA channel disabled by BIOS\n");
167 return 0;
168 }
169
170 /* do chipset specific setups only needed once */
171 if (ATA_MASTERDEV(dev) || pci_read_config(dev, 0x18, 4) & IOMASK)
172 ctlr->channels = 2;
173 else
174 ctlr->channels = 1;
175 ctlr->allocate = ata_pci_allocate;
176 ctlr->dmainit = ata_pci_dmainit;
177 ctlr->locking = ata_pci_locknoop;
178
179#ifdef __sparc64__
180 if (!(cmd & PCIM_CMD_BUSMASTEREN)) {
181 pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2);
182 cmd = pci_read_config(dev, PCIR_COMMAND, 2);
183 }
184#endif
185 /* if busmastering configured get the I/O resource */
186 if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
187 int rid = ATA_BMADDR_RID;
188
189 ctlr->r_io1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
190 0, ~0, 1, RF_ACTIVE);
191 }
192
193 ctlr->chipinit(dev);
194
195 /* attach all channels on this controller */
196 for (unit = 0; unit < ctlr->channels; unit++)
197 device_add_child(dev, "ata", ATA_MASTERDEV(dev) ?
198 unit : devclass_find_free_unit(ata_devclass, 2));
199
200 return bus_generic_attach(dev);
201}
202
203
204static int
205ata_pci_print_child(device_t dev, device_t child)
206{
207 struct ata_channel *ch = device_get_softc(child);
208 int retval = 0;
209
210 retval += bus_print_child_header(dev, child);
211 retval += printf(": at 0x%lx", rman_get_start(ch->r_io[ATA_IDX_ADDR].res));
212
213 if (ATA_MASTERDEV(dev))
214 retval += printf(" irq %d", 14 + ch->unit);
215
216 retval += bus_print_child_footer(dev, child);
217
218 return retval;
219}
220
221static struct resource *
222ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
223 u_long start, u_long end, u_long count, u_int flags)
224{
225 struct ata_pci_controller *controller = device_get_softc(dev);
226 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
227 struct resource *res = NULL;
228 int myrid;
229
230 if (type == SYS_RES_IOPORT) {
231 switch (*rid) {
232 case ATA_IOADDR_RID:
233 if (ATA_MASTERDEV(dev)) {
234 myrid = 0;
235 start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
236 end = start + ATA_IOSIZE - 1;
237 count = ATA_IOSIZE;
238 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
239 SYS_RES_IOPORT, &myrid,
240 start, end, count, flags);
241 }
242 else {
243 myrid = 0x10 + 8 * unit;
244 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
245 SYS_RES_IOPORT, &myrid,
246 start, end, count, flags);
247 }
248 break;
249
250 case ATA_ALTADDR_RID:
251 if (ATA_MASTERDEV(dev)) {
252 myrid = 0;
253 start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET;
254 end = start + ATA_ALTIOSIZE - 1;
255 count = ATA_ALTIOSIZE;
256 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
257 SYS_RES_IOPORT, &myrid,
258 start, end, count, flags);
259 }
260 else {
261 myrid = 0x14 + 8 * unit;
262 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
263 SYS_RES_IOPORT, &myrid,
264 start, end, count, flags);
265 if (res) {
266 start = rman_get_start(res) + 2;
267 end = start + ATA_ALTIOSIZE - 1;
268 count = ATA_ALTIOSIZE;
269 BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
270 SYS_RES_IOPORT, myrid, res);
271 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
272 SYS_RES_IOPORT, &myrid,
273 start, end, count, flags);
274 }
275 }
276 break;
277 }
278 return res;
279 }
280
281 if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
282 if (ATA_MASTERDEV(dev)) {
283#ifdef __alpha__
284 return alpha_platform_alloc_ide_intr(unit);
285#else
286 int irq = (unit == 0 ? 14 : 15);
287
288 return BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
289 SYS_RES_IRQ, rid, irq, irq, 1, flags);
290#endif
291 }
292 else {
293 return controller->r_irq;
294 }
295 }
296 return 0;
297}
298
299static int
300ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
301 struct resource *r)
302{
303 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
304
305 if (type == SYS_RES_IOPORT) {
306 switch (rid) {
307 case ATA_IOADDR_RID:
308 if (ATA_MASTERDEV(dev))
309 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
310 SYS_RES_IOPORT, 0x0, r);
311 else
312 return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
313 SYS_RES_IOPORT, 0x10 + 8 * unit, r);
314 break;
315
316 case ATA_ALTADDR_RID:
317 if (ATA_MASTERDEV(dev))
318 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
319 SYS_RES_IOPORT, 0x0, r);
320 else
321 return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
322 SYS_RES_IOPORT, 0x14 + 8 * unit, r);
323 break;
324 default:
325 return ENOENT;
326 }
327 }
328 if (type == SYS_RES_IRQ) {
329 if (rid != ATA_IRQ_RID)
330 return ENOENT;
331
332 if (ATA_MASTERDEV(dev)) {
333#ifdef __alpha__
334 return alpha_platform_release_ide_intr(unit, r);
335#else
336 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
337 SYS_RES_IRQ, rid, r);
338#endif
339 }
340 else
341 return 0;
342 }
343 return EINVAL;
344}
345
346static int
347ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
348 int flags, driver_intr_t *function, void *argument,
349 void **cookiep)
350{
351 if (ATA_MASTERDEV(dev)) {
352#ifdef __alpha__
353 return alpha_platform_setup_ide_intr(child, irq, function, argument,
354 cookiep);
355#else
356 return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
357 flags, function, argument, cookiep);
358#endif
359 }
360 else {
361 struct ata_pci_controller *controller = device_get_softc(dev);
362 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
363
364 controller->interrupt[unit].function = function;
365 controller->interrupt[unit].argument = argument;
366 *cookiep = controller;
367 return 0;
368 }
369}
370
371static int
372ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
373 void *cookie)
374{
375 if (ATA_MASTERDEV(dev)) {
376#ifdef __alpha__
377 return alpha_platform_teardown_ide_intr(child, irq, cookie);
378#else
379 return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
380#endif
381 }
382 else {
383 struct ata_pci_controller *controller = device_get_softc(dev);
384 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
385
386 controller->interrupt[unit].function = NULL;
387 controller->interrupt[unit].argument = NULL;
388 return 0;
389 }
390}
391
392static int
393ata_pci_allocate(device_t dev, struct ata_channel *ch)
394{
395 struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
396 struct resource *io = NULL, *altio = NULL;
397 int i, rid;
398
399 rid = ATA_IOADDR_RID;
400 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
401 0, ~0, ATA_IOSIZE, RF_ACTIVE);
402 if (!io)
403 return ENXIO;
404
405 rid = ATA_ALTADDR_RID;
406 altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
407 0, ~0, ATA_ALTIOSIZE, RF_ACTIVE);
408 if (!altio) {
409 bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
410 return ENXIO;
411 }
412
413 for (i = ATA_DATA; i <= ATA_STATUS; i ++) {
414 ch->r_io[i].res = io;
415 ch->r_io[i].offset = i;
416 }
417 ch->r_io[ATA_ALTSTAT].res = altio;
418 ch->r_io[ATA_ALTSTAT].offset = 0;
419 ch->r_io[ATA_IDX_ADDR].res = io;
420
421 if (ctlr->r_io1) {
422 for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) {
423 ch->r_io[i].res = ctlr->r_io1;
424 ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE);
425 }
426
427 /* if simplex controller, only allow DMA on primary channel */
428 ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_IDX_INB(ch, ATA_BMSTAT_PORT) &
429 (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE));
430 if (ch->unit > 0 &&
431 (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_DMA_SIMPLEX))
432 device_printf(dev, "simplex device, DMA on primary only\n");
433 else
434 ctlr->dmainit(ch);
435 }
436 return 0;
437}
438
439static int
440ata_pci_dmastart(struct ata_channel *ch)
441{
442 ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) |
443 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
444 ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab);
445 ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
446 ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
447 ATA_BMCMD_START_STOP);
448 return 0;
449}
450
451static int
452ata_pci_dmastop(struct ata_channel *ch)
453{
454 int error;
455
456 error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
457 ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
458 ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
459 ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
460 return error;
461}
462
463static void
464ata_pci_dmainit(struct ata_channel *ch)
465{
466 ata_dmainit(ch);
467 if (ch->dma) {
468 ch->dma->start = ata_pci_dmastart;
469 ch->dma->stop = ata_pci_dmastop;
470 }
471}
472
473static void
474ata_pci_locknoop(struct ata_channel *ch, int flags)
475{
476}
477
478static device_method_t ata_pci_methods[] = {
479 /* device interface */
480 DEVMETHOD(device_probe, ata_pci_probe),
481 DEVMETHOD(device_attach, ata_pci_attach),
482 DEVMETHOD(device_shutdown, bus_generic_shutdown),
483 DEVMETHOD(device_suspend, bus_generic_suspend),
484 DEVMETHOD(device_resume, bus_generic_resume),
485
486 /* bus methods */
487 DEVMETHOD(bus_print_child, ata_pci_print_child),
488 DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource),
489 DEVMETHOD(bus_release_resource, ata_pci_release_resource),
490 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
491 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
492 DEVMETHOD(bus_setup_intr, ata_pci_setup_intr),
493 DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr),
494 { 0, 0 }
495};
496
497static driver_t ata_pci_driver = {
498 "atapci",
499 ata_pci_methods,
500 sizeof(struct ata_pci_controller),
501};
502
503static devclass_t ata_pci_devclass;
504
505DRIVER_MODULE(atapci, pci, ata_pci_driver, ata_pci_devclass, 0, 0);
506
507static int
508ata_pcisub_probe(device_t dev)
509{
510 struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
511 struct ata_channel *ch = device_get_softc(dev);
512 device_t *children;
513 int count, error, i;
514
515 /* find channel number on this controller */
516 device_get_children(device_get_parent(dev), &children, &count);
517 for (i = 0; i < count; i++) {
518 if (children[i] == dev)
519 ch->unit = i;
520 }
521 free(children, M_TEMP);
522
523 if ((error = ctlr->allocate(dev, ch)))
524 return error;
525
526 ch->device[MASTER].setmode = ctlr->setmode;
527 ch->device[SLAVE].setmode = ctlr->setmode;
528 ch->locking = ctlr->locking;
529 return ata_probe(dev);
530}
531
532static device_method_t ata_pcisub_methods[] = {
533 /* device interface */
534 DEVMETHOD(device_probe, ata_pcisub_probe),
535 DEVMETHOD(device_attach, ata_attach),
536 DEVMETHOD(device_detach, ata_detach),
537 DEVMETHOD(device_suspend, ata_suspend),
538 DEVMETHOD(device_resume, ata_resume),
539 { 0, 0 }
540};
541
542static driver_t ata_pcisub_driver = {
543 "ata",
544 ata_pcisub_methods,
545 sizeof(struct ata_channel),
546};
547
548DRIVER_MODULE(ata, atapci, ata_pcisub_driver, ata_devclass, 0, 0);
40#include <sys/taskqueue.h>
41#include <machine/stdarg.h>
42#include <machine/resource.h>
43#include <machine/bus.h>
44#ifdef __alpha__
45#include <machine/md_var.h>
46#endif
47#include <sys/rman.h>
48#include <dev/pci/pcivar.h>
49#include <dev/pci/pcireg.h>
50#include <dev/ata/ata-all.h>
51#include <dev/ata/ata-pci.h>
52
53/* local vars */
54static MALLOC_DEFINE(M_ATAPCI, "ATA PCI", "ATA driver PCI");
55
56/* misc defines */
57#define IOMASK 0xfffffffc
58
59/* prototypes */
60static int ata_pci_allocate(device_t, struct ata_channel *);
61static void ata_pci_dmainit(struct ata_channel *);
62static void ata_pci_locknoop(struct ata_channel *, int);
63
64static int
65ata_pci_probe(device_t dev)
66{
67 if (pci_get_class(dev) != PCIC_STORAGE)
68 return ENXIO;
69
70 switch (pci_get_vendor(dev)) {
71 case ATA_ACARD_ID:
72 if (!ata_acard_ident(dev))
73 return 0;
74 break;
75 case ATA_ACER_LABS_ID:
76 if (!ata_ali_ident(dev))
77 return 0;
78 break;
79 case ATA_AMD_ID:
80 if (!ata_amd_ident(dev))
81 return 0;
82 break;
83 case ATA_CYRIX_ID:
84 if (!ata_cyrix_ident(dev))
85 return 0;
86 break;
87 case ATA_CYPRESS_ID:
88 if (!ata_cypress_ident(dev))
89 return 0;
90 break;
91 case ATA_HIGHPOINT_ID:
92 if (!ata_highpoint_ident(dev))
93 return 0;
94 break;
95 case ATA_INTEL_ID:
96 if (!ata_intel_ident(dev))
97 return 0;
98 break;
99 case ATA_NATIONAL_ID:
100 if (!ata_national_ident(dev))
101 return 0;
102 break;
103 case ATA_NVIDIA_ID:
104 if (!ata_nvidia_ident(dev))
105 return 0;
106 break;
107 case ATA_PROMISE_ID:
108 if (!ata_promise_ident(dev))
109 return 0;
110 break;
111 case ATA_SERVERWORKS_ID:
112 if (!ata_serverworks_ident(dev))
113 return 0;
114 break;
115 case ATA_SILICON_IMAGE_ID:
116 if (!ata_sii_ident(dev))
117 return 0;
118 break;
119 case ATA_SIS_ID:
120 if (!ata_sis_ident(dev))
121 return 0;
122 break;
123 case ATA_VIA_ID:
124 if (!ata_via_ident(dev))
125 return 0;
126 break;
127 case 0x16ca:
128 if (pci_get_devid(dev) == 0x000116ca) {
129 ata_generic_ident(dev);
130 device_set_desc(dev, "Cenatek Rocket Drive controller");
131 return 0;
132 }
133 break;
134 case 0x1042:
135 if (pci_get_devid(dev)==0x10001042 || pci_get_devid(dev)==0x10011042) {
136 ata_generic_ident(dev);
137 device_set_desc(dev,
138 "RZ 100? ATA controller !WARNING! buggy HW data loss possible");
139 return 0;
140 }
141 break;
142 }
143
144 /* unknown chipset, try generic DMA if it seems possible */
145 if ((pci_get_class(dev) == PCIC_STORAGE) &&
146 (pci_get_subclass(dev) == PCIS_STORAGE_IDE))
147 return ata_generic_ident(dev);
148
149 return ENXIO;
150}
151
152static int
153ata_pci_attach(device_t dev)
154{
155 struct ata_pci_controller *ctlr = device_get_softc(dev);
156 u_int8_t class, subclass;
157 u_int32_t type, cmd;
158 int unit;
159
160 /* set up vendor-specific stuff */
161 type = pci_get_devid(dev);
162 class = pci_get_class(dev);
163 subclass = pci_get_subclass(dev);
164 cmd = pci_read_config(dev, PCIR_COMMAND, 2);
165
166 if (!(cmd & PCIM_CMD_PORTEN)) {
167 device_printf(dev, "ATA channel disabled by BIOS\n");
168 return 0;
169 }
170
171 /* do chipset specific setups only needed once */
172 if (ATA_MASTERDEV(dev) || pci_read_config(dev, 0x18, 4) & IOMASK)
173 ctlr->channels = 2;
174 else
175 ctlr->channels = 1;
176 ctlr->allocate = ata_pci_allocate;
177 ctlr->dmainit = ata_pci_dmainit;
178 ctlr->locking = ata_pci_locknoop;
179
180#ifdef __sparc64__
181 if (!(cmd & PCIM_CMD_BUSMASTEREN)) {
182 pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2);
183 cmd = pci_read_config(dev, PCIR_COMMAND, 2);
184 }
185#endif
186 /* if busmastering configured get the I/O resource */
187 if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
188 int rid = ATA_BMADDR_RID;
189
190 ctlr->r_io1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
191 0, ~0, 1, RF_ACTIVE);
192 }
193
194 ctlr->chipinit(dev);
195
196 /* attach all channels on this controller */
197 for (unit = 0; unit < ctlr->channels; unit++)
198 device_add_child(dev, "ata", ATA_MASTERDEV(dev) ?
199 unit : devclass_find_free_unit(ata_devclass, 2));
200
201 return bus_generic_attach(dev);
202}
203
204
205static int
206ata_pci_print_child(device_t dev, device_t child)
207{
208 struct ata_channel *ch = device_get_softc(child);
209 int retval = 0;
210
211 retval += bus_print_child_header(dev, child);
212 retval += printf(": at 0x%lx", rman_get_start(ch->r_io[ATA_IDX_ADDR].res));
213
214 if (ATA_MASTERDEV(dev))
215 retval += printf(" irq %d", 14 + ch->unit);
216
217 retval += bus_print_child_footer(dev, child);
218
219 return retval;
220}
221
222static struct resource *
223ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
224 u_long start, u_long end, u_long count, u_int flags)
225{
226 struct ata_pci_controller *controller = device_get_softc(dev);
227 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
228 struct resource *res = NULL;
229 int myrid;
230
231 if (type == SYS_RES_IOPORT) {
232 switch (*rid) {
233 case ATA_IOADDR_RID:
234 if (ATA_MASTERDEV(dev)) {
235 myrid = 0;
236 start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
237 end = start + ATA_IOSIZE - 1;
238 count = ATA_IOSIZE;
239 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
240 SYS_RES_IOPORT, &myrid,
241 start, end, count, flags);
242 }
243 else {
244 myrid = 0x10 + 8 * unit;
245 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
246 SYS_RES_IOPORT, &myrid,
247 start, end, count, flags);
248 }
249 break;
250
251 case ATA_ALTADDR_RID:
252 if (ATA_MASTERDEV(dev)) {
253 myrid = 0;
254 start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET;
255 end = start + ATA_ALTIOSIZE - 1;
256 count = ATA_ALTIOSIZE;
257 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
258 SYS_RES_IOPORT, &myrid,
259 start, end, count, flags);
260 }
261 else {
262 myrid = 0x14 + 8 * unit;
263 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
264 SYS_RES_IOPORT, &myrid,
265 start, end, count, flags);
266 if (res) {
267 start = rman_get_start(res) + 2;
268 end = start + ATA_ALTIOSIZE - 1;
269 count = ATA_ALTIOSIZE;
270 BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
271 SYS_RES_IOPORT, myrid, res);
272 res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
273 SYS_RES_IOPORT, &myrid,
274 start, end, count, flags);
275 }
276 }
277 break;
278 }
279 return res;
280 }
281
282 if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
283 if (ATA_MASTERDEV(dev)) {
284#ifdef __alpha__
285 return alpha_platform_alloc_ide_intr(unit);
286#else
287 int irq = (unit == 0 ? 14 : 15);
288
289 return BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
290 SYS_RES_IRQ, rid, irq, irq, 1, flags);
291#endif
292 }
293 else {
294 return controller->r_irq;
295 }
296 }
297 return 0;
298}
299
300static int
301ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
302 struct resource *r)
303{
304 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
305
306 if (type == SYS_RES_IOPORT) {
307 switch (rid) {
308 case ATA_IOADDR_RID:
309 if (ATA_MASTERDEV(dev))
310 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
311 SYS_RES_IOPORT, 0x0, r);
312 else
313 return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
314 SYS_RES_IOPORT, 0x10 + 8 * unit, r);
315 break;
316
317 case ATA_ALTADDR_RID:
318 if (ATA_MASTERDEV(dev))
319 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
320 SYS_RES_IOPORT, 0x0, r);
321 else
322 return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
323 SYS_RES_IOPORT, 0x14 + 8 * unit, r);
324 break;
325 default:
326 return ENOENT;
327 }
328 }
329 if (type == SYS_RES_IRQ) {
330 if (rid != ATA_IRQ_RID)
331 return ENOENT;
332
333 if (ATA_MASTERDEV(dev)) {
334#ifdef __alpha__
335 return alpha_platform_release_ide_intr(unit, r);
336#else
337 return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
338 SYS_RES_IRQ, rid, r);
339#endif
340 }
341 else
342 return 0;
343 }
344 return EINVAL;
345}
346
347static int
348ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
349 int flags, driver_intr_t *function, void *argument,
350 void **cookiep)
351{
352 if (ATA_MASTERDEV(dev)) {
353#ifdef __alpha__
354 return alpha_platform_setup_ide_intr(child, irq, function, argument,
355 cookiep);
356#else
357 return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
358 flags, function, argument, cookiep);
359#endif
360 }
361 else {
362 struct ata_pci_controller *controller = device_get_softc(dev);
363 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
364
365 controller->interrupt[unit].function = function;
366 controller->interrupt[unit].argument = argument;
367 *cookiep = controller;
368 return 0;
369 }
370}
371
372static int
373ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
374 void *cookie)
375{
376 if (ATA_MASTERDEV(dev)) {
377#ifdef __alpha__
378 return alpha_platform_teardown_ide_intr(child, irq, cookie);
379#else
380 return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
381#endif
382 }
383 else {
384 struct ata_pci_controller *controller = device_get_softc(dev);
385 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
386
387 controller->interrupt[unit].function = NULL;
388 controller->interrupt[unit].argument = NULL;
389 return 0;
390 }
391}
392
393static int
394ata_pci_allocate(device_t dev, struct ata_channel *ch)
395{
396 struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
397 struct resource *io = NULL, *altio = NULL;
398 int i, rid;
399
400 rid = ATA_IOADDR_RID;
401 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
402 0, ~0, ATA_IOSIZE, RF_ACTIVE);
403 if (!io)
404 return ENXIO;
405
406 rid = ATA_ALTADDR_RID;
407 altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
408 0, ~0, ATA_ALTIOSIZE, RF_ACTIVE);
409 if (!altio) {
410 bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
411 return ENXIO;
412 }
413
414 for (i = ATA_DATA; i <= ATA_STATUS; i ++) {
415 ch->r_io[i].res = io;
416 ch->r_io[i].offset = i;
417 }
418 ch->r_io[ATA_ALTSTAT].res = altio;
419 ch->r_io[ATA_ALTSTAT].offset = 0;
420 ch->r_io[ATA_IDX_ADDR].res = io;
421
422 if (ctlr->r_io1) {
423 for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) {
424 ch->r_io[i].res = ctlr->r_io1;
425 ch->r_io[i].offset = (i - ATA_BMCMD_PORT)+(ch->unit * ATA_BMIOSIZE);
426 }
427
428 /* if simplex controller, only allow DMA on primary channel */
429 ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_IDX_INB(ch, ATA_BMSTAT_PORT) &
430 (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE));
431 if (ch->unit > 0 &&
432 (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_DMA_SIMPLEX))
433 device_printf(dev, "simplex device, DMA on primary only\n");
434 else
435 ctlr->dmainit(ch);
436 }
437 return 0;
438}
439
440static int
441ata_pci_dmastart(struct ata_channel *ch)
442{
443 ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) |
444 (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
445 ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab);
446 ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
447 ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) |
448 ATA_BMCMD_START_STOP);
449 return 0;
450}
451
452static int
453ata_pci_dmastop(struct ata_channel *ch)
454{
455 int error;
456
457 error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
458 ATA_IDX_OUTB(ch, ATA_BMCMD_PORT,
459 ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
460 ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR);
461 return error;
462}
463
464static void
465ata_pci_dmainit(struct ata_channel *ch)
466{
467 ata_dmainit(ch);
468 if (ch->dma) {
469 ch->dma->start = ata_pci_dmastart;
470 ch->dma->stop = ata_pci_dmastop;
471 }
472}
473
474static void
475ata_pci_locknoop(struct ata_channel *ch, int flags)
476{
477}
478
479static device_method_t ata_pci_methods[] = {
480 /* device interface */
481 DEVMETHOD(device_probe, ata_pci_probe),
482 DEVMETHOD(device_attach, ata_pci_attach),
483 DEVMETHOD(device_shutdown, bus_generic_shutdown),
484 DEVMETHOD(device_suspend, bus_generic_suspend),
485 DEVMETHOD(device_resume, bus_generic_resume),
486
487 /* bus methods */
488 DEVMETHOD(bus_print_child, ata_pci_print_child),
489 DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource),
490 DEVMETHOD(bus_release_resource, ata_pci_release_resource),
491 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
492 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
493 DEVMETHOD(bus_setup_intr, ata_pci_setup_intr),
494 DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr),
495 { 0, 0 }
496};
497
498static driver_t ata_pci_driver = {
499 "atapci",
500 ata_pci_methods,
501 sizeof(struct ata_pci_controller),
502};
503
504static devclass_t ata_pci_devclass;
505
506DRIVER_MODULE(atapci, pci, ata_pci_driver, ata_pci_devclass, 0, 0);
507
508static int
509ata_pcisub_probe(device_t dev)
510{
511 struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
512 struct ata_channel *ch = device_get_softc(dev);
513 device_t *children;
514 int count, error, i;
515
516 /* find channel number on this controller */
517 device_get_children(device_get_parent(dev), &children, &count);
518 for (i = 0; i < count; i++) {
519 if (children[i] == dev)
520 ch->unit = i;
521 }
522 free(children, M_TEMP);
523
524 if ((error = ctlr->allocate(dev, ch)))
525 return error;
526
527 ch->device[MASTER].setmode = ctlr->setmode;
528 ch->device[SLAVE].setmode = ctlr->setmode;
529 ch->locking = ctlr->locking;
530 return ata_probe(dev);
531}
532
533static device_method_t ata_pcisub_methods[] = {
534 /* device interface */
535 DEVMETHOD(device_probe, ata_pcisub_probe),
536 DEVMETHOD(device_attach, ata_attach),
537 DEVMETHOD(device_detach, ata_detach),
538 DEVMETHOD(device_suspend, ata_suspend),
539 DEVMETHOD(device_resume, ata_resume),
540 { 0, 0 }
541};
542
543static driver_t ata_pcisub_driver = {
544 "ata",
545 ata_pcisub_methods,
546 sizeof(struct ata_channel),
547};
548
549DRIVER_MODULE(ata, atapci, ata_pcisub_driver, ata_devclass, 0, 0);