]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/dev/siba/siba.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / sys / dev / siba / siba.c
1 /*-
2  * Copyright (c) 2007 Bruce M. Simpson.
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  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/rman.h>
36 #include <sys/malloc.h>
37
38 #include <machine/bus.h>
39
40 #include <dev/siba/sibavar.h>
41 #include <dev/siba/sibareg.h>
42 #include <dev/siba/siba_ids.h>
43
44 /*
45  * TODO: De-mipsify this code.
46  * TODO: cpu clock calculation. -> move to siba_cc instance
47  * TODO: Hardwire IRQs for attached cores on siba at probe time.
48  * TODO: Support detach.
49  * TODO: Power management.
50  * TODO: code cleanup.
51  * TODO: Support deployments of siba other than as a system bus.
52  */
53
54 #ifndef MIPS_MEM_RID
55 #define MIPS_MEM_RID 0x20
56 #endif
57
58 extern int rman_debug;
59
60 static struct rman mem_rman;    /* XXX move to softc */
61
62 static int siba_debug = 1;
63 static const char descfmt[] = "Sonics SiliconBackplane rev %s";
64 #define SIBA_DEVDESCLEN sizeof(descfmt) + 8
65
66 /*
67  * Device identifiers and descriptions.
68  */
69 static struct siba_devid siba_devids[] = {
70         { SIBA_VID_BROADCOM,    SIBA_DEVID_CHIPCOMMON,  SIBA_REV_ANY,
71           "ChipCommon" },
72         { SIBA_VID_BROADCOM,    SIBA_DEVID_SDRAM,       SIBA_REV_ANY,
73           "SDRAM controller" },
74         { SIBA_VID_BROADCOM,    SIBA_DEVID_PCI,         SIBA_REV_ANY,
75           "PCI host interface" },
76         { SIBA_VID_BROADCOM,    SIBA_DEVID_MIPS,        SIBA_REV_ANY,
77           "MIPS core" },
78         { SIBA_VID_BROADCOM,    SIBA_DEVID_ETHERNET,    SIBA_REV_ANY,
79           "Ethernet core" },
80         { SIBA_VID_BROADCOM,    SIBA_DEVID_USB,         SIBA_REV_ANY,
81           "USB host controller" },
82         { SIBA_VID_BROADCOM,    SIBA_DEVID_IPSEC,       SIBA_REV_ANY,
83           "IPSEC accelerator" },
84         { SIBA_VID_BROADCOM,    SIBA_DEVID_SDRAMDDR,    SIBA_REV_ANY,
85           "SDRAM/DDR controller" },
86         { SIBA_VID_BROADCOM,    SIBA_DEVID_MIPS_3302,   SIBA_REV_ANY,
87           "MIPS 3302 core" },
88         { 0, 0, 0, NULL }
89 };
90
91 static int      siba_activate_resource(device_t, device_t, int, int,
92                     struct resource *);
93 static device_t siba_add_child(device_t, int, const char *, int);
94 static struct resource *
95                 siba_alloc_resource(device_t, device_t, int, int *, u_long,
96                     u_long, u_long, u_int);
97 static int      siba_attach(device_t);
98 #ifdef notyet
99 static void     siba_destroy_devinfo(struct siba_devinfo *);
100 #endif
101 static struct siba_devid *
102                 siba_dev_match(uint16_t, uint16_t, uint8_t);
103 static struct resource_list *
104                 siba_get_reslist(device_t, device_t);
105 static uint8_t  siba_getirq(uint16_t);
106 static uint8_t  siba_getncores(uint16_t);
107 static int      siba_print_all_resources(device_t dev);
108 static int      siba_print_child(device_t, device_t);
109 static int      siba_probe(device_t);
110 static void     siba_probe_nomatch(device_t, device_t);
111 int             siba_read_ivar(device_t, device_t, int, uintptr_t *);
112 static struct siba_devinfo *
113                 siba_setup_devinfo(device_t, uint8_t);
114 int             siba_write_ivar(device_t, device_t, int, uintptr_t);
115
116 /*
117  * Earlier ChipCommon revisions have hardcoded number of cores
118  * present dependent on the ChipCommon ID.
119  */
120 static uint8_t
121 siba_getncores(uint16_t ccid)
122 {
123         uint8_t ncores;
124
125         switch (ccid) {
126         case SIBA_CCID_SENTRY5:
127                 ncores = 7;
128                 break;
129         case SIBA_CCID_BCM4710:
130         case SIBA_CCID_BCM4704:
131                 ncores = 9;
132                 break;
133         default:
134                 ncores = 0;
135         }
136
137         return (ncores);
138 }
139
140 /*
141  * On the Sentry5, the system bus IRQs are the same as the
142  * MIPS IRQs. Particular cores are hardwired to certain IRQ lines.
143  */
144 static uint8_t
145 siba_getirq(uint16_t devid)
146 {
147         uint8_t irq;
148
149         switch (devid) {
150         case SIBA_DEVID_CHIPCOMMON:
151                 irq = 0;
152                 break;
153         case SIBA_DEVID_ETHERNET:
154                 irq = 1;
155                 break;
156         case SIBA_DEVID_IPSEC:
157                 irq = 2;
158                 break;
159         case SIBA_DEVID_USB:
160                 irq = 3;
161                 break;
162         case SIBA_DEVID_PCI:
163                 irq = 4;
164                 break;
165 #if 0
166         /*
167          * 5 is reserved for the MIPS on-chip timer interrupt;
168          * it is hard-wired by the tick driver.
169          */
170         case SIBA_DEVID_MIPS:
171         case SIBA_DEVID_MIPS_3302:
172                 irq = 5;
173                 break;
174 #endif
175         default:
176                 irq = 0xFF;     /* this core does not need an irq */
177                 break;
178         }
179
180         return (irq);
181 }
182
183 static int
184 siba_probe(device_t dev)
185 {
186         struct siba_softc *sc = device_get_softc(dev);
187         uint32_t idlo, idhi;
188         uint16_t ccid;
189         int rid;
190
191         sc->sc_dev = dev;
192
193         //rman_debug = 1;       /* XXX */
194
195         /*
196          * Map the ChipCommon register set using the hints the kernel
197          * was compiled with.
198          */
199         rid = MIPS_MEM_RID;
200         sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
201             RF_ACTIVE);
202         if (sc->sc_mem == NULL) {
203                 device_printf(dev, "unable to allocate probe aperture\n");
204                 return (ENXIO);
205         }
206         sc->sc_bt = rman_get_bustag(sc->sc_mem);
207         sc->sc_bh = rman_get_bushandle(sc->sc_mem);
208         sc->sc_maddr = rman_get_start(sc->sc_mem);
209         sc->sc_msize = rman_get_size(sc->sc_mem);
210
211         if (siba_debug) {
212                 device_printf(dev, "start %08x len %08x\n",
213                     sc->sc_maddr, sc->sc_msize);
214         }
215
216         idlo = siba_read_4(sc, 0, SIBA_CORE_IDLO);
217         idhi = siba_read_4(sc, 0, SIBA_CORE_IDHI);
218         ccid = ((idhi & 0x8ff0) >> 4);
219         if (siba_debug) {
220                 device_printf(dev, "idlo = %08x\n", idlo);
221                 device_printf(dev, "idhi = %08x\n", idhi);
222                 device_printf(dev, " chipcore id = %08x\n", ccid);
223         }
224
225         /*
226          * For now, check that the first core is the ChipCommon core.
227          */
228         if (ccid != SIBA_DEVID_CHIPCOMMON) {
229                 if (siba_debug)
230                         device_printf(dev, "first core is not ChipCommon\n");
231                 return (ENXIO);
232         }
233
234         /*
235          * Determine backplane revision and set description string.
236          */
237         uint32_t rev;
238         char *revp;
239         char descbuf[SIBA_DEVDESCLEN];
240
241         rev = idlo & 0xF0000000;
242         revp = "unknown";
243         if (rev == 0x00000000)
244                 revp = "2.2";
245         else if (rev == 0x10000000)
246                 revp = "2.3";
247
248         (void)snprintf(descbuf, sizeof(descbuf), descfmt, revp);
249         device_set_desc_copy(dev, descbuf);
250
251         /*
252          * Determine how many cores are present on this siba bus, so
253          * that we may map them all.
254          */
255         uint32_t ccidreg;
256         uint16_t cc_id;
257         uint16_t cc_rev;
258
259         ccidreg = siba_read_4(sc, 0, SIBA_CC_CCID);
260         cc_id = (ccidreg & SIBA_CC_IDMASK);
261         cc_rev = (ccidreg & SIBA_CC_REVMASK) >> SIBA_CC_REVSHIFT;
262         if (siba_debug) {
263                 device_printf(dev, "ccid = %08x, cc_id = %04x, cc_rev = %04x\n",
264                      ccidreg, cc_id, cc_rev);
265         }
266
267         sc->sc_ncores = siba_getncores(cc_id);
268         if (siba_debug) {
269                 device_printf(dev, "%d cores detected.\n", sc->sc_ncores);
270         }
271
272         /*
273          * Now we know how many cores are on this siba, release the
274          * mapping and allocate a new mapping spanning all cores on the bus.
275          */
276         rid = MIPS_MEM_RID;
277         int result;
278         result = bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_mem);
279         if (result != 0) {
280                 device_printf(dev, "error %d releasing resource\n", result);
281                 return (ENXIO);
282         }
283
284         uint32_t total;
285         total = sc->sc_ncores * SIBA_CORE_LEN;
286
287         /* XXX Don't allocate the entire window until we
288          * enumerate the bus. Once the bus has been enumerated,
289          * and instance variables/children instantiated + populated,
290          * release the resource so children may attach.
291          */
292         sc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
293             sc->sc_maddr, sc->sc_maddr + total - 1, total, RF_ACTIVE);
294         if (sc->sc_mem == NULL) {
295                 device_printf(dev, "unable to allocate entire aperture\n");
296                 return (ENXIO);
297         }
298         sc->sc_bt = rman_get_bustag(sc->sc_mem);
299         sc->sc_bh = rman_get_bushandle(sc->sc_mem);
300         sc->sc_maddr = rman_get_start(sc->sc_mem);
301         sc->sc_msize = rman_get_size(sc->sc_mem);
302
303         if (siba_debug) {
304                 device_printf(dev, "after remapping: start %08x len %08x\n",
305                     sc->sc_maddr, sc->sc_msize);
306         }
307         bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->sc_maddr, sc->sc_msize);
308
309         /*
310          * We need a manager for the space we claim on nexus to
311          * satisfy requests from children.
312          * We need to keep the source reservation we took because
313          * otherwise it may be claimed elsewhere.
314          * XXX move to softc
315          */
316         mem_rman.rm_start = sc->sc_maddr;
317         mem_rman.rm_end = sc->sc_maddr + sc->sc_msize - 1;
318         mem_rman.rm_type = RMAN_ARRAY;
319         mem_rman.rm_descr = "SiBa I/O memory addresses";
320         if (rman_init(&mem_rman) != 0 ||
321             rman_manage_region(&mem_rman, mem_rman.rm_start, mem_rman.rm_end) != 0) {
322                 panic("%s: mem_rman", __func__);
323         }
324
325         return (0);
326 }
327
328 static int
329 siba_attach(device_t dev)
330 {
331         struct siba_softc       *sc = device_get_softc(dev);
332         struct siba_devinfo     *sdi;
333         device_t                 child;
334         int                      idx;
335
336         if (siba_debug)
337                 printf("%s: entry\n", __func__);
338
339         bus_generic_probe(dev);
340
341         /*
342          * Now that all bus space is mapped and visible to the CPU,
343          * enumerate its children.
344          * NB: only one core may be mapped at any time if the siba bus
345          * is the child of a PCI or PCMCIA bus.
346          */
347         for (idx = 0; idx < sc->sc_ncores; idx++) {
348                 sdi = siba_setup_devinfo(dev, idx);
349                 child = device_add_child(dev, NULL, -1);
350                 if (child == NULL)
351                         panic("%s: device_add_child() failed\n", __func__);
352                 device_set_ivars(child, sdi);
353         }
354
355         return (bus_generic_attach(dev));
356 }
357
358 static struct siba_devid *
359 siba_dev_match(uint16_t vid, uint16_t devid, uint8_t rev)
360 {
361         size_t                   i, bound;
362         struct siba_devid       *sd;
363
364         bound = sizeof(siba_devids) / sizeof(struct siba_devid);
365         sd = &siba_devids[0];
366         for (i = 0; i < bound; i++, sd++) {
367                 if (((vid == SIBA_VID_ANY) || (vid == sd->sd_vendor)) &&
368                     ((devid == SIBA_DEVID_ANY) || (devid == sd->sd_device)) &&
369                     ((rev == SIBA_REV_ANY) || (rev == sd->sd_rev) ||
370                      (sd->sd_rev == SIBA_REV_ANY)))
371                         break;
372         }
373         if (i == bound)
374                 sd = NULL;
375
376         return (sd);
377 }
378
379 static int
380 siba_print_child(device_t bus, device_t child)
381 {
382         int retval = 0;
383
384         retval += bus_print_child_header(bus, child);
385         retval += siba_print_all_resources(child);
386         if (device_get_flags(child))
387                 retval += printf(" flags %#x", device_get_flags(child));
388         retval += printf(" on %s\n", device_get_nameunit(bus));
389
390         return (retval);
391 }
392
393 static struct resource *
394 siba_alloc_resource(device_t bus, device_t child, int type, int *rid,
395     u_long start, u_long end, u_long count, u_int flags)
396 {
397         struct resource                 *rv;
398         struct resource_list            *rl;
399         struct resource_list_entry      *rle;
400         int                              isdefault, needactivate;
401
402 #if 0
403         if (siba_debug)
404                 printf("%s: entry\n", __func__);
405 #endif
406
407         isdefault = (start == 0UL && end == ~0UL && count == 1);
408         needactivate = flags & RF_ACTIVE;
409         rl = BUS_GET_RESOURCE_LIST(bus, child);
410         rle = NULL;
411
412         if (isdefault) {
413                 rle = resource_list_find(rl, type, *rid);
414                 if (rle == NULL)
415                         return (NULL);
416                 if (rle->res != NULL)
417                         panic("%s: resource entry is busy", __func__);
418                 start = rle->start;
419                 end = rle->end;
420                 count = rle->count;
421         }
422
423         /*
424          * If the request is for a resource which we manage,
425          * attempt to satisfy the allocation ourselves.
426          */
427         if (type == SYS_RES_MEMORY &&
428             start >= mem_rman.rm_start && end <= mem_rman.rm_end) {
429
430                 rv = rman_reserve_resource(&mem_rman, start, end, count,
431                     flags, child);
432                 if (rv == 0) {
433                         printf("%s: could not reserve resource\n", __func__);
434                         return (0);
435                 }
436
437                 rman_set_rid(rv, *rid);
438
439                 if (needactivate) {
440                         if (bus_activate_resource(child, type, *rid, rv)) {
441                                 printf("%s: could not activate resource\n",
442                                     __func__);
443                                 rman_release_resource(rv);
444                                 return (0);
445                         }
446                 }
447
448                 return (rv);
449         }
450
451         /*
452          * Pass the request to the parent, usually MIPS nexus.
453          */
454         if (siba_debug)
455                 printf("%s: proxying request to parent\n", __func__);
456         return (resource_list_alloc(rl, bus, child, type, rid,
457             start, end, count, flags));
458 }
459
460 /*
461  * The parent bus is responsible for resource activation; in the
462  * case of MIPS, this boils down to setting the virtual address and
463  * bus handle by mapping the physical address into KSEG1.
464  */
465 static int
466 siba_activate_resource(device_t bus, device_t child, int type, int rid,
467     struct resource *r)
468 {
469
470         return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child, type,
471             rid, r));
472 }
473
474 static struct siba_devinfo *
475 siba_setup_devinfo(device_t dev, uint8_t idx)
476 {
477         struct siba_softc *sc = device_get_softc(dev);
478         struct siba_devinfo *sdi;
479         uint32_t idlo, idhi, rev;
480         uint16_t vendorid, devid;
481         bus_addr_t baseaddr;
482
483         sdi = malloc(sizeof(*sdi), M_DEVBUF, M_WAITOK | M_ZERO);
484         resource_list_init(&sdi->sdi_rl);
485
486         idlo = siba_read_4(sc, idx, SIBA_CORE_IDLO);
487         idhi = siba_read_4(sc, idx, SIBA_CORE_IDHI);
488
489         vendorid = (idhi & SIBA_IDHIGH_VC) >> SIBA_IDHIGH_VC_SHIFT;
490         devid = ((idhi & 0x8ff0) >> 4);
491         rev = (idhi & SIBA_IDHIGH_RCLO);
492         rev |= (idhi & SIBA_IDHIGH_RCHI) >> SIBA_IDHIGH_RCHI_SHIFT;
493
494         sdi->sdi_vid = vendorid;
495         sdi->sdi_devid = devid;
496         sdi->sdi_rev = rev;
497         sdi->sdi_idx = idx;
498         sdi->sdi_irq = siba_getirq(devid);
499
500         /*
501          * Determine memory window on bus and irq if one is needed.
502          */
503         baseaddr = sc->sc_maddr + (idx * SIBA_CORE_LEN);
504         resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY,
505             MIPS_MEM_RID, /* XXX */
506             baseaddr, baseaddr + SIBA_CORE_LEN - 1, SIBA_CORE_LEN);
507
508         if (sdi->sdi_irq != 0xff) {
509                 resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ,
510                     0, sdi->sdi_irq, sdi->sdi_irq, 1);
511         }
512
513         return (sdi);
514 }
515
516 #ifdef notyet
517 static void
518 siba_destroy_devinfo(struct siba_devinfo *sdi)
519 {
520
521         resource_list_free(&sdi->sdi_rl);
522         free(sdi, M_DEVBUF);
523 }
524 #endif
525
526 /* XXX is this needed? */
527 static device_t
528 siba_add_child(device_t dev, int order, const char *name, int unit)
529 {
530 #if 1
531
532         device_printf(dev, "%s: entry\n", __func__);
533         return (NULL);
534 #else
535         device_t child;
536         struct siba_devinfo *sdi;
537
538         child = device_add_child_ordered(dev, order, name, unit);
539         if (child == NULL)
540                 return (NULL);
541
542         sdi = malloc(sizeof(struct siba_devinfo), M_DEVBUF, M_NOWAIT|M_ZERO);
543         if (sdi == NULL)
544                 return (NULL);
545
546         device_set_ivars(child, sdi);
547         return (child);
548 #endif
549 }
550
551 int
552 siba_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
553 {
554         struct siba_devinfo *sdi;
555
556         sdi = device_get_ivars(child);
557
558         switch (which) {
559         case SIBA_IVAR_VENDOR:
560                 *result = sdi->sdi_vid;
561                 break;
562         case SIBA_IVAR_DEVICE:
563                 *result = sdi->sdi_devid;
564                 break;
565         case SIBA_IVAR_REVID:
566                 *result = sdi->sdi_rev;
567                 break;
568         case SIBA_IVAR_CORE_INDEX:
569                 *result = sdi->sdi_idx;
570                 break;
571         default:
572                 return (ENOENT);
573         }
574
575         return (0);
576 }
577
578 int
579 siba_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
580 {
581
582         return (EINVAL);
583 }
584
585 static void
586 siba_probe_nomatch(device_t dev, device_t child)
587 {
588
589         /*
590          * Announce devices which weren't attached after we probed the bus.
591          */
592         if (siba_debug) {
593                 struct siba_devid *sd;
594
595                 sd = siba_dev_match(siba_get_vendor(child),
596                     siba_get_device(child), SIBA_REV_ANY);
597                 if (sd != NULL && sd->sd_desc != NULL) {
598                         device_printf(dev, "<%s> "
599                             "at device %d (no driver attached)\n",
600                             sd->sd_desc, siba_get_core_index(child));
601                 } else {
602                         device_printf(dev, "<0x%04x, 0x%04x> "
603                             "at device %d (no driver attached)\n",
604                             siba_get_vendor(child), siba_get_device(child),
605                             siba_get_core_index(child));
606                 }
607         }
608 }
609
610 static int
611 siba_print_all_resources(device_t dev)
612 {
613         struct siba_devinfo *sdi = device_get_ivars(dev);
614         struct resource_list *rl = &sdi->sdi_rl;
615         int retval = 0;
616
617         if (STAILQ_FIRST(rl))
618                 retval += printf(" at");
619
620         retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
621         retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
622
623         return (retval);
624 }
625
626 static struct resource_list *
627 siba_get_reslist(device_t dev, device_t child)
628 {
629         struct siba_devinfo *sdi = device_get_ivars(child);
630
631         return (&sdi->sdi_rl);
632 }
633
634 static device_method_t siba_methods[] = {
635         /* Device interface */
636         DEVMETHOD(device_attach,        siba_attach),
637         DEVMETHOD(device_detach,        bus_generic_detach),
638         DEVMETHOD(device_probe,         siba_probe),
639         DEVMETHOD(device_resume,        bus_generic_resume),
640         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
641         DEVMETHOD(device_suspend,       bus_generic_suspend),
642
643         /* Bus interface */
644         DEVMETHOD(bus_activate_resource,siba_activate_resource),
645         DEVMETHOD(bus_add_child,        siba_add_child),
646         DEVMETHOD(bus_alloc_resource,   siba_alloc_resource),
647         DEVMETHOD(bus_get_resource_list,siba_get_reslist),
648         DEVMETHOD(bus_print_child,      siba_print_child),
649         DEVMETHOD(bus_probe_nomatch,    siba_probe_nomatch),
650         DEVMETHOD(bus_read_ivar,        siba_read_ivar),
651         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
652         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
653         DEVMETHOD(bus_write_ivar,       siba_write_ivar),
654
655         {0, 0},
656 };
657
658 static driver_t siba_driver = {
659         "siba",
660         siba_methods,
661         sizeof(struct siba_softc),
662 };
663 static devclass_t siba_devclass;
664
665 DRIVER_MODULE(siba, nexus, siba_driver, siba_devclass, 0, 0);