1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25
26 /*
27 * PCI-IDE bus nexus driver
28 */
29
30 #include <sys/types.h>
31 #include <sys/cmn_err.h>
32 #include <sys/conf.h>
33 #include <sys/errno.h>
34 #include <sys/debug.h>
35 #include <sys/ddidmareq.h>
36 #include <sys/ddi_impldefs.h>
37 #include <sys/dma_engine.h>
38 #include <sys/modctl.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41 #include <sys/sunndi.h>
42 #include <sys/mach_intr.h>
43 #include <sys/kmem.h>
44 #include <sys/pci.h>
45 #include <sys/promif.h>
46 #include <sys/pci_intr_lib.h>
47 #include <sys/apic.h>
48
49 int pciide_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
50 int pciide_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
51
52 #define PCIIDE_NATIVE_MODE(dip) \
53 (!ddi_prop_exists(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
54 "compatibility-mode"))
55
56 #define PCIIDE_PRE26(dip) \
57 ddi_prop_exists(DDI_DEV_T_ANY, (dip), 0, "ignore-hardware-nodes")
58
59 #define PCI_IDE_IF_BM_CAP_MASK 0x80
60
61 #define PCIIDE_PDSIZE (sizeof (struct ddi_parent_private_data) + \
62 sizeof (struct intrspec))
63
64 #ifdef DEBUG
65 static int pci_ide_debug = 0;
66 #define PDBG(fmt) \
67 if (pci_ide_debug) { \
68 prom_printf fmt; \
69 }
70 #else
71 #define PDBG(fmt)
72 #endif
73
74 #ifndef TRUE
75 #define TRUE 1
76 #endif
77 #ifndef FALSE
78 #define FALSE 0
79 #endif
80
81 /*
82 * bus_ops functions
83 */
84
85 static int pciide_bus_map(dev_info_t *dip, dev_info_t *rdip,
86 ddi_map_req_t *mp, off_t offset, off_t len,
87 caddr_t *vaddrp);
88
89 static int pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip,
90 ddi_ctl_enum_t ctlop, void *arg,
91 void *result);
92
93 static int pciide_get_pri(dev_info_t *dip, dev_info_t *rdip,
94 ddi_intr_handle_impl_t *hdlp, int *pri);
95
96 static int pciide_intr_ops(dev_info_t *dip, dev_info_t *rdip,
97 ddi_intr_op_t intr_op,
98 ddi_intr_handle_impl_t *hdlp, void *result);
99
100 static struct intrspec *pciide_get_ispec(dev_info_t *dip, dev_info_t *rdip,
101 int inum);
102
103 /*
104 * Local Functions
105 */
106 static int pciide_initchild(dev_info_t *mydip, dev_info_t *cdip);
107
108 static void pciide_compat_setup(dev_info_t *mydip, dev_info_t *cdip,
109 int dev);
110 static int pciide_pre26_rnumber_map(dev_info_t *mydip, int rnumber);
111 static int pciide_map_rnumber(int canonical_rnumber, int pri_native,
112 int sec_native);
113 static int pciide_alloc_intr(dev_info_t *, dev_info_t *,
114 ddi_intr_handle_impl_t *, void *);
115 static int pciide_free_intr(dev_info_t *, dev_info_t *,
116 ddi_intr_handle_impl_t *);
117
118 extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *,
119 psm_intr_op_t, int *);
120
121 /*
122 * Config information
123 */
124
125 struct bus_ops pciide_bus_ops = {
126 BUSO_REV,
127 pciide_bus_map,
128 0,
129 0,
130 0,
131 i_ddi_map_fault,
132 ddi_dma_map,
133 ddi_dma_allochdl,
134 ddi_dma_freehdl,
135 ddi_dma_bindhdl,
136 ddi_dma_unbindhdl,
137 ddi_dma_flush,
138 ddi_dma_win,
139 ddi_dma_mctl,
140 pciide_ddi_ctlops,
141 ddi_bus_prop_op,
142 0, /* (*bus_get_eventcookie)(); */
143 0, /* (*bus_add_eventcall)(); */
144 0, /* (*bus_remove_eventcall)(); */
145 0, /* (*bus_post_event)(); */
146 0,
147 0,
148 0,
149 0,
150 0,
151 0,
152 0,
153 0,
154 pciide_intr_ops
155 };
156
157 struct dev_ops pciide_ops = {
158 DEVO_REV, /* devo_rev, */
159 0, /* refcnt */
160 ddi_no_info, /* info */
161 nulldev, /* identify */
162 nulldev, /* probe */
163 pciide_attach, /* attach */
164 pciide_detach, /* detach */
165 nodev, /* reset */
166 (struct cb_ops *)0, /* driver operations */
167 &pciide_bus_ops, /* bus operations */
168 NULL, /* power */
169 ddi_quiesce_not_needed, /* quiesce */
170 };
171
172 /*
173 * Module linkage information for the kernel.
174 */
175
176 static struct modldrv modldrv = {
177 &mod_driverops, /* Type of module. This is PCI-IDE bus driver */
178 "pciide nexus driver for 'PCI-IDE' 1.26",
179 &pciide_ops, /* driver ops */
180 };
181
182 static struct modlinkage modlinkage = {
183 MODREV_1,
184 &modldrv,
185 NULL
186 };
187
188
189 int
_init(void)190 _init(void)
191 {
192 return (mod_install(&modlinkage));
193 }
194
195 int
_fini(void)196 _fini(void)
197 {
198 return (mod_remove(&modlinkage));
199 }
200
201 int
_info(struct modinfo * modinfop)202 _info(struct modinfo *modinfop)
203 {
204 return (mod_info(&modlinkage, modinfop));
205 }
206
207 int
pciide_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)208 pciide_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
209 {
210 uint16_t cmdreg;
211 ddi_acc_handle_t conf_hdl = NULL;
212 int rc;
213
214 switch (cmd) {
215 case DDI_ATTACH:
216 /*
217 * Make sure bus-mastering is enabled, even if
218 * BIOS didn't.
219 */
220 rc = pci_config_setup(dip, &conf_hdl);
221
222 /*
223 * In case of error, return SUCCESS. This is because
224 * bus-mastering could be already enabled by BIOS.
225 */
226 if (rc != DDI_SUCCESS)
227 return (DDI_SUCCESS);
228
229 cmdreg = pci_config_get16(conf_hdl, PCI_CONF_COMM);
230 if ((cmdreg & PCI_COMM_ME) == 0) {
231 pci_config_put16(conf_hdl, PCI_CONF_COMM,
232 cmdreg | PCI_COMM_ME);
233 }
234 pci_config_teardown(&conf_hdl);
235 return (DDI_SUCCESS);
236
237 case DDI_RESUME:
238 /* Restore our PCI configuration header */
239 if (pci_restore_config_regs(dip) != DDI_SUCCESS) {
240 /*
241 * XXXX
242 * This is a pretty bad thing. However, for some
243 * reason it always happens. To further complicate
244 * things, it appears if we just ignore this, we
245 * properly resume. For now, all I want to do is
246 * to generate this message so that it doesn't get
247 * forgotten.
248 */
249 cmn_err(CE_WARN,
250 "Couldn't restore PCI config regs for %s(%p)",
251 ddi_node_name(dip), (void *) dip);
252 }
253 #ifdef DEBUG
254 /* Bus mastering should still be enabled */
255 if (pci_config_setup(dip, &conf_hdl) != DDI_SUCCESS)
256 return (DDI_FAILURE);
257 cmdreg = pci_config_get16(conf_hdl, PCI_CONF_COMM);
258 ASSERT((cmdreg & PCI_COMM_ME) != 0);
259 pci_config_teardown(&conf_hdl);
260 #endif
261 return (DDI_SUCCESS);
262 }
263
264 return (DDI_FAILURE);
265 }
266
267 /*ARGSUSED*/
268 int
pciide_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)269 pciide_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
270 {
271 switch (cmd) {
272 case DDI_DETACH:
273 return (DDI_SUCCESS);
274 case DDI_SUSPEND:
275 /* Save our PCI configuration header */
276 if (pci_save_config_regs(dip) != DDI_SUCCESS) {
277 /* Don't suspend if we cannot save config regs */
278 return (DDI_FAILURE);
279 }
280 return (DDI_SUCCESS);
281 }
282 return (DDI_FAILURE);
283 }
284
285 /*ARGSUSED*/
286 static int
pciide_ddi_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)287 pciide_ddi_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
288 void *arg, void *result)
289 {
290 dev_info_t *cdip;
291 int controller;
292 void *pdptr;
293 int rnumber;
294 off_t tmp;
295 int rc;
296
297 PDBG(("pciide_bus_ctl\n"));
298
299 switch (ctlop) {
300 case DDI_CTLOPS_INITCHILD:
301 cdip = (dev_info_t *)arg;
302 return (pciide_initchild(dip, cdip));
303
304 case DDI_CTLOPS_UNINITCHILD:
305 cdip = (dev_info_t *)arg;
306 pdptr = ddi_get_parent_data(cdip);
307 ddi_set_parent_data(cdip, NULL);
308 ddi_set_name_addr(cdip, NULL);
309 kmem_free(pdptr, PCIIDE_PDSIZE);
310 return (DDI_SUCCESS);
311
312 case DDI_CTLOPS_NREGS:
313 *(int *)result = 3;
314 return (DDI_SUCCESS);
315
316 case DDI_CTLOPS_REGSIZE:
317 /*
318 * Adjust the rnumbers based on which controller instance
319 * is requested; adjust for the 2 tuples per controller.
320 */
321 if (strcmp("0", ddi_get_name_addr(rdip)) == 0)
322 controller = 0;
323 else
324 controller = 1;
325
326
327 switch (rnumber = *(int *)arg) {
328 case 0:
329 case 1:
330 rnumber += (2 * controller);
331 break;
332 case 2:
333 rnumber = 4;
334 break;
335 default:
336 PDBG(("pciide_ctlops invalid rnumber\n"));
337 return (DDI_FAILURE);
338 }
339
340
341 if (PCIIDE_PRE26(dip)) {
342 int old_rnumber;
343 int new_rnumber;
344
345 old_rnumber = rnumber;
346 new_rnumber
347 = pciide_pre26_rnumber_map(dip, old_rnumber);
348 PDBG(("pciide rnumber old %d new %d\n",
349 old_rnumber, new_rnumber));
350 rnumber = new_rnumber;
351 }
352
353 /*
354 * Add 1 to skip over the PCI config space tuple
355 */
356 rnumber++;
357
358 /*
359 * If it's not tuple #2 pass the adjusted request to my parent
360 */
361 if (*(int *)arg != 2) {
362 return (ddi_ctlops(dip, dip, ctlop, &rnumber, result));
363 }
364
365 /*
366 * Handle my child's reg-tuple #2 here by splitting my 16 byte
367 * reg-tuple #4 into two 8 byte ranges based on the
368 * the child's controller #.
369 */
370
371 tmp = 8;
372 rc = ddi_ctlops(dip, dip, ctlop, &rnumber, &tmp);
373
374 /*
375 * Allow for the possibility of less than 16 bytes by
376 * by checking what's actually returned for my reg-tuple #4.
377 */
378 if (controller == 1) {
379 if (tmp < 8)
380 tmp = 0;
381 else
382 tmp -= 8;
383 }
384 if (tmp > 8)
385 tmp = 8;
386 *(off_t *)result = tmp;
387
388 return (rc);
389
390 case DDI_CTLOPS_ATTACH:
391 case DDI_CTLOPS_DETACH:
392 /*
393 * Don't pass child ide ATTACH/DETACH to parent
394 */
395 return (DDI_SUCCESS);
396
397 default:
398 return (ddi_ctlops(dip, rdip, ctlop, arg, result));
399 }
400 }
401
402 /*
403 * IEEE 1275 Working Group Proposal #414 says that the Primary
404 * controller is "ata@0" and the Secondary controller "ata@1".
405 *
406 * By the time we get here, boot Bootconf (2.6+) has created devinfo
407 * nodes with the appropriate "reg", "assigned-addresses" and "interrupts"
408 * properites on the pci-ide node and both ide child nodes.
409 *
410 * In compatibility mode the "reg" and "assigned-addresses" properties
411 * of the pci-ide node are set up like this:
412 *
413 * 1. PCI-IDE Nexus
414 *
415 * interrupts=0
416 * (addr-hi addr-mid addr-low size-hi size-low)
417 * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000
418 * 81000000.00000000.000001f0.00000000.00000008
419 * 81000000.00000000.000003f4.00000000.00000004
420 * 81000000.00000000,00000170.00000000.00000008
421 * 81000000.00000000,00000374.00000000.00000004
422 * 01000020.00000000,-[BAR4]-.00000000.00000010
423 *
424 * In native PCI mode the "reg" and "assigned-addresses" properties
425 * would be set up like this:
426 *
427 * 2. PCI-IDE Nexus
428 *
429 * interrupts=0
430 * reg= assigned-addresses=00000000.00000000.00000000.00000000.00000000
431 * 01000010.00000000.-[BAR0]-.00000000.00000008
432 * 01000014,00000000.-[BAR1]-.00000000.00000004
433 * 01000018.00000000.-[BAR2]-.00000000.00000008
434 * 0100001c.00000000.-[BAR3]-.00000000.00000004
435 * 01000020.00000000.-[BAR4]-.00000000.00000010
436 *
437 *
438 * In both modes the child nodes simply have the following:
439 *
440 * 2. primary controller (compatibility mode)
441 *
442 * interrupts=14
443 * reg=00000000
444 *
445 * 3. secondary controller
446 *
447 * interrupts=15
448 * reg=00000001
449 *
450 * The pciide_bus_map() function is responsible for turning requests
451 * to map primary or secondary controller rnumbers into mapping requests
452 * of the appropriate regspec on the pci-ide node.
453 *
454 */
455
456 static int
pciide_initchild(dev_info_t * mydip,dev_info_t * cdip)457 pciide_initchild(dev_info_t *mydip, dev_info_t *cdip)
458 {
459 struct ddi_parent_private_data *pdptr;
460 struct intrspec *ispecp;
461 int vec;
462 int *rp;
463 uint_t proplen;
464 char name[80];
465 int dev;
466
467 PDBG(("pciide_initchild\n"));
468
469 /*
470 * Set the address portion of the node name based on
471 * the controller number (0 or 1) from the 'reg' property.
472 */
473 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
474 "reg", &rp, (uint_t *)&proplen) != DDI_PROP_SUCCESS) {
475 PDBG(("pciide_intchild prop error\n"));
476 return (DDI_NOT_WELL_FORMED);
477 }
478
479 /*
480 * copy the controller number and
481 * free the memory allocated by ddi_prop_lookup_int_array
482 */
483 dev = *rp;
484 ddi_prop_free(rp);
485
486 /*
487 * I only support two controllers per device, determine
488 * which this one is and set its unit address.
489 */
490 if (dev > 1) {
491 PDBG(("pciide_initchild bad dev\n"));
492 return (DDI_NOT_WELL_FORMED);
493 }
494 (void) sprintf(name, "%d", dev);
495 ddi_set_name_addr(cdip, name);
496
497 /*
498 * determine if this instance is running in native or compat mode
499 */
500 pciide_compat_setup(mydip, cdip, dev);
501
502 /* interrupts property is required */
503 if (PCIIDE_NATIVE_MODE(cdip)) {
504 vec = 1;
505 } else {
506 /*
507 * In compatibility mode, dev 0 should always be
508 * IRQ 14 and dev 1 is IRQ 15. If for some reason
509 * this needs to be changed, do it via the interrupts
510 * property in the ata.conf file.
511 */
512 vec = ddi_prop_get_int(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
513 "interrupts", -1);
514 if (vec == -1) {
515 /* setup compatibility mode interrupts */
516 if (dev == 0) {
517 vec = 14;
518 } else if (dev == 1) {
519 vec = 15;
520 } else {
521 PDBG(("pciide_initchild bad intr\n"));
522 return (DDI_NOT_WELL_FORMED);
523 }
524 }
525 }
526
527 pdptr = kmem_zalloc(PCIIDE_PDSIZE, KM_SLEEP);
528 ispecp = (struct intrspec *)(pdptr + 1);
529 pdptr->par_nintr = 1;
530 pdptr->par_intr = ispecp;
531 ispecp->intrspec_vec = vec;
532 ddi_set_parent_data(cdip, pdptr);
533
534 PDBG(("pciide_initchild okay\n"));
535 return (DDI_SUCCESS);
536 }
537
538 static int
pciide_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)539 pciide_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
540 off_t offset, off_t len, caddr_t *vaddrp)
541 {
542 dev_info_t *pdip;
543 int rnumber = mp->map_obj.rnumber;
544 int controller;
545 int rc;
546
547 PDBG(("pciide_bus_map\n"));
548
549 if (strcmp("0", ddi_get_name_addr(rdip)) == 0)
550 controller = 0;
551 else
552 controller = 1;
553
554 /*
555 * Adjust the rnumbers based on which controller instance
556 * is being mapped; adjust for the 2 tuples per controller.
557 */
558
559 switch (rnumber) {
560 case 0:
561 case 1:
562 mp->map_obj.rnumber += (controller * 2);
563 break;
564 case 2:
565 /*
566 * split the 16 I/O ports into two 8 port ranges
567 */
568 mp->map_obj.rnumber = 4;
569 if (offset + len > 8) {
570 PDBG(("pciide_bus_map offset\n"));
571 return (DDI_FAILURE);
572 }
573 if (len == 0)
574 len = 8 - offset;
575 offset += 8 * controller;
576 break;
577 default:
578 PDBG(("pciide_bus_map default\n"));
579 return (DDI_FAILURE);
580 }
581
582 if (PCIIDE_PRE26(dip)) {
583 int old_rnumber;
584 int new_rnumber;
585
586 old_rnumber = mp->map_obj.rnumber;
587 new_rnumber = pciide_pre26_rnumber_map(dip, old_rnumber);
588 PDBG(("pciide rnumber old %d new %d\n",
589 old_rnumber, new_rnumber));
590 mp->map_obj.rnumber = new_rnumber;
591 }
592
593 /*
594 * Add 1 to skip over the PCI config space tuple
595 */
596 mp->map_obj.rnumber++;
597
598
599 /*
600 * pass the adjusted request to my parent
601 */
602 pdip = ddi_get_parent(dip);
603 rc = ((*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_map))
604 (pdip, dip, mp, offset, len, vaddrp));
605
606 PDBG(("pciide_bus_map %s\n", rc == DDI_SUCCESS ? "okay" : "!ok"));
607
608 return (rc);
609 }
610
611
612 static struct intrspec *
pciide_get_ispec(dev_info_t * dip,dev_info_t * rdip,int inumber)613 pciide_get_ispec(dev_info_t *dip, dev_info_t *rdip, int inumber)
614 {
615 struct ddi_parent_private_data *ppdptr;
616
617 PDBG(("pciide_get_ispec\n"));
618
619 /*
620 * Native mode PCI-IDE controllers share the parent's
621 * PCI interrupt line.
622 *
623 * Compatibility mode PCI-IDE controllers have their
624 * own intrspec which specifies ISA IRQ 14 or 15.
625 *
626 */
627 if (PCIIDE_NATIVE_MODE(rdip)) {
628 ddi_intrspec_t is;
629
630 is = pci_intx_get_ispec(dip, dip, inumber);
631 PDBG(("pciide_get_ispec okay\n"));
632 return ((struct intrspec *)is);
633 }
634
635 /* Else compatibility mode, use the ISA IRQ */
636 if ((ppdptr = ddi_get_parent_data(rdip)) == NULL) {
637 PDBG(("pciide_get_ispec null\n"));
638 return (NULL);
639 }
640
641 /* validate the interrupt number */
642 if (inumber >= ppdptr->par_nintr) {
643 PDBG(("pciide_get_inum\n"));
644 return (NULL);
645 }
646
647 PDBG(("pciide_get_ispec ok\n"));
648
649 return ((struct intrspec *)&ppdptr->par_intr[inumber]);
650 }
651
652 static int
pciide_get_pri(dev_info_t * dip,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp,int * pri)653 pciide_get_pri(dev_info_t *dip, dev_info_t *rdip,
654 ddi_intr_handle_impl_t *hdlp, int *pri)
655 {
656 struct intrspec *ispecp;
657 int *intpriorities;
658 uint_t num_intpriorities;
659
660 PDBG(("pciide_get_pri\n"));
661
662 if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == NULL) {
663 PDBG(("pciide_get_pri null\n"));
664 return (DDI_FAILURE);
665 }
666
667 if (PCIIDE_NATIVE_MODE(rdip)) {
668 *pri = ispecp->intrspec_pri;
669 PDBG(("pciide_get_pri ok\n"));
670 return (DDI_SUCCESS);
671 }
672
673 /* check if the intrspec has been initialized */
674 if (ispecp->intrspec_pri != 0) {
675 *pri = ispecp->intrspec_pri;
676 PDBG(("pciide_get_pri ok2\n"));
677 return (DDI_SUCCESS);
678 }
679
680 /* Use a default of level 5 */
681 ispecp->intrspec_pri = 5;
682
683 /*
684 * If there's an interrupt-priorities property, use it to
685 * over-ride the default interrupt priority.
686 */
687 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
688 "interrupt-priorities", &intpriorities, &num_intpriorities) ==
689 DDI_PROP_SUCCESS) {
690 if (hdlp->ih_inum < num_intpriorities)
691 ispecp->intrspec_pri = intpriorities[hdlp->ih_inum];
692 ddi_prop_free(intpriorities);
693 }
694 *pri = ispecp->intrspec_pri;
695
696 PDBG(("pciide_get_pri ok3\n"));
697
698 return (DDI_SUCCESS);
699 }
700
701 static int
pciide_intr_ops(dev_info_t * dip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)702 pciide_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
703 ddi_intr_handle_impl_t *hdlp, void *result)
704 {
705 struct intrspec *ispecp;
706 int rc;
707 int pri = 0;
708
709 PDBG(("pciide_intr_ops: dip %p rdip %p op %x hdlp %p\n",
710 (void *)dip, (void *)rdip, intr_op, (void *)hdlp));
711
712 switch (intr_op) {
713 case DDI_INTROP_SUPPORTED_TYPES:
714 *(int *)result = DDI_INTR_TYPE_FIXED;
715 break;
716 case DDI_INTROP_GETCAP:
717 *(int *)result = DDI_INTR_FLAG_LEVEL;
718 break;
719 case DDI_INTROP_NINTRS:
720 case DDI_INTROP_NAVAIL:
721 *(int *)result = (!PCIIDE_NATIVE_MODE(rdip)) ?
722 i_ddi_get_intx_nintrs(rdip) : 1;
723 break;
724 case DDI_INTROP_ALLOC:
725 return (pciide_alloc_intr(dip, rdip, hdlp, result));
726 case DDI_INTROP_FREE:
727 return (pciide_free_intr(dip, rdip, hdlp));
728 case DDI_INTROP_GETPRI:
729 if (pciide_get_pri(dip, rdip, hdlp, &pri) != DDI_SUCCESS) {
730 *(int *)result = 0;
731 return (DDI_FAILURE);
732 }
733 *(int *)result = pri;
734 break;
735 case DDI_INTROP_ADDISR:
736 if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) ==
737 NULL)
738 return (DDI_FAILURE);
739 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispecp;
740 ispecp->intrspec_func = hdlp->ih_cb_func;
741 break;
742 case DDI_INTROP_REMISR:
743 if ((ispecp = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) ==
744 NULL)
745 return (DDI_FAILURE);
746 ispecp->intrspec_func = (uint_t (*)()) 0;
747 break;
748 case DDI_INTROP_ENABLE:
749 /* FALLTHRU */
750 case DDI_INTROP_DISABLE:
751 if (PCIIDE_NATIVE_MODE(rdip)) {
752 rdip = dip;
753 dip = ddi_get_parent(dip);
754 } else { /* get ptr to the root node */
755 dip = ddi_root_node();
756 }
757
758 rc = (*(DEVI(dip)->devi_ops->devo_bus_ops->bus_intr_op))(dip,
759 rdip, intr_op, hdlp, result);
760
761 #ifdef DEBUG
762 if (intr_op == DDI_INTROP_ENABLE) {
763 PDBG(("pciide_enable rc=%d", rc));
764 } else
765 PDBG(("pciide_disable rc=%d", rc));
766 #endif /* DEBUG */
767 return (rc);
768 default:
769 return (DDI_FAILURE);
770 }
771
772 return (DDI_SUCCESS);
773 }
774
775 int
pciide_alloc_intr(dev_info_t * dip,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp,void * result)776 pciide_alloc_intr(dev_info_t *dip, dev_info_t *rdip,
777 ddi_intr_handle_impl_t *hdlp, void *result)
778 {
779 struct intrspec *ispec;
780 ddi_intr_handle_impl_t info_hdl;
781 int ret;
782 int free_phdl = 0;
783 apic_get_type_t type_info;
784
785 if (psm_intr_ops == NULL)
786 return (DDI_FAILURE);
787
788 if ((ispec = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) == NULL)
789 return (DDI_FAILURE);
790
791 /*
792 * If the PSM module is "APIX" then pass the request for it
793 * to allocate the vector now.
794 */
795 bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t));
796 info_hdl.ih_private = &type_info;
797 if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) ==
798 PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) {
799 if (hdlp->ih_private == NULL) { /* allocate phdl structure */
800 free_phdl = 1;
801 i_ddi_alloc_intr_phdl(hdlp);
802 }
803 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
804 if (PCIIDE_NATIVE_MODE(rdip)) {
805 rdip = dip;
806 dip = ddi_get_parent(dip);
807 } else { /* get ptr to the root node */
808 dip = ddi_root_node();
809 }
810 ret = (*psm_intr_ops)(rdip, hdlp,
811 PSM_INTR_OP_ALLOC_VECTORS, result);
812 if (free_phdl) { /* free up the phdl structure */
813 free_phdl = 0;
814 i_ddi_free_intr_phdl(hdlp);
815 }
816 } else {
817 /*
818 * No APIX module; fall back to the old scheme where the
819 * interrupt vector is allocated during ddi_enable_intr() call.
820 */
821 *(int *)result = hdlp->ih_scratch1;
822 ret = DDI_SUCCESS;
823 }
824
825 return (ret);
826 }
827
828 int
pciide_free_intr(dev_info_t * dip,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp)829 pciide_free_intr(dev_info_t *dip, dev_info_t *rdip,
830 ddi_intr_handle_impl_t *hdlp)
831 {
832 struct intrspec *ispec;
833 ddi_intr_handle_impl_t info_hdl;
834 apic_get_type_t type_info;
835
836 if (psm_intr_ops == NULL)
837 return (DDI_FAILURE);
838
839 /*
840 * If the PSM module is "APIX" then pass the request for it
841 * to free up the vector now.
842 */
843 bzero(&info_hdl, sizeof (ddi_intr_handle_impl_t));
844 info_hdl.ih_private = &type_info;
845 if ((*psm_intr_ops)(NULL, &info_hdl, PSM_INTR_OP_APIC_TYPE, NULL) ==
846 PSM_SUCCESS && strcmp(type_info.avgi_type, APIC_APIX_NAME) == 0) {
847 if ((ispec = pciide_get_ispec(dip, rdip, hdlp->ih_inum)) ==
848 NULL)
849 return (DDI_FAILURE);
850 ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
851 if (PCIIDE_NATIVE_MODE(rdip)) {
852 rdip = dip;
853 dip = ddi_get_parent(dip);
854 } else { /* get ptr to the root node */
855 dip = ddi_root_node();
856 }
857 return ((*psm_intr_ops)(rdip, hdlp,
858 PSM_INTR_OP_FREE_VECTORS, NULL));
859 }
860
861 /*
862 * No APIX module; fall back to the old scheme where
863 * the interrupt vector was already freed during
864 * ddi_disable_intr() call.
865 */
866 return (DDI_SUCCESS);
867 }
868
869 /*
870 * This is one of the places where controller specific setup needs to be
871 * considered.
872 * At this point the controller was already pre-qualified as a known and
873 * supported pciide controller.
874 * Some controllers do not provide PCI_MASS_IDE sub-class code and IDE
875 * programming interface code but rather PCI_MASS_OTHER sub-class code
876 * without any additional data.
877 * For those controllers IDE programming interface cannot be extracted
878 * from PCI class - we assume that they are pci-native type and we fix
879 * the programming interface used by other functions.
880 * The programming interface byte is set to indicate pci-native mode
881 * for both controllers and the Bus Master DMA capabilitiy of the controller.
882 */
883 static void
pciide_compat_setup(dev_info_t * mydip,dev_info_t * cdip,int dev)884 pciide_compat_setup(dev_info_t *mydip, dev_info_t *cdip, int dev)
885 {
886 int class_code;
887 int rc = DDI_PROP_SUCCESS;
888
889 class_code = ddi_prop_get_int(DDI_DEV_T_ANY, mydip,
890 DDI_PROP_DONTPASS, "class-code", 0);
891
892 if (((class_code & 0x00FF00) >> 8) == PCI_MASS_IDE) {
893 /*
894 * Controller provides PCI_MASS_IDE sub-class code first
895 * (implied IDE programming interface)
896 */
897 if ((dev == 0 && !(class_code & PCI_IDE_IF_NATIVE_PRI)) ||
898 (dev == 1 && !(class_code & PCI_IDE_IF_NATIVE_SEC))) {
899 rc = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
900 "compatibility-mode", 1);
901 if (rc != DDI_PROP_SUCCESS)
902 cmn_err(CE_WARN,
903 "pciide prop error %d compat-mode", rc);
904 }
905 } else {
906 /*
907 * Pci-ide controllers not providing PCI_MASS_IDE sub-class are
908 * assumed to be of pci-native type and bus master DMA capable.
909 * Programming interface part of the class-code property is
910 * fixed here.
911 */
912 class_code &= 0x00ffff00;
913 class_code |= PCI_IDE_IF_BM_CAP_MASK |
914 PCI_IDE_IF_NATIVE_PRI | PCI_IDE_IF_NATIVE_SEC;
915 rc = ddi_prop_update_int(DDI_DEV_T_NONE, mydip,
916 "class-code", class_code);
917 if (rc != DDI_PROP_SUCCESS)
918 cmn_err(CE_WARN,
919 "pciide prop error %d class-code", rc);
920 }
921 }
922
923
924 static int
pciide_pre26_rnumber_map(dev_info_t * mydip,int rnumber)925 pciide_pre26_rnumber_map(dev_info_t *mydip, int rnumber)
926 {
927 int pri_native;
928 int sec_native;
929 int class_code;
930
931 class_code = ddi_prop_get_int(DDI_DEV_T_ANY, mydip, DDI_PROP_DONTPASS,
932 "class-code", 0);
933
934 pri_native = (class_code & PCI_IDE_IF_NATIVE_PRI) ? TRUE : FALSE;
935 sec_native = (class_code & PCI_IDE_IF_NATIVE_SEC) ? TRUE : FALSE;
936
937 return (pciide_map_rnumber(rnumber, pri_native, sec_native));
938
939 }
940
941 /*
942 * The canonical order of the reg property tuples for the
943 * Base Address Registers is supposed to be:
944 *
945 * primary controller (BAR 0)
946 * primary controller (BAR 1)
947 * secondary controller (BAR 2)
948 * secondary controller (BAR 3)
949 * bus mastering regs (BAR 4)
950 *
951 * For 2.6, bootconf has been fixed to always generate the
952 * reg property (and assigned-addresses property) tuples
953 * in the above order.
954 *
955 * But in releases prior to 2.6 the order varies depending
956 * on whether compatibility or native mode is being used for
957 * each controller. There ends up being four possible
958 * orders:
959 *
960 * BM, P0, P1, S0, S1 primary compatible, secondary compatible
961 * S0, S1, BM, P0, P1 primary compatible, secondary native
962 * P0, P1, BM, S0, S1 primary native, secondary compatible
963 * P0, P1, S0, S1, BM primary native, secondary native
964 *
965 * where: Px is the primary tuples, Sx the secondary tuples, and
966 * B the Bus Master tuple.
967 *
968 * Here's the results for each of the four states:
969 *
970 * 0, 1, 2, 3, 4
971 *
972 * CC 1, 2, 3, 4, 0
973 * CN 3, 4, 0, 1, 2
974 * NC 0, 1, 3, 4, 2
975 * NN 0, 1, 2, 3, 4
976 *
977 * C = compatible(!native) == 0
978 * N = native == 1
979 *
980 * Here's the transformation matrix:
981 */
982
983 static int pciide_transform[2][2][5] = {
984 /* P S */
985 /* [C][C] */ +1, +1, +1, +1, -4,
986 /* [C][N] */ +3, +3, -2, -2, -2,
987 /* [N][C] */ +0, +0, +1, +1, -2,
988 /* [N][N] */ +0, +0, +0, +0, +0
989 };
990
991
992 static int
pciide_map_rnumber(int rnumber,int pri_native,int sec_native)993 pciide_map_rnumber(int rnumber, int pri_native, int sec_native)
994 {
995 /* transform flags into indexes */
996 pri_native = pri_native ? 1 : 0;
997 sec_native = sec_native ? 1 : 0;
998
999 rnumber += pciide_transform[pri_native][sec_native][rnumber];
1000 return (rnumber);
1001 }
1002