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 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/ddi_impldefs.h>
33 #include <sys/ddi_subrdefs.h>
34 #include <sys/pci.h>
35 #include <sys/pci/pci_nexus.h>
36 #include <sys/autoconf.h>
37 #include <sys/cmn_err.h>
38 #include <sys/errno.h>
39 #include <sys/kmem.h>
40 #include <sys/debug.h>
41 #include <sys/sysmacros.h>
42 #include <sys/acebus.h>
43
44 #ifdef DEBUG
45 static uint_t acebus_debug_flags = 0;
46 #endif
47
48 /*
49 * The values of the following variables are used to initialize
50 * the cache line size and latency timer registers in the ebus
51 * configuration header. Variables are used instead of constants
52 * to allow tuning from the /etc/system file.
53 */
54 static uint8_t acebus_cache_line_size = 0x10; /* 64 bytes */
55 static uint8_t acebus_latency_timer = 0x40; /* 64 PCI cycles */
56
57 /*
58 * function prototypes for bus ops routines:
59 */
60 static int
61 acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
62 off_t offset, off_t len, caddr_t *addrp);
63 static int
64 acebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
65 ddi_ctl_enum_t op, void *arg, void *result);
66 static int
67 acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
68 ddi_intr_handle_impl_t *hdlp, void *result);
69
70 /*
71 * function prototypes for dev ops routines:
72 */
73 static int acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
74 static int acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
75
76 /*
77 * general function prototypes:
78 */
79 static int acebus_config(ebus_devstate_t *ebus_p);
80 static int acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
81 ebus_regspec_t *ebus_rp, pci_regspec_t *rp);
82 static int acebus_get_ranges_prop(ebus_devstate_t *ebus_p);
83 #ifdef ACEBUS_HOTPLUG
84 static int acebus_update_props(ebus_devstate_t *ebus_p);
85 static int acebus_set_imap(dev_info_t *dip);
86 #endif
87
88 #define getprop(dip, name, addr, intp) \
89 ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
90 (name), (caddr_t)(addr), (intp))
91
92 /*
93 * bus ops and dev ops structures:
94 */
95 static struct bus_ops acebus_bus_ops = {
96 BUSO_REV,
97 acebus_map,
98 NULL,
99 NULL,
100 NULL,
101 i_ddi_map_fault,
102 ddi_dma_map,
103 ddi_dma_allochdl,
104 ddi_dma_freehdl,
105 ddi_dma_bindhdl,
106 ddi_dma_unbindhdl,
107 ddi_dma_flush,
108 ddi_dma_win,
109 ddi_dma_mctl,
110 acebus_ctlops,
111 ddi_bus_prop_op,
112 0, /* (*bus_get_eventcookie)(); */
113 0, /* (*bus_add_eventcall)(); */
114 0, /* (*bus_remove_eventcall)(); */
115 0, /* (*bus_post_event)(); */
116 0, /* (*bus_intr_ctl)(); */
117 NULL, /* (*bus_config)(); */
118 NULL, /* (*bus_unconfig)(); */
119 NULL, /* (*bus_fm_init)(); */
120 NULL, /* (*bus_fm_fini)(); */
121 NULL, /* (*bus_fm_access_enter)(); */
122 NULL, /* (*bus_fm_access_fini)(); */
123 NULL, /* (*bus_power)(); */
124 acebus_intr_ops /* (*bus_intr_op)(); */
125 };
126
127 static struct dev_ops acebus_ops = {
128 DEVO_REV,
129 0,
130 ddi_no_info,
131 nulldev,
132 nulldev,
133 acebus_attach,
134 acebus_detach,
135 nodev,
136 (struct cb_ops *)0,
137 &acebus_bus_ops,
138 NULL,
139 ddi_quiesce_not_supported, /* devo_quiesce */
140 };
141
142 /*
143 * module definitions:
144 */
145 #include <sys/modctl.h>
146 extern struct mod_ops mod_driverops;
147
148 static struct modldrv modldrv = {
149 &mod_driverops, /* Type of module. This one is a driver */
150 "Alarm Card ebus nexus", /* Name of module. */
151 &acebus_ops, /* driver ops */
152 };
153
154 static struct modlinkage modlinkage = {
155 MODREV_1, (void *)&modldrv, NULL
156 };
157
158 /*
159 * driver global data:
160 */
161 static void *per_acebus_state; /* per-ebus soft state pointer */
162
163
164 int
_init(void)165 _init(void)
166 {
167 int e;
168
169 /*
170 * Initialize per-ebus soft state pointer.
171 */
172 e = ddi_soft_state_init(&per_acebus_state, sizeof (ebus_devstate_t), 1);
173 if (e != 0)
174 return (e);
175
176 /*
177 * Install the module.
178 */
179 e = mod_install(&modlinkage);
180 if (e != 0)
181 ddi_soft_state_fini(&per_acebus_state);
182 return (e);
183 }
184
185 int
_fini(void)186 _fini(void)
187 {
188 int e;
189
190 /*
191 * Remove the module.
192 */
193 e = mod_remove(&modlinkage);
194 if (e != 0)
195 return (e);
196
197 /*
198 * Free the soft state info.
199 */
200 ddi_soft_state_fini(&per_acebus_state);
201 return (e);
202 }
203
204 int
_info(struct modinfo * modinfop)205 _info(struct modinfo *modinfop)
206 {
207 return (mod_info(&modlinkage, modinfop));
208 }
209
210 /* device driver entry points */
211
212 /*
213 * attach entry point:
214 *
215 * normal attach:
216 *
217 * create soft state structure (dip, reg, nreg and state fields)
218 * map in configuration header
219 * make sure device is properly configured
220 * report device
221 */
222 static int
acebus_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)223 acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
224 {
225 ebus_devstate_t *ebus_p; /* per ebus state pointer */
226 int instance;
227
228 DBG1(D_ATTACH, NULL, "dip=%x\n", dip);
229 switch (cmd) {
230 case DDI_ATTACH:
231
232 /*
233 * Allocate soft state for this instance.
234 */
235 instance = ddi_get_instance(dip);
236 if (ddi_soft_state_zalloc(per_acebus_state, instance)
237 != DDI_SUCCESS) {
238 DBG(D_ATTACH, NULL, "failed to alloc soft state\n");
239 return (DDI_FAILURE);
240 }
241 ebus_p = get_acebus_soft_state(instance);
242 ebus_p->dip = dip;
243
244 /*
245 * Make sure the master enable and memory access enable
246 * bits are set in the config command register.
247 */
248 if (!acebus_config(ebus_p)) {
249 free_acebus_soft_state(instance);
250 return (DDI_FAILURE);
251 }
252
253 (void) ddi_prop_create(DDI_DEV_T_NONE, dip,
254 DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0);
255 /* Get our ranges property for mapping child registers. */
256 if (acebus_get_ranges_prop(ebus_p) != DDI_SUCCESS) {
257 free_acebus_soft_state(instance);
258 return (DDI_FAILURE);
259 }
260
261 /*
262 * Make the state as attached and report the device.
263 */
264 ebus_p->state = ATTACHED;
265 ddi_report_dev(dip);
266 DBG(D_ATTACH, ebus_p, "returning\n");
267 return (DDI_SUCCESS);
268
269 case DDI_RESUME:
270
271 instance = ddi_get_instance(dip);
272 ebus_p = get_acebus_soft_state(instance);
273
274 /*
275 * Make sure the master enable and memory access enable
276 * bits are set in the config command register.
277 */
278 if (!acebus_config(ebus_p)) {
279 free_acebus_soft_state(instance);
280 return (DDI_FAILURE);
281 }
282
283 ebus_p->state = RESUMED;
284 return (DDI_SUCCESS);
285 }
286 return (DDI_FAILURE);
287 }
288
289 /*
290 * detach entry point:
291 */
292 static int
acebus_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)293 acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
294 {
295 int instance = ddi_get_instance(dip);
296 ebus_devstate_t *ebus_p = get_acebus_soft_state(instance);
297
298 switch (cmd) {
299 case DDI_DETACH:
300 DBG1(D_DETACH, ebus_p, "DDI_DETACH dip=%p\n", dip);
301 ddi_prop_remove_all(dip);
302 kmem_free(ebus_p->rangep, ebus_p->range_cnt *
303 sizeof (struct ebus_pci_rangespec));
304 free_acebus_soft_state(instance);
305 return (DDI_SUCCESS);
306
307 case DDI_SUSPEND:
308 DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip);
309 ebus_p->state = SUSPENDED;
310 return (DDI_SUCCESS);
311 }
312 return (DDI_FAILURE);
313 }
314
315
316 static int
acebus_get_ranges_prop(ebus_devstate_t * ebus_p)317 acebus_get_ranges_prop(ebus_devstate_t *ebus_p)
318 {
319 struct ebus_pci_rangespec *rangep;
320 int nrange, range_len;
321
322 if (ddi_getlongprop(DDI_DEV_T_ANY, ebus_p->dip, DDI_PROP_DONTPASS,
323 "ranges", (caddr_t)&rangep, &range_len) != DDI_SUCCESS) {
324
325 cmn_err(CE_WARN, "%s%d: can't get ranges property",
326 ddi_get_name(ebus_p->dip), ddi_get_instance(ebus_p->dip));
327 return (DDI_ME_REGSPEC_RANGE);
328 }
329
330 nrange = range_len / sizeof (struct ebus_pci_rangespec);
331
332 if (nrange == 0) {
333 kmem_free(rangep, range_len);
334 return (DDI_FAILURE);
335 }
336
337 #ifdef DEBUG
338 {
339 int i;
340
341 for (i = 0; i < nrange; i++) {
342 DBG5(D_MAP, ebus_p,
343 "ebus range addr 0x%x.0x%x PCI range "
344 "addr 0x%x.0x%x.0x%x ", rangep[i].ebus_phys_hi,
345 rangep[i].ebus_phys_low, rangep[i].pci_phys_hi,
346 rangep[i].pci_phys_mid, rangep[i].pci_phys_low);
347 DBG1(D_MAP, ebus_p, "Size 0x%x\n", rangep[i].rng_size);
348 }
349 }
350 #endif /* DEBUG */
351
352 ebus_p->rangep = rangep;
353 ebus_p->range_cnt = nrange;
354
355 return (DDI_SUCCESS);
356 }
357
358
359 /* bus driver entry points */
360
361 /*
362 * bus map entry point:
363 *
364 * if map request is for an rnumber
365 * get the corresponding regspec from device node
366 * build a new regspec in our parent's format
367 * build a new map_req with the new regspec
368 * call up the tree to complete the mapping
369 */
370 static int
acebus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t off,off_t len,caddr_t * addrp)371 acebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
372 off_t off, off_t len, caddr_t *addrp)
373 {
374 ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip));
375 ebus_regspec_t *ebus_rp, *ebus_regs;
376 pci_regspec_t pci_reg;
377 ddi_map_req_t p_map_request;
378 int rnumber, i, n;
379 int rval = DDI_SUCCESS;
380
381 /*
382 * Handle the mapping according to its type.
383 */
384 DBG4(D_MAP, ebus_p, "rdip=%s%d: off=%x len=%x\n",
385 ddi_get_name(rdip), ddi_get_instance(rdip), off, len);
386 switch (mp->map_type) {
387 case DDI_MT_REGSPEC:
388
389 /*
390 * We assume the register specification is in ebus format.
391 * We must convert it into a PCI format regspec and pass
392 * the request to our parent.
393 */
394 DBG3(D_MAP, ebus_p, "rdip=%s%d: REGSPEC - handlep=%x\n",
395 ddi_get_name(rdip), ddi_get_instance(rdip),
396 mp->map_handlep);
397 ebus_rp = (ebus_regspec_t *)mp->map_obj.rp;
398 break;
399
400 case DDI_MT_RNUMBER:
401
402 /*
403 * Get the "reg" property from the device node and convert
404 * it to our parent's format.
405 */
406 rnumber = mp->map_obj.rnumber;
407 DBG4(D_MAP, ebus_p, "rdip=%s%d: rnumber=%x handlep=%x\n",
408 ddi_get_name(rdip), ddi_get_instance(rdip),
409 rnumber, mp->map_handlep);
410
411 if (getprop(rdip, "reg", &ebus_regs, &i) != DDI_SUCCESS) {
412 DBG(D_MAP, ebus_p, "can't get reg property\n");
413 return (DDI_ME_RNUMBER_RANGE);
414 }
415 n = i / sizeof (ebus_regspec_t);
416
417 if (rnumber < 0 || rnumber >= n) {
418 DBG(D_MAP, ebus_p, "rnumber out of range\n");
419 return (DDI_ME_RNUMBER_RANGE);
420 }
421 ebus_rp = &ebus_regs[rnumber];
422 break;
423
424 default:
425 return (DDI_ME_INVAL);
426
427 }
428
429 /* Adjust our reg property with offset and length */
430 ebus_rp->addr_low += off;
431 if (len)
432 ebus_rp->size = len;
433
434 /*
435 * Now we have a copy the "reg" entry we're attempting to map.
436 * Translate this into our parents PCI address using the ranges
437 * property.
438 */
439 rval = acebus_apply_range(ebus_p, rdip, ebus_rp, &pci_reg);
440
441 if (mp->map_type == DDI_MT_RNUMBER)
442 kmem_free((caddr_t)ebus_regs, i);
443
444 if (rval != DDI_SUCCESS)
445 return (rval);
446
447 #ifdef ACEBUS_HOTPLUG
448 /*
449 * The map operation provides a translated (not a re-assigned, or
450 * relocated) ebus address for the child in its address space(range).
451 * Ebus address space is relocatible but its child address space
452 * is not. As specified by their 'reg' properties, they reside
453 * at a fixed offset in their parent's (ebus's) space.
454 *
455 * By setting this bit, we will not run into HostPCI nexus
456 * trying to relocate a translated ebus address (which is already
457 * relocated) and failing the operation.
458 * The reason for doing this here is that the PCI hotplug configurator
459 * always marks the ebus space as relocatible (unlike OBP) and that
460 * information is implied for the child too, which is wrong.
461 */
462 pci_reg.pci_phys_hi |= PCI_RELOCAT_B;
463 #endif
464 #ifdef DEBUG
465 DBG5(D_MAP, ebus_p, "(%x,%x,%x)(%x,%x)\n",
466 pci_reg.pci_phys_hi,
467 pci_reg.pci_phys_mid,
468 pci_reg.pci_phys_low,
469 pci_reg.pci_size_hi,
470 pci_reg.pci_size_low);
471 #endif
472
473 p_map_request = *mp;
474 p_map_request.map_type = DDI_MT_REGSPEC;
475 p_map_request.map_obj.rp = (struct regspec *)&pci_reg;
476 rval = ddi_map(dip, &p_map_request, 0, 0, addrp);
477 DBG1(D_MAP, ebus_p, "parent returned %x\n", rval);
478 return (rval);
479 }
480
481
482 static int
acebus_apply_range(ebus_devstate_t * ebus_p,dev_info_t * rdip,ebus_regspec_t * ebus_rp,pci_regspec_t * rp)483 acebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
484 ebus_regspec_t *ebus_rp, pci_regspec_t *rp)
485 {
486 int b;
487 int rval = DDI_SUCCESS;
488 struct ebus_pci_rangespec *rangep = ebus_p->rangep;
489 int nrange = ebus_p->range_cnt;
490 static const char out_of_range[] =
491 "Out of range register specification from device node <%s>";
492
493 DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n",
494 ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size);
495
496 for (b = 0; b < nrange; ++b, ++rangep) {
497
498 /* Check for the correct space */
499 if (ebus_rp->addr_hi == rangep->ebus_phys_hi)
500 /* See if we fit in this range */
501 if ((ebus_rp->addr_low >=
502 rangep->ebus_phys_low) &&
503 ((ebus_rp->addr_low + ebus_rp->size - 1)
504 <= (rangep->ebus_phys_low +
505 rangep->rng_size - 1))) {
506 uint_t addr_offset = ebus_rp->addr_low -
507 rangep->ebus_phys_low;
508 /*
509 * Use the range entry to translate
510 * the EBUS physical address into the
511 * parents PCI space.
512 */
513 rp->pci_phys_hi =
514 rangep->pci_phys_hi;
515 rp->pci_phys_mid = rangep->pci_phys_mid;
516 rp->pci_phys_low =
517 rangep->pci_phys_low + addr_offset;
518 rp->pci_size_hi = 0;
519 rp->pci_size_low =
520 min(ebus_rp->size, (rangep->rng_size -
521 addr_offset));
522
523 DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ",
524 rangep->ebus_phys_hi,
525 rangep->ebus_phys_low);
526 DBG4(D_MAP, ebus_p, "Parent hi0x%x "
527 "mid0x%x lo0x%x size 0x%x\n",
528 rangep->pci_phys_hi,
529 rangep->pci_phys_mid,
530 rangep->pci_phys_low,
531 rangep->rng_size);
532
533 break;
534 }
535 }
536
537 if (b == nrange) {
538 cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip));
539 return (DDI_ME_REGSPEC_RANGE);
540 }
541
542 return (rval);
543 }
544
545
546 /*
547 * control ops entry point:
548 *
549 * Requests handled completely:
550 * DDI_CTLOPS_INITCHILD
551 * DDI_CTLOPS_UNINITCHILD
552 * DDI_CTLOPS_REPORTDEV
553 * DDI_CTLOPS_REGSIZE
554 * DDI_CTLOPS_NREGS
555 *
556 * All others passed to parent.
557 */
558 static int
acebus_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t op,void * arg,void * result)559 acebus_ctlops(dev_info_t *dip, dev_info_t *rdip,
560 ddi_ctl_enum_t op, void *arg, void *result)
561 {
562 #ifdef DEBUG
563 ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip));
564 #endif
565 ebus_regspec_t *ebus_rp;
566 int32_t reglen;
567 int i, n;
568 char name[10];
569
570 switch (op) {
571 case DDI_CTLOPS_INITCHILD: {
572 dev_info_t *child = (dev_info_t *)arg;
573 /*
574 * Set the address portion of the node name based on the
575 * address/offset.
576 */
577 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n",
578 ddi_get_name(child), ddi_get_instance(child));
579
580 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
581 "reg", (caddr_t)&ebus_rp, ®len) != DDI_SUCCESS) {
582
583 DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
584 return (DDI_FAILURE);
585
586 }
587
588 (void) sprintf(name, "%x,%x", ebus_rp->addr_hi,
589 ebus_rp->addr_low);
590 ddi_set_name_addr(child, name);
591 kmem_free((caddr_t)ebus_rp, reglen);
592
593 ddi_set_parent_data(child, NULL);
594
595 return (DDI_SUCCESS);
596
597 }
598
599 case DDI_CTLOPS_UNINITCHILD:
600 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n",
601 ddi_get_name((dev_info_t *)arg),
602 ddi_get_instance((dev_info_t *)arg));
603 ddi_set_name_addr((dev_info_t *)arg, NULL);
604 ddi_remove_minor_node((dev_info_t *)arg, NULL);
605 impl_rem_dev_props((dev_info_t *)arg);
606 return (DDI_SUCCESS);
607
608 case DDI_CTLOPS_REPORTDEV:
609
610 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n",
611 ddi_get_name(rdip), ddi_get_instance(rdip));
612 cmn_err(CE_CONT, "?%s%d at %s%d: offset %s\n",
613 ddi_driver_name(rdip), ddi_get_instance(rdip),
614 ddi_driver_name(dip), ddi_get_instance(dip),
615 ddi_get_name_addr(rdip));
616 return (DDI_SUCCESS);
617
618 case DDI_CTLOPS_REGSIZE:
619
620 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n",
621 ddi_get_name(rdip), ddi_get_instance(rdip));
622 if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
623 DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
624 return (DDI_FAILURE);
625 }
626 n = i / sizeof (ebus_regspec_t);
627 if (*(int *)arg < 0 || *(int *)arg >= n) {
628 DBG(D_MAP, ebus_p, "rnumber out of range\n");
629 kmem_free((caddr_t)ebus_rp, i);
630 return (DDI_FAILURE);
631 }
632 *((off_t *)result) = ebus_rp[*(int *)arg].size;
633 kmem_free((caddr_t)ebus_rp, i);
634 return (DDI_SUCCESS);
635
636 case DDI_CTLOPS_NREGS:
637
638 DBG2(D_CTLOPS, ebus_p, "DDI_CTLOPS_NREGS: rdip=%s%d\n",
639 ddi_get_name(rdip), ddi_get_instance(rdip));
640 if (getprop(rdip, "reg", &ebus_rp, &i) != DDI_SUCCESS) {
641 DBG(D_CTLOPS, ebus_p, "can't get reg property\n");
642 return (DDI_FAILURE);
643 }
644 *((uint_t *)result) = i / sizeof (ebus_regspec_t);
645 kmem_free((caddr_t)ebus_rp, i);
646 return (DDI_SUCCESS);
647 }
648
649 /*
650 * Now pass the request up to our parent.
651 */
652 DBG2(D_CTLOPS, ebus_p, "passing request to parent: rdip=%s%d\n",
653 ddi_get_name(rdip), ddi_get_instance(rdip));
654 return (ddi_ctlops(dip, rdip, op, arg, result));
655 }
656
657 struct ebus_string_to_pil {
658 int8_t *string;
659 uint32_t pil;
660 };
661
662 static struct ebus_string_to_pil acebus_name_to_pil[] = {{"SUNW,CS4231", 9},
663 {"fdthree", 8},
664 {"ecpp", 3},
665 {"su", 12},
666 {"se", 12},
667 {"power", 14}};
668
669 static struct ebus_string_to_pil acebus_device_type_to_pil[] = {{"serial", 12},
670 {"block", 8}};
671
672 static int
acebus_intr_ops(dev_info_t * dip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)673 acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
674 ddi_intr_handle_impl_t *hdlp, void *result)
675 {
676 #ifdef DEBUG
677 ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip));
678 #endif
679 int8_t *name, *device_type;
680 int32_t i, max_children, max_device_types, len;
681
682 /*
683 * NOTE: These ops below will never be supported in this nexus
684 * driver, hence they always return immediately.
685 */
686 switch (intr_op) {
687 case DDI_INTROP_GETCAP:
688 *(int *)result = DDI_INTR_FLAG_LEVEL;
689 return (DDI_SUCCESS);
690 case DDI_INTROP_SUPPORTED_TYPES:
691 *(int *)result = i_ddi_get_intx_nintrs(rdip) ?
692 DDI_INTR_TYPE_FIXED : 0;
693 return (DDI_SUCCESS);
694 case DDI_INTROP_SETCAP:
695 case DDI_INTROP_SETMASK:
696 case DDI_INTROP_CLRMASK:
697 case DDI_INTROP_GETPENDING:
698 return (DDI_ENOTSUP);
699 default:
700 break;
701 }
702
703 if (hdlp->ih_pri)
704 goto done;
705
706 /*
707 * This is a hack to set the PIL for the devices under ebus.
708 * We first look up a device by it's specific name, if we can't
709 * match the name, we try and match it's device_type property.
710 * Lastly we default a PIL level of 1.
711 */
712 DBG1(D_INTR, ebus_p, "ebus_p %p\n", ebus_p);
713
714 name = ddi_get_name(rdip);
715 max_children = sizeof (acebus_name_to_pil) /
716 sizeof (struct ebus_string_to_pil);
717
718 for (i = 0; i < max_children; i++) {
719 if (strcmp(acebus_name_to_pil[i].string, name) == 0) {
720 DBG2(D_INTR, ebus_p, "child name %s; match PIL %d\n",
721 acebus_name_to_pil[i].string,
722 acebus_name_to_pil[i].pil);
723
724 hdlp->ih_pri = acebus_name_to_pil[i].pil;
725 goto done;
726 }
727 }
728
729 if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
730 "device_type", (caddr_t)&device_type, &len) == DDI_SUCCESS) {
731
732 max_device_types = sizeof (acebus_device_type_to_pil) /
733 sizeof (struct ebus_string_to_pil);
734
735 for (i = 0; i < max_device_types; i++) {
736 if (strcmp(acebus_device_type_to_pil[i].string,
737 device_type) == 0) {
738 DBG2(D_INTR, ebus_p,
739 "Device type %s; match PIL %d\n",
740 acebus_device_type_to_pil[i].string,
741 acebus_device_type_to_pil[i].pil);
742
743 hdlp->ih_pri = acebus_device_type_to_pil[i].pil;
744 break;
745 }
746 }
747
748 kmem_free(device_type, len);
749 }
750
751 /*
752 * If we get here, we need to set a default value
753 * for the PIL.
754 */
755 if (hdlp->ih_pri == 0) {
756 hdlp->ih_pri = 1;
757 cmn_err(CE_WARN, "%s%d assigning default interrupt level %d "
758 "for device %s%d", ddi_driver_name(dip),
759 ddi_get_instance(dip), hdlp->ih_pri, ddi_driver_name(rdip),
760 ddi_get_instance(rdip));
761 }
762
763 done:
764 /* Pass up the request to our parent. */
765 return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result));
766 }
767
768
769 static int
acebus_config(ebus_devstate_t * ebus_p)770 acebus_config(ebus_devstate_t *ebus_p)
771 {
772 ddi_acc_handle_t conf_handle;
773 uint16_t comm;
774 #ifdef ACEBUS_HOTPLUG
775 int tcr_reg;
776 caddr_t csr_io;
777 ddi_device_acc_attr_t csr_attr = { /* CSR map attributes */
778 DDI_DEVICE_ATTR_V0,
779 DDI_STRUCTURE_LE_ACC,
780 DDI_STRICTORDER_ACC
781 };
782 ddi_acc_handle_t csr_handle;
783 #endif
784
785 /*
786 * Make sure the master enable and memory access enable
787 * bits are set in the config command register.
788 */
789 if (pci_config_setup(ebus_p->dip, &conf_handle) != DDI_SUCCESS)
790 return (0);
791
792 comm = pci_config_get16(conf_handle, PCI_CONF_COMM),
793 #ifdef DEBUG
794 DBG1(D_ATTACH, ebus_p, "command register was 0x%x\n", comm);
795 #endif
796 comm |= (PCI_COMM_ME|PCI_COMM_MAE|PCI_COMM_SERR_ENABLE|
797 PCI_COMM_PARITY_DETECT);
798 pci_config_put16(conf_handle, PCI_CONF_COMM, comm),
799 #ifdef DEBUG
800 DBG1(D_MAP, ebus_p, "command register is now 0x%x\n",
801 pci_config_get16(conf_handle, PCI_CONF_COMM));
802 #endif
803 pci_config_put8(conf_handle, PCI_CONF_CACHE_LINESZ,
804 (uchar_t)acebus_cache_line_size);
805 pci_config_put8(conf_handle, PCI_CONF_LATENCY_TIMER,
806 (uchar_t)acebus_latency_timer);
807 pci_config_teardown(&conf_handle);
808
809 #ifdef ACEBUS_HOTPLUG
810 if (acebus_update_props(ebus_p) != DDI_SUCCESS) {
811 cmn_err(CE_WARN, "%s%d: Could not update special properties.",
812 ddi_driver_name(ebus_p->dip),
813 ddi_get_instance(ebus_p->dip));
814 return (0);
815 }
816
817 if (ddi_regs_map_setup(ebus_p->dip, CSR_IO_RINDEX,
818 (caddr_t *)&csr_io, 0, CSR_SIZE, &csr_attr,
819 &csr_handle) != DDI_SUCCESS) {
820 cmn_err(CE_WARN, "%s%d: Could not map Ebus CSR.",
821 ddi_driver_name(ebus_p->dip),
822 ddi_get_instance(ebus_p->dip));
823 }
824 #ifdef DEBUG
825 if (acebus_debug_flags) {
826 DBG3(D_ATTACH, ebus_p, "tcr[123] = %x,%x,%x\n",
827 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
828 TCR1_OFF)),
829 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
830 TCR2_OFF)),
831 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
832 TCR3_OFF)));
833 DBG2(D_ATTACH, ebus_p, "pmd-aux=%x, freq-aux=%x\n",
834 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
835 PMD_AUX_OFF)),
836 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
837 FREQ_AUX_OFF)));
838 #ifdef ACEBUS_DEBUG
839 for (comm = 0; comm < 4; comm++)
840 prom_printf("dcsr%d=%x, dacr%d=%x, dbcr%d=%x\n", comm,
841 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
842 0x700000+(0x2000*comm))), comm,
843 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
844 0x700000+(0x2000*comm)+4)), comm,
845 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
846 0x700000+(0x2000*comm)+8)));
847 #endif
848 } /* acebus_debug_flags */
849 #endif
850 /* If TCR registers are not initialized, initialize them here */
851 tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
852 TCR1_OFF));
853 if ((tcr_reg == 0) || (tcr_reg == -1))
854 ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF),
855 TCR1_REGVAL);
856 tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
857 TCR2_OFF));
858 if ((tcr_reg == 0) || (tcr_reg == -1))
859 ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF),
860 TCR2_REGVAL);
861 tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
862 TCR3_OFF));
863 if ((tcr_reg == 0) || (tcr_reg == -1))
864 ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF),
865 TCR3_REGVAL);
866 #ifdef DEBUG
867 if (acebus_debug_flags) {
868 DBG3(D_ATTACH, ebus_p, "wrote tcr[123] = %x,%x,%x\n",
869 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
870 TCR1_OFF)),
871 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
872 TCR2_OFF)),
873 ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io +
874 TCR3_OFF)));
875 }
876 #endif
877
878 ddi_regs_map_free(&csr_handle);
879 #endif /* ACEBUS_HOTPLUG */
880 return (1); /* return success */
881 }
882
883 #ifdef DEBUG
884 extern void prom_printf(const char *, ...);
885
886 static void
acebus_debug(uint_t flag,ebus_devstate_t * ebus_p,char * fmt,uintptr_t a1,uintptr_t a2,uintptr_t a3,uintptr_t a4,uintptr_t a5)887 acebus_debug(uint_t flag, ebus_devstate_t *ebus_p, char *fmt,
888 uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
889 {
890 char *s;
891
892 if (acebus_debug_flags & flag) {
893 switch (flag) {
894 case D_ATTACH:
895 s = "attach"; break;
896 case D_DETACH:
897 s = "detach"; break;
898 case D_MAP:
899 s = "map"; break;
900 case D_CTLOPS:
901 s = "ctlops"; break;
902 case D_INTR:
903 s = "intr"; break;
904 }
905 if (ebus_p)
906 cmn_err(CE_CONT, "%s%d: %s: ",
907 ddi_get_name(ebus_p->dip),
908 ddi_get_instance(ebus_p->dip), s);
909 else
910 cmn_err(CE_CONT, "ebus: ");
911 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
912 }
913 }
914 #endif
915
916 #ifdef ACEBUS_HOTPLUG
917 #define EBUS_CHILD_PHYS_LOW_RANGE 0x10
918 #define EBUS_CHILD_PHYS_HI_RANGE 0x14
919
920 static int
acebus_update_props(ebus_devstate_t * ebus_p)921 acebus_update_props(ebus_devstate_t *ebus_p)
922 {
923 dev_info_t *dip = ebus_p->dip;
924 struct ebus_pci_rangespec er[2], *erp;
925 pci_regspec_t *pci_rp, *prp;
926 int length, rnums, imask[3], i, found = 0;
927
928 /*
929 * If "ranges" property is found, then the device is initialized
930 * by OBP, hence simply return.
931 * Otherwise we create all the properties here.
932 */
933 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
934 "ranges", (int **)&erp, (uint_t *)&length) == DDI_PROP_SUCCESS) {
935 ddi_prop_free(erp);
936 return (DDI_SUCCESS);
937 }
938
939 /*
940 * interrupt-map is the only property that comes from a .conf file.
941 * Since it doesn't have the nodeid field set, it must be done here.
942 * Other properties can come from OBP or created here.
943 */
944 if (acebus_set_imap(dip) != DDI_SUCCESS) {
945 return (DDI_FAILURE);
946 }
947
948 /*
949 * Create the "ranges" property.
950 * Ebus has BAR0 and BAR1 allocated (both in memory space).
951 * Other BARs are 0.
952 * Hence there are 2 memory ranges it operates in. (one for each BAR).
953 * ie. there are 2 entries in its ranges property.
954 */
955 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
956 DDI_PROP_DONTPASS, "assigned-addresses",
957 (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) {
958 cmn_err(CE_WARN, "%s%d: Could not get assigned-addresses",
959 ddi_driver_name(dip), ddi_get_instance(dip));
960 return (DDI_FAILURE);
961 }
962 /*
963 * Create the 1st mem range in which it operates corresponding
964 * to BAR0
965 */
966 er[0].ebus_phys_hi = EBUS_CHILD_PHYS_LOW_RANGE;
967 rnums = (length * sizeof (int))/sizeof (pci_regspec_t);
968 for (i = 0; i < rnums; i++) {
969 prp = pci_rp + i;
970 if (PCI_REG_REG_G(prp->pci_phys_hi) == er[0].ebus_phys_hi) {
971 found = 1;
972 break;
973 }
974 }
975 if (!found) {
976 cmn_err(CE_WARN, "No assigned space for memory range 0.");
977 ddi_prop_free(pci_rp);
978 return (DDI_FAILURE);
979 }
980 found = 0;
981 er[0].ebus_phys_low = 0;
982 er[0].pci_phys_hi = prp->pci_phys_hi;
983 er[0].pci_phys_mid = prp->pci_phys_mid;
984 er[0].pci_phys_low = prp->pci_phys_low;
985 er[0].rng_size = prp->pci_size_low;
986
987 /*
988 * Create the 2nd mem range in which it operates corresponding
989 * to BAR1
990 */
991 er[1].ebus_phys_hi = EBUS_CHILD_PHYS_HI_RANGE;
992 for (i = 0; i < rnums; i++) {
993 prp = pci_rp + i;
994 if (PCI_REG_REG_G(prp->pci_phys_hi) == er[1].ebus_phys_hi) {
995 found = 1;
996 break;
997 }
998 }
999 if (!found) {
1000 cmn_err(CE_WARN, "No assigned space for memory range 1.");
1001 ddi_prop_free(pci_rp);
1002 return (DDI_FAILURE);
1003 }
1004 er[1].ebus_phys_low = 0;
1005 er[1].pci_phys_hi = prp->pci_phys_hi;
1006 er[1].pci_phys_mid = prp->pci_phys_mid;
1007 er[1].pci_phys_low = prp->pci_phys_low;
1008 er[1].rng_size = prp->pci_size_low;
1009
1010 ddi_prop_free(pci_rp);
1011 length = sizeof (er) / sizeof (int);
1012 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1013 "ranges", (int *)er, length) != DDI_PROP_SUCCESS) {
1014 cmn_err(CE_WARN, "%s%d: Could not create ranges property",
1015 ddi_driver_name(dip), ddi_get_instance(dip));
1016 return (DDI_FAILURE);
1017 }
1018 /* The following properties are as defined by PCI 1275 bindings. */
1019 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
1020 "#address-cells", 2) != DDI_PROP_SUCCESS)
1021 return (DDI_FAILURE);
1022 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
1023 "#size-cells", 1) != DDI_PROP_SUCCESS)
1024 return (DDI_FAILURE);
1025 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
1026 "#interrupt-cells", 1) != DDI_PROP_SUCCESS)
1027 return (DDI_FAILURE);
1028
1029 imask[0] = 0x1f;
1030 imask[1] = 0x00ffffff;
1031 imask[2] = 0x00000003;
1032 length = sizeof (imask) / sizeof (int);
1033 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1034 "interrupt-map-mask", (int *)imask, length) != DDI_PROP_SUCCESS) {
1035 cmn_err(CE_WARN, "%s%d: Could not update imap mask property",
1036 ddi_driver_name(dip), ddi_get_instance(dip));
1037 return (DDI_FAILURE);
1038 }
1039
1040 return (DDI_SUCCESS);
1041 }
1042
1043 /*
1044 * This function takes in the ac-interrupt-map property from the .conf file,
1045 * fills in the 'nodeid' information and then creates the 'interrupt-map'
1046 * property.
1047 */
1048 static int
acebus_set_imap(dev_info_t * dip)1049 acebus_set_imap(dev_info_t *dip)
1050 {
1051 int *imapp, *timapp, length, num, i, default_ival = 0;
1052 dev_info_t *tdip = dip;
1053 int *port_id, imap_ok = 1;
1054 int ilength;
1055 int acebus_default_se_imap[5];
1056
1057 /*
1058 * interrupt-map is specified via .conf file in hotplug mode,
1059 * since the child configuration is static.
1060 * It could even be hardcoded in the driver.
1061 */
1062 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1063 "ac-interrupt-map", (int **)&imapp, (uint_t *)&ilength) !=
1064 DDI_PROP_SUCCESS) {
1065 /* assume default implementation */
1066 acebus_default_se_imap[0] = 0x14;
1067 acebus_default_se_imap[1] = 0x400000;
1068 acebus_default_se_imap[2] = 1;
1069 acebus_default_se_imap[3] = 0;
1070 acebus_default_se_imap[4] = 2;
1071 imapp = acebus_default_se_imap;
1072 ilength = 5;
1073 default_ival = 1;
1074 }
1075 num = ilength / 5; /* there are 5 integer cells in our property */
1076 timapp = imapp;
1077 for (i = 0; i < num; i++) {
1078 if (*(timapp+i*5+3) == 0)
1079 imap_ok = 0;
1080 }
1081 if (imap_ok) {
1082 if (!default_ival)
1083 ddi_prop_free(imapp);
1084 return (DDI_SUCCESS);
1085 }
1086
1087 while (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, tdip,
1088 DDI_PROP_DONTPASS, "upa-portid", (int **)&port_id,
1089 (uint_t *)&length) != DDI_PROP_SUCCESS) {
1090 tdip = ddi_get_parent(tdip);
1091 if (tdip == NULL) {
1092 cmn_err(CE_WARN, "%s%d: Could not get imap parent",
1093 ddi_driver_name(dip), ddi_get_instance(dip));
1094 if (!default_ival)
1095 ddi_prop_free(imapp);
1096 return (DDI_FAILURE);
1097 }
1098 }
1099 timapp = imapp;
1100 for (i = 0; i < num; i++) {
1101 *(timapp+i*5+3) = ddi_get_nodeid(tdip);
1102 }
1103
1104 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
1105 "interrupt-map", imapp, ilength) != DDI_PROP_SUCCESS) {
1106 cmn_err(CE_WARN, "%s%d: Could not update AC imap property",
1107 ddi_driver_name(dip), ddi_get_instance(dip));
1108 if (!default_ival)
1109 ddi_prop_free(imapp);
1110 return (DDI_FAILURE);
1111 }
1112 if (!default_ival)
1113 ddi_prop_free(imapp);
1114 return (DDI_SUCCESS);
1115 }
1116 #endif /* ACEBUS_HOTPLUG */
1117