FreeBSD/Linux Kernel Cross Reference
sys/pccard/mecia.c
1 /*
2 * NEC MECIA controller.
3 *-------------------------------------------------------------------------
4 */
5 /*-
6 * Copyright (c) 2001 M. Warner Losh. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
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 * $FreeBSD: src/sys/pccard/mecia.c,v 1.5.2.1 2005/01/31 23:26:49 imp Exp $
29 *
30 * Based heavily on the FreeBSD pcic driver's pcic98 support, derived
31 * from PAO3 tree. This copyright notice likely needs modification for
32 * such a linage. The only authorship I could find was:
33 *
34 * PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L.
35 * by Noriyuki Hosobuchi <hoso@ce.mbn.or.jp>
36 */
37
38 #include <sys/param.h>
39 #include <sys/bus.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43
44 #include <pccard/meciareg.h>
45 #include <pccard/cardinfo.h>
46 #include <pccard/slot.h>
47 #ifndef MECIA_IOBASE
48 #define MECIA_IOBASE 0x80d0
49 #endif
50
51 /* Get pnp IDs */
52 #include <isa/isavar.h>
53
54 #include <dev/pccard/pccardvar.h>
55 #include "card_if.h"
56
57 #define MECIA_DEVICE2SOFTC(dev) ((struct mecia_slot *) device_get_softc(dev))
58
59 /*
60 * Prototypes for interrupt handler.
61 */
62 static driver_intr_t meciaintr;
63 static int mecia_ioctl(struct slot *, int, caddr_t);
64 static int mecia_power(struct slot *);
65 static void mecia_mapirq(struct slot *, int);
66 static timeout_t mecia_reset;
67 static void mecia_resume(struct slot *);
68 static void mecia_disable(struct slot *);
69 static timeout_t meciatimeout;
70 static struct callout_handle meciatimeout_ch
71 = CALLOUT_HANDLE_INITIALIZER(&meciatimeout_ch);
72 static int mecia_memory(struct slot *, int);
73 static int mecia_io(struct slot *, int);
74
75 /*
76 * Per-slot data table.
77 */
78 struct mecia_slot {
79 int unit; /* Unit number */
80 int slotnum; /* My slot number */
81 struct slot *slt; /* Back ptr to slot */
82 device_t dev; /* My device */
83 u_char last_reg1; /* Last value of change reg */
84 };
85
86 static struct slot_ctrl mecia_cinfo = {
87 mecia_mapirq,
88 mecia_memory,
89 mecia_io,
90 mecia_reset,
91 mecia_disable,
92 mecia_power,
93 mecia_ioctl,
94 mecia_resume,
95 1,
96 #if 0
97 1
98 #else
99 2 /* Fake for UE2212 LAN card */
100 #endif
101 };
102
103 static int validunits = 0;
104
105 /*
106 * Look for an NEC MECIA.
107 * For each available slot, allocate a PC-CARD slot.
108 */
109
110 static int
111 mecia_probe(device_t dev)
112 {
113 int validslots = 0;
114
115 /* Check isapnp ids */
116 if (isa_get_logicalid(dev)) /* skip PnP probes */
117 return (ENXIO);
118
119 if (inb(MECIA_REG0) != 0xff) {
120 validslots++;
121 /* XXX need to allocated the port resources */
122 device_set_desc(dev, "MECIA PC98 Original PCMCIA Controller");
123 }
124 return (validslots ? 0 : ENXIO);
125 }
126
127 static int
128 mecia_attach(device_t dev)
129 {
130 int error;
131 int irq;
132 void *ih;
133 device_t kid;
134 struct resource *r;
135 int rid;
136 struct slot *slt;
137 struct mecia_slot *sp;
138
139 sp = MECIA_DEVICE2SOFTC(dev);
140 sp->unit = validunits++;
141 kid = device_add_child(dev, NULL, -1);
142 if (kid == NULL) {
143 device_printf(dev, "Can't add pccard bus slot 0\n");
144 return (ENXIO);
145 }
146 device_probe_and_attach(kid);
147 slt = pccard_init_slot(kid, &mecia_cinfo);
148 if (slt == 0) {
149 device_printf(dev, "Can't get pccard info slot 0\n");
150 return (ENXIO);
151 }
152 slt->cdata = sp;
153 sp->slt = slt;
154 validunits++;
155
156 rid = 0;
157 r = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
158 if (!r)
159 return (ENXIO);
160
161 irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0);
162 if (irq == 0) {
163 /* See if the user has requested a specific IRQ */
164 if (!getenv_int("machdep.pccard.mecia_irq", &irq))
165 irq = 0;
166 }
167 rid = 0;
168 r = 0;
169 if (irq > 0) {
170 r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq,
171 irq, 1, RF_ACTIVE);
172 }
173 if (r && ((1 << (rman_get_start(r))) & MECIA_INT_MASK_ALLOWED) == 0) {
174 device_printf(dev,
175 "Hardware does not support irq %d, trying polling.\n",
176 irq);
177 bus_release_resource(dev, SYS_RES_IRQ, rid, r);
178 r = 0;
179 irq = 0;
180 }
181 if (r) {
182 error = bus_setup_intr(dev, r, INTR_TYPE_MISC,
183 meciaintr, (void *) sp, &ih);
184 if (error) {
185 bus_release_resource(dev, SYS_RES_IRQ, rid, r);
186 return (error);
187 }
188 irq = rman_get_start(r);
189 device_printf(dev, "management irq %d\n", irq);
190 } else {
191 irq = 0;
192 }
193 if (irq == 0) {
194 meciatimeout_ch = timeout(meciatimeout, (void *) sp, hz/2);
195 device_printf(dev, "Polling mode\n");
196 }
197
198 sp->last_reg1 = inb(MECIA_REG1);
199 if (sp->last_reg1 & MECIA_CARDEXIST) {
200 /* PCMCIA card exist */
201 sp->slt->laststate = sp->slt->state = filled;
202 pccard_event(sp->slt, card_inserted);
203 } else {
204 sp->slt->laststate = sp->slt->state = empty;
205 }
206 sp->slt->irq = irq;
207
208 return (bus_generic_attach(dev));
209 }
210
211 static int
212 mecia_sresource(struct slot *slt, caddr_t data)
213 {
214 struct pccard_resource *pr;
215 struct resource *r;
216 int flags;
217 int rid = 0;
218 device_t pccarddev = slt->dev;
219
220 pr = (struct pccard_resource *)data;
221 pr->resource_addr = ~0ul;
222 switch(pr->type) {
223 default:
224 return (EINVAL);
225 case SYS_RES_MEMORY:
226 case SYS_RES_IRQ:
227 case SYS_RES_IOPORT:
228 break;
229 }
230 flags = rman_make_alignment_flags(pr->size);
231 r = bus_alloc_resource(pccarddev, pr->type, &rid, pr->min, pr->max,
232 pr->size, flags);
233 if (r != NULL) {
234 pr->resource_addr = (u_long)rman_get_start(r);
235 bus_release_resource(bridgedev, pr->type, rid, r);
236 }
237 return (0);
238 }
239
240 /*
241 * ioctl calls - Controller specific ioctls
242 */
243 static int
244 mecia_ioctl(struct slot *slt, int cmd, caddr_t data)
245 {
246 switch(cmd) {
247 default:
248 return (ENOTTY);
249 case PIOCSRESOURCE: /* Can I use this resource? */
250 mecia_sresource(slt, data);
251 break;
252 }
253 return (0);
254 }
255
256 /*
257 * MECIA timer. If the controller doesn't have a free IRQ to use
258 * or if interrupt steering doesn't work, poll the controller for
259 * insertion/removal events.
260 */
261 static void
262 meciatimeout(void *chan)
263 {
264 meciaintr(chan);
265 meciatimeout_ch = timeout(meciatimeout, chan, hz/2);
266 }
267
268 /*
269 * MECIA Interrupt handler.
270 * Check the slot and report any changes.
271 */
272 static void
273 meciaintr(void *arg)
274 {
275 u_char reg1;
276 int s;
277 struct mecia_slot *sp = (struct mecia_slot *) arg;
278
279 s = splhigh();
280 /* Check for a card in this slot */
281 reg1 = inb(MECIA_REG1);
282 if ((sp->last_reg1 ^ reg1) & MECIA_CARDEXIST) {
283 sp->last_reg1 = reg1;
284 if (reg1 & MECIA_CARDEXIST)
285 pccard_event(sp->slt, card_inserted);
286 else
287 pccard_event(sp->slt, card_removed);
288 }
289 splx(s);
290 }
291
292 /*
293 * local functions for PC-98 Original PC-Card controller
294 */
295 #define MECIA_ALWAYS_128MAPPING 1 /* trick for using UE2212 */
296
297 int mecia_mode = 0; /* almost the same as the value in MECIA_REG2 */
298
299 static unsigned char reg_winsel = MECIA_UNMAPWIN;
300 static unsigned short reg_pagofs = 0;
301
302 static int
303 mecia_memory(struct slot *slt, int win)
304 {
305 struct mem_desc *mp = &slt->mem[win];
306 unsigned char x;
307
308 if (mp->flags & MDF_ACTIVE) {
309 /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */
310 if ((unsigned long)mp->start != 0xda000) {
311 printf(
312 "sys_addr must be 0xda000. requested address = %p\n",
313 mp->start);
314 return (EINVAL);
315 }
316
317 /* omajinai ??? */
318 outb(MECIA_REG0, 0);
319 x = inb(MECIA_REG1);
320 x &= 0xfc;
321 x |= 0x02;
322 outb(MECIA_REG1, x);
323 reg_winsel = inb(MECIA_REG_WINSEL);
324 reg_pagofs = inw(MECIA_REG_PAGOFS);
325 outb(MECIA_REG_WINSEL, MECIA_MAPWIN);
326 outw(MECIA_REG_PAGOFS, (mp->card >> 13)); /* 8KB */
327
328 if (mp->flags & MDF_ATTR)
329 outb(MECIA_REG7, inb(MECIA_REG7) | MECIA_ATTRMEM);
330 else
331 outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_ATTRMEM));
332
333 outb(MECIA_REG_WINSEL, MECIA_MAPWIN);
334 #if 0
335 if ((mp->flags & MDF_16BITS) == 1) /* 16bit */
336 outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_8BIT));
337 else /* 8bit */
338 outb(MECIA_REG2, inb(MECIA_REG2) | MECIA_8BIT);
339 #endif
340 } else { /* !(mp->flags & MDF_ACTIVE) */
341 outb(MECIA_REG0, 0);
342 x = inb(MECIA_REG1);
343 x &= 0xfc;
344 x |= 0x02;
345 outb(MECIA_REG1, x);
346 #if 0
347 outb(MECIA_REG_WINSEL, MECIA_UNMAPWIN);
348 outw(MECIA_REG_PAGOFS, 0);
349 #else
350 outb(MECIA_REG_WINSEL, reg_winsel);
351 outw(MECIA_REG_PAGOFS, reg_pagofs);
352 #endif
353 }
354 return (0);
355 }
356
357 static int
358 mecia_io(struct slot *slt, int win)
359 {
360 struct io_desc *ip = &slt->io[win];
361 unsigned char x;
362 unsigned short cardbase;
363 u_short ofst;
364
365 if (win != 0) {
366 /* ignore for UE2212 */
367 printf(
368 "mecia:Illegal MECIA I/O window(%d) request! Ignored.\n", win);
369 /* return (EINVAL);*/
370 return (0);
371 }
372
373 if (ip->flags & IODF_ACTIVE) {
374 x = inb(MECIA_REG2) & 0x0f;
375 #if 0
376 if (! (ip->flags & IODF_CS16))
377 x |= MECIA_8BIT;
378 #else
379 if (! (ip->flags & IODF_16BIT)) {
380 x |= MECIA_8BIT;
381 mecia_mode |= MECIA_8BIT;
382 }
383 #endif
384
385 ofst = ip->start & 0xf;
386 cardbase = ip->start & ~0xf;
387 #ifndef MECIA_ALWAYS_128MAPPING
388 if (ip->size + ofst > 16)
389 #endif
390 { /* 128bytes mapping */
391 x |= MECIA_MAP128;
392 mecia_mode |= MECIA_MAP128;
393 ofst |= ((cardbase & 0x70) << 4);
394 cardbase &= ~0x70;
395 }
396
397 x |= MECIA_MAPIO;
398 outb(MECIA_REG2, x);
399
400 outw(MECIA_REG4, MECIA_IOBASE); /* 98side I/O base */
401 outw(MECIA_REG5, cardbase); /* card side I/O base */
402
403 if (bootverbose) {
404 printf("mecia: I/O mapped 0x%04x(98) -> "
405 "0x%04x(Card) and width %d bytes\n",
406 MECIA_IOBASE+ofst, ip->start, ip->size);
407 printf("mecia: reg2=0x%02x reg3=0x%02x reg7=0x%02x\n",
408 inb(MECIA_REG2), inb(MECIA_REG3),
409 inb(MECIA_REG7));
410 printf("mecia: mode=%d\n", mecia_mode);
411 }
412
413 ip->start = MECIA_IOBASE + ofst;
414 } else {
415 outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO));
416 mecia_mode = 0;
417 }
418 return (0);
419 }
420
421 static int
422 mecia_power(struct slot *slt)
423 {
424 unsigned char reg;
425
426 reg = inb(MECIA_REG7) & (~MECIA_VPP12V);
427 switch(slt->pwr.vpp) {
428 default:
429 return (EINVAL);
430 case 50:
431 break;
432 case 120:
433 reg |= MECIA_VPP12V;
434 break;
435 }
436 outb(MECIA_REG7, reg);
437 DELAY(100*1000);
438
439 reg = inb(MECIA_REG2) & (~MECIA_VCC3P3V);
440 switch(slt->pwr.vcc) {
441 default:
442 return (EINVAL);
443 case 33:
444 reg |= MECIA_VCC3P3V;
445 break;
446 case 50:
447 break;
448 }
449 outb(MECIA_REG2, reg);
450 DELAY(100*1000);
451 return (0);
452 }
453
454 static void
455 mecia_mapirq(struct slot *slt, int irq)
456 {
457 u_char x;
458
459 switch (irq) {
460 case 3:
461 x = MECIA_INT0;
462 break;
463 case 5:
464 x = MECIA_INT1;
465 break;
466 case 6:
467 x = MECIA_INT2;
468 break;
469 case 10:
470 x = MECIA_INT4;
471 break;
472 case 12:
473 x = MECIA_INT5;
474 break;
475 case 0: /* disable */
476 x = MECIA_INTDISABLE;
477 break;
478 default:
479 printf("mecia: illegal irq %d\n", irq);
480 return;
481 }
482 #ifdef MECIA_DEBUG
483 printf("mecia: irq=%d mapped.\n", irq);
484 #endif
485 outb(MECIA_REG3, x);
486 }
487
488 static void
489 mecia_reset(void *chan)
490 {
491 struct slot *slt = chan;
492
493 outb(MECIA_REG0, 0);
494 outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO));
495 outb(MECIA_REG3, MECIA_INTDISABLE);
496 #if 0
497 /* mecia_reset() is called after mecia_power() */
498 outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_VCC3P3V));
499 outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_VPP12V));
500 #endif
501 outb(MECIA_REG1, 0);
502
503 selwakeuppri(&slt->selp, PZERO);
504 }
505
506 static void
507 mecia_disable(struct slot *slt)
508 {
509 /* null function */
510 }
511
512 static void
513 mecia_resume(struct slot *slt)
514 {
515 /* XXX MECIA How ? */
516 }
517
518 static int
519 mecia_activate_resource(device_t dev, device_t child, int type, int rid,
520 struct resource *r)
521 {
522 struct pccard_devinfo *devi = device_get_ivars(child);
523 int err;
524
525 if (dev != device_get_parent(device_get_parent(child)) || devi == NULL)
526 return (bus_generic_activate_resource(dev, child, type,
527 rid, r));
528
529 switch (type) {
530 case SYS_RES_IOPORT: {
531 struct io_desc *ip;
532 ip = &devi->slt->io[rid];
533 if (ip->flags == 0) {
534 if (rid == 0)
535 ip->flags = IODF_WS | IODF_16BIT | IODF_CS16;
536 else
537 ip->flags = devi->slt->io[0].flags;
538 }
539 ip->flags |= IODF_ACTIVE;
540 ip->start = rman_get_start(r);
541 ip->size = rman_get_end(r) - rman_get_start(r) + 1;
542 err = mecia_cinfo.mapio(devi->slt, rid);
543 if (err)
544 return (err);
545 break;
546 }
547 case SYS_RES_IRQ:
548 /*
549 * We actually defer the activation of the IRQ resource
550 * until the interrupt is registered to avoid stray
551 * interrupt messages.
552 */
553 break;
554 case SYS_RES_MEMORY: {
555 struct mem_desc *mp;
556 if (rid >= NUM_MEM_WINDOWS)
557 return (EINVAL);
558 mp = &devi->slt->mem[rid];
559 mp->flags |= MDF_ACTIVE;
560 mp->start = (caddr_t) rman_get_start(r);
561 mp->size = rman_get_end(r) - rman_get_start(r) + 1;
562 err = mecia_cinfo.mapmem(devi->slt, rid);
563 if (err)
564 return (err);
565 break;
566 }
567 default:
568 break;
569 }
570 err = bus_generic_activate_resource(dev, child, type, rid, r);
571 return (err);
572 }
573
574 static int
575 mecia_deactivate_resource(device_t dev, device_t child, int type, int rid,
576 struct resource *r)
577 {
578 struct pccard_devinfo *devi = device_get_ivars(child);
579 int err;
580
581 if (dev != device_get_parent(device_get_parent(child)) || devi == NULL)
582 return (bus_generic_deactivate_resource(dev, child, type,
583 rid, r));
584
585 switch (type) {
586 case SYS_RES_IOPORT: {
587 struct io_desc *ip = &devi->slt->io[rid];
588 ip->flags &= ~IODF_ACTIVE;
589 err = mecia_cinfo.mapio(devi->slt, rid);
590 if (err)
591 return (err);
592 break;
593 }
594 case SYS_RES_IRQ:
595 break;
596 case SYS_RES_MEMORY: {
597 struct mem_desc *mp = &devi->slt->mem[rid];
598 mp->flags &= ~(MDF_ACTIVE | MDF_ATTR);
599 err = mecia_cinfo.mapmem(devi->slt, rid);
600 if (err)
601 return (err);
602 break;
603 }
604 default:
605 break;
606 }
607 err = bus_generic_deactivate_resource(dev, child, type, rid, r);
608 return (err);
609 }
610
611 static int
612 mecia_setup_intr(device_t dev, device_t child, struct resource *irq,
613 int flags, driver_intr_t *intr, void *arg, void **cookiep)
614 {
615 struct pccard_devinfo *devi = device_get_ivars(child);
616 int err;
617
618 if (((1 << rman_get_start(irq)) & MECIA_INT_MASK_ALLOWED) == 0) {
619 device_printf(dev, "Hardware does not support irq %ld.\n",
620 rman_get_start(irq));
621 return (EINVAL);
622 }
623
624 err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg,
625 cookiep);
626 if (err == 0)
627 mecia_cinfo.mapirq(devi->slt, rman_get_start(irq));
628 else
629 device_printf(dev, "Error %d irq %ld\n", err,
630 rman_get_start(irq));
631 return (err);
632 }
633
634 static int
635 mecia_teardown_intr(device_t dev, device_t child, struct resource *irq,
636 void *cookie)
637 {
638 struct pccard_devinfo *devi = device_get_ivars(child);
639
640 mecia_cinfo.mapirq(devi->slt, 0);
641 return (bus_generic_teardown_intr(dev, child, irq, cookie));
642 }
643
644 static int
645 mecia_set_res_flags(device_t bus, device_t child, int restype, int rid,
646 u_long value)
647 {
648 struct pccard_devinfo *devi = device_get_ivars(child);
649 int err = 0;
650
651 switch (restype) {
652 case SYS_RES_MEMORY: {
653 struct mem_desc *mp = &devi->slt->mem[rid];
654 switch (value) {
655 case PCCARD_A_MEM_COM:
656 mp->flags &= ~MDF_ATTR;
657 break;
658 case PCCARD_A_MEM_ATTR:
659 mp->flags |= MDF_ATTR;
660 break;
661 case PCCARD_A_MEM_8BIT:
662 mp->flags &= ~MDF_16BITS;
663 break;
664 case PCCARD_A_MEM_16BIT:
665 mp->flags |= MDF_16BITS;
666 break;
667 }
668 err = mecia_cinfo.mapmem(devi->slt, rid);
669 break;
670 }
671 default:
672 err = EOPNOTSUPP;
673 }
674 return (err);
675 }
676
677 static int
678 mecia_get_res_flags(device_t bus, device_t child, int restype, int rid,
679 u_long *value)
680 {
681 struct pccard_devinfo *devi = device_get_ivars(child);
682 int err = 0;
683
684 if (value == 0)
685 return (ENOMEM);
686
687 switch (restype) {
688 case SYS_RES_IOPORT: {
689 struct io_desc *ip = &devi->slt->io[rid];
690 *value = ip->flags;
691 break;
692 }
693 case SYS_RES_MEMORY: {
694 struct mem_desc *mp = &devi->slt->mem[rid];
695 *value = mp->flags;
696 break;
697 }
698 default:
699 err = EOPNOTSUPP;
700 }
701 return (err);
702 }
703
704 static int
705 mecia_set_memory_offset(device_t bus, device_t child, int rid,
706 u_int32_t offset, u_int32_t *deltap)
707 {
708 struct pccard_devinfo *devi = device_get_ivars(child);
709 struct mem_desc *mp = &devi->slt->mem[rid];
710
711 mp->card = offset;
712 if (deltap)
713 *deltap = 0; /* XXX BAD XXX */
714 return (mecia_cinfo.mapmem(devi->slt, rid));
715 }
716
717 static int
718 mecia_get_memory_offset(device_t bus, device_t child, int rid,
719 u_int32_t *offset)
720 {
721 struct pccard_devinfo *devi = device_get_ivars(child);
722 struct mem_desc *mp = &devi->slt->mem[rid];
723
724 if (offset == 0)
725 return (ENOMEM);
726
727 *offset = mp->card;
728
729 return (0);
730 }
731
732 static device_method_t mecia_methods[] = {
733 /* Device interface */
734 DEVMETHOD(device_probe, mecia_probe),
735 DEVMETHOD(device_attach, mecia_attach),
736 DEVMETHOD(device_detach, bus_generic_detach),
737 DEVMETHOD(device_shutdown, bus_generic_shutdown),
738 DEVMETHOD(device_suspend, bus_generic_suspend),
739 DEVMETHOD(device_resume, bus_generic_resume),
740
741 /* Bus interface */
742 DEVMETHOD(bus_print_child, bus_generic_print_child),
743 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
744 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
745 DEVMETHOD(bus_activate_resource, mecia_activate_resource),
746 DEVMETHOD(bus_deactivate_resource, mecia_deactivate_resource),
747 DEVMETHOD(bus_setup_intr, mecia_setup_intr),
748 DEVMETHOD(bus_teardown_intr, mecia_teardown_intr),
749
750 /* Card interface */
751 DEVMETHOD(card_set_res_flags, mecia_set_res_flags),
752 DEVMETHOD(card_get_res_flags, mecia_get_res_flags),
753 DEVMETHOD(card_set_memory_offset, mecia_set_memory_offset),
754 DEVMETHOD(card_get_memory_offset, mecia_get_memory_offset),
755
756 { 0, 0 }
757 };
758
759 devclass_t mecia_devclass;
760
761 static driver_t mecia_driver = {
762 "mecia",
763 mecia_methods,
764 sizeof(struct mecia_slot)
765 };
766
767 DRIVER_MODULE(mecia, isa, mecia_driver, mecia_devclass, 0, 0);
Cache object: d8dfc2298dbdb801c90a2cfbbdd9ecee
|