FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/isa/mpu.c
1 /*
2 * The low level driver for Roland MPU-401 compatible Midi interfaces.
3 *
4 * Copyright by Hannu Savolainen 1993
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 2.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 * 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 * Modified: Riccardo Facchetti 24 Mar 1995 - Added the Audio Excel DSP 16
27 * initialization routine.
28 *
29 * Ported to the new Audio Driver by Luigi Rizzo:
30 * (C) 1999 Seigo Tanimura
31 *
32 * This is the MPU401 midi interface driver for FreeBSD, based on the Luigi Sound Driver.
33 * This handles io against /dev/midi, the midi {in, out}put event queues
34 * and the event/message transmittion to/from an MPU401 interface.
35 *
36 * $FreeBSD: releng/5.2/sys/dev/sound/isa/mpu.c 121711 2003-10-29 21:54:37Z deischen $
37 *
38 */
39
40 #include <dev/sound/midi/midi.h>
41 #include <dev/sound/chip.h>
42 #include <machine/cpufunc.h>
43
44 #include <isa/isavar.h>
45 #include <dev/ic/ns16550.h>
46
47 static devclass_t midi_devclass;
48
49 #ifndef DDB
50 #undef DDB
51 #define DDB(x)
52 #endif /* DDB */
53
54 #define MPU_DATAPORT 0
55 #define MPU_CMDPORT 1
56 #define MPU_STATPORT 1
57
58 #define MPU_RESET 0xff
59 #define MPU_UART 0x3f
60 #define MPU_ACK 0xfe
61
62 #define MPU_STATMASK 0xc0
63 #define MPU_OUTPUTBUSY 0x40
64 #define MPU_INPUTBUSY 0x80
65
66 #define MPU_TRYDATA 50
67 #define MPU_DELAY 25000
68
69 /* Device flag. */
70 #define MPU_DF_NO_IRQ 1
71
72 extern synthdev_info midisynth_op_desc;
73
74 /* PnP IDs */
75 static struct isa_pnp_id mpu_ids[] = {
76 {0x01200001, "@H@2001 Midi Interface"}, /* @H@2001 */
77 {0x01100001, "@H@1001 Midi Interface"}, /* @H@1001 */
78 #if notdef
79 /* TODO: write bridge driver for these devices */
80 {0x0000630e, "CSC0000 Midi Interface"}, /* CSC0000 */
81 {0x2100a865, "YMH0021 Midi Interface"}, /* YMH0021 */
82 {0x80719304, "ADS7180 Midi Interface"}, /* ADS7180 */
83 {0x0300561e, "GRV0003 Midi Interface"}, /* GRV0003 */
84 #endif
85 };
86
87 /* These are the synthesizer and the midi interface information. */
88 static struct synth_info mpu_synthinfo = {
89 "MPU401 MIDI",
90 0,
91 SYNTH_TYPE_MIDI,
92 0,
93 0,
94 128,
95 128,
96 128,
97 SYNTH_CAP_INPUT,
98 };
99
100 static struct midi_info mpu_midiinfo = {
101 "MPU401 MIDI",
102 0,
103 0,
104 0,
105 };
106
107 /*
108 * These functions goes into mpu_op_desc to get called
109 * from sound.c.
110 */
111
112 static int mpu_probe(device_t dev);
113 static int mpu_probe1(device_t dev);
114 static int mpu_probe2(device_t dev);
115 static int mpu_attach(device_t dev);
116 static int mpusbc_probe(device_t dev);
117 static int mpusbc_attach(device_t dev);
118
119 static d_ioctl_t mpu_ioctl;
120 static driver_intr_t mpu_intr;
121 static midi_callback_t mpu_callback;
122
123 /* Here is the parameter structure per a device. */
124 struct mpu_softc {
125 device_t dev; /* device information */
126 mididev_info *devinfo; /* midi device information */
127
128 struct mtx mtx; /* Mutex to protect the device. */
129
130 struct resource *io; /* Base of io port */
131 int io_rid; /* Io resource ID */
132 u_long irq_val; /* Irq value */
133 struct resource *irq; /* Irq */
134 int irq_rid; /* Irq resource ID */
135 void *ih; /* Interrupt cookie */
136
137 int fflags; /* File flags */
138 };
139
140 typedef struct mpu_softc *sc_p;
141
142 /* These functions are local. */
143 static void mpu_startplay(sc_p scp);
144 static void mpu_xmit(sc_p scp);
145 static int mpu_resetmode(sc_p scp);
146 static int mpu_uartmode(sc_p scp);
147 static int mpu_waitack(sc_p scp);
148 static int mpu_status(sc_p scp);
149 static int mpu_command(sc_p scp, u_int8_t value);
150 static int mpu_readdata(sc_p scp, u_int8_t *value);
151 static int mpu_writedata(sc_p scp, u_int8_t value);
152 static u_int mpu_readport(sc_p scp, int off);
153 static void mpu_writeport(sc_p scp, int off, u_int8_t value);
154 static int mpu_allocres(sc_p scp, device_t dev);
155 static void mpu_releaseres(sc_p scp, device_t dev);
156
157 /*
158 * This is the device descriptor for the midi device.
159 */
160 static mididev_info mpu_op_desc = {
161 "MPU401 midi",
162
163 SNDCARD_MPU401,
164
165 NULL,
166 NULL,
167 mpu_ioctl,
168
169 mpu_callback,
170
171 MIDI_BUFFSIZE, /* Queue Length */
172
173 0, /* XXX This is not an *audio* device! */
174 };
175
176 /*
177 * Here are the main functions to interact to the user process.
178 */
179
180 static int
181 mpu_probe(device_t dev)
182 {
183 sc_p scp;
184 int ret;
185
186 /* Check isapnp ids */
187 if (isa_get_logicalid(dev) != 0)
188 return (ISA_PNP_PROBE(device_get_parent(dev), dev, mpu_ids));
189
190 scp = device_get_softc(dev);
191
192 device_set_desc(dev, mpu_op_desc.name);
193 bzero(scp, sizeof(*scp));
194
195 scp->io_rid = 0;
196 ret = mpu_probe1(dev);
197 if (ret != 0)
198 return (ret);
199 ret = mpu_probe2(dev);
200 if (ret != 0)
201 return (ret);
202
203 return (0);
204 }
205
206 /*
207 * Make sure this is an MPU401, not an 16550 uart.
208 * Called only for non-pnp devices.
209 */
210 static int
211 mpu_probe1(device_t dev)
212 {
213 sc_p scp;
214 int iir;
215 struct resource *io;
216
217 scp = device_get_softc(dev);
218
219 /*
220 * If an MPU401 is ready to both input and output,
221 * the status register value is zero, which may
222 * confuse an 16550 uart to probe as an MPU401.
223 * We read the IIR (base + 2), which is not used
224 * by an MPU401.
225 */
226 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 3, RF_ACTIVE);
227 iir = bus_space_read_1(rman_get_bustag(io), rman_get_bushandle(io), com_iir) & 0xff;
228 bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, io);
229 if ((iir & ~(IIR_IMASK | IIR_FIFO_MASK)) == 0)
230 /* Likely to be an 16550. */
231 return (ENXIO);
232
233 return (0);
234 }
235
236 /* Look up the irq. */
237 static int
238 mpu_probe2(device_t dev)
239 {
240 sc_p scp;
241 int unit, i;
242 intrmask_t irqp0, irqp1;
243
244 scp = device_get_softc(dev);
245 unit = device_get_unit(dev);
246
247 scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
248 if (scp->io == NULL)
249 return (ENXIO);
250
251 MIDI_DEBUG(printf("mpu%d: probing.\n", unit));
252
253 /* Reset the interface. */
254 if (mpu_resetmode(scp) != 0 || mpu_waitack(scp) != 0) {
255 printf("mpu%d: reset failed.\n", unit);
256 mpu_releaseres(scp, dev);
257 return (ENXIO);
258 }
259
260 /*
261 * At this point, we are likely to have an interface.
262 *
263 * Switching the interface to uart mode gives us an interrupt.
264 * We can make use of it to determine the irq.
265 * Idea-stolen-from: sys/isa/sio.c:sioprobe()
266 */
267
268 critical_enter();
269
270 /*
271 * See the initial irq. We have to do this now,
272 * otherwise a midi module/instrument might send
273 * an active sensing, to mess up the irq.
274 */
275 irqp0 = isa_irq_pending();
276 irqp1 = 0;
277
278 /* Switch to uart mode. */
279 if (mpu_uartmode(scp) != 0) {
280 critical_exit();
281 printf("mpu%d: mode switching failed.\n", unit);
282 mpu_releaseres(scp, dev);
283 return (ENXIO);
284 }
285
286 if (device_get_flags(dev) & MPU_DF_NO_IRQ) {
287 irqp0 = irqp1 = 0;
288 goto no_irq;
289 }
290
291 /* See which irq we have now. */
292 for (i = 0 ; i < MPU_TRYDATA ; i++) {
293 DELAY(MPU_DELAY);
294 irqp1 = isa_irq_pending();
295 if (irqp1 != irqp0)
296 break;
297 }
298 if (irqp1 == irqp0) {
299 critical_exit();
300 printf("mpu%d: switching the mode gave no interrupt.\n", unit);
301 mpu_releaseres(scp, dev);
302 return (ENXIO);
303 }
304
305 no_irq:
306 /* Wait to see an ACK. */
307 if (mpu_waitack(scp) != 0) {
308 critical_exit();
309 printf("mpu%d: not acked.\n", unit);
310 mpu_releaseres(scp, dev);
311 return (ENXIO);
312 }
313
314 critical_exit();
315
316 if (device_get_flags(dev) & MPU_DF_NO_IRQ)
317 scp->irq_val = 0;
318 else
319 /* We have found the irq. */
320 scp->irq_val = ffs(~irqp0 & irqp1) - 1;
321
322 MIDI_DEBUG(printf("mpu%d: probed.\n", unit));
323
324 return (0);
325 }
326
327 static int
328 mpusbc_probe(device_t dev)
329 {
330 char *s;
331 sc_p scp;
332 struct sndcard_func *func;
333
334 /* The parent device has already been probed. */
335
336 func = device_get_ivars(dev);
337 if (func == NULL || func->func != SCF_MIDI)
338 return (ENXIO);
339
340 s = "SB Midi Interface";
341
342 scp = device_get_softc(dev);
343 bzero(scp, sizeof(*scp));
344 scp->io_rid = 1;
345 scp->irq_rid = 0;
346 device_set_desc(dev, s);
347 return (0);
348 }
349
350 static int
351 mpu_attach(device_t dev)
352 {
353 sc_p scp;
354 mididev_info *devinfo;
355
356 scp = device_get_softc(dev);
357
358 MIDI_DEBUG(printf("mpu: attaching.\n"));
359
360 mtx_init(&scp->mtx, "mpumid", NULL, MTX_DEF);
361
362 /* Allocate the resources, switch to uart mode. */
363 if (mpu_allocres(scp, dev) || mpu_uartmode(scp)) {
364 mpu_releaseres(scp, dev);
365 mtx_destroy(&scp->mtx);
366 return (ENXIO);
367 }
368
369 /* mpu_probe() has put the interface to uart mode. */
370
371 /* Fill the softc. */
372 scp->dev = dev;
373 scp->devinfo = devinfo = create_mididev_info_unit(MDT_MIDI, &mpu_op_desc, &midisynth_op_desc);
374
375 /* Fill the midi info. */
376 if (scp->irq != NULL)
377 snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x irq %d",
378 (u_int)rman_get_start(scp->io), (int)rman_get_start(scp->irq));
379 else
380 snprintf(devinfo->midistat, sizeof(devinfo->midistat), "at 0x%x",
381 (u_int)rman_get_start(scp->io));
382
383 midiinit(devinfo, dev);
384
385 /* Now we can handle the interrupts. */
386 if (scp->irq != NULL)
387 bus_setup_intr(dev, scp->irq, INTR_TYPE_AV, mpu_intr, scp,
388 &scp->ih);
389
390 MIDI_DEBUG(printf("mpu: attached.\n"));
391
392 return (0);
393 }
394
395 static int
396 mpusbc_attach(device_t dev)
397 {
398 sc_p scp;
399 int unit;
400
401 scp = device_get_softc(dev);
402 unit = device_get_unit(dev);
403
404 mpu_attach(dev);
405
406 return (0);
407 }
408
409 static int
410 mpu_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
411 {
412 sc_p scp;
413 mididev_info *devinfo;
414 int unit;
415 struct synth_info *synthinfo;
416 struct midi_info *midiinfo;
417
418 unit = MIDIUNIT(i_dev);
419
420 MIDI_DEBUG(printf("mpu_ioctl: unit %d, cmd %s.\n", unit, midi_cmdname(cmd, cmdtab_midiioctl)));
421
422 devinfo = get_mididev_info(i_dev, &unit);
423 if (devinfo == NULL) {
424 MIDI_DEBUG(printf("mpu_ioctl: unit %d is not configured.\n", unit));
425 return (ENXIO);
426 }
427 scp = devinfo->softc;
428
429 switch (cmd) {
430 case SNDCTL_SYNTH_INFO:
431 synthinfo = (struct synth_info *)arg;
432 if (synthinfo->device != unit)
433 return (ENXIO);
434 bcopy(&mpu_synthinfo, synthinfo, sizeof(mpu_synthinfo));
435 synthinfo->device = unit;
436 return (0);
437 break;
438 case SNDCTL_MIDI_INFO:
439 midiinfo = (struct midi_info *)arg;
440 if (midiinfo->device != unit)
441 return (ENXIO);
442 bcopy(&mpu_midiinfo, midiinfo, sizeof(mpu_midiinfo));
443 midiinfo->device = unit;
444 return (0);
445 break;
446 default:
447 return (ENOSYS);
448 }
449 /* NOTREACHED */
450 return (EINVAL);
451 }
452
453 static void
454 mpu_intr(void *arg)
455 {
456 sc_p scp;
457 u_char c;
458 mididev_info *devinfo;
459 int leni;
460
461 scp = (sc_p)arg;
462 devinfo = scp->devinfo;
463
464 mtx_lock(&devinfo->flagqueue_mtx);
465 mtx_lock(&scp->mtx);
466
467 /* Read the received data. */
468 while ((mpu_status(scp) & MPU_INPUTBUSY) == 0) {
469 /* Receive the data. */
470 mpu_readdata(scp, &c);
471 mtx_unlock(&scp->mtx);
472 /* Queue into the passthru buffer and start transmitting if we can. */
473 if ((devinfo->flags & MIDI_F_PASSTHRU) != 0 && ((devinfo->flags & MIDI_F_BUSY) == 0 || (devinfo->fflags & FWRITE) == 0)) {
474 midibuf_input_intr(&devinfo->midi_dbuf_passthru, &c, sizeof(c), &leni);
475 devinfo->callback(devinfo, MIDI_CB_START | MIDI_CB_WR);
476 }
477 /* Queue if we are reading. Discard an active sensing. */
478 if ((devinfo->flags & MIDI_F_READING) != 0 && c != 0xfe) {
479 midibuf_input_intr(&devinfo->midi_dbuf_in, &c, sizeof(c), &leni);
480 }
481 mtx_lock(&scp->mtx);
482 }
483 mtx_unlock(&scp->mtx);
484 mtx_unlock(&devinfo->flagqueue_mtx);
485
486 /* Invoke the upper layer. */
487 midi_intr(devinfo);
488 }
489
490 static int
491 mpu_callback(void *di, int reason)
492 {
493 int unit;
494 sc_p scp;
495 mididev_info *d;
496
497 d = (mididev_info *)di;
498
499 mtx_assert(&d->flagqueue_mtx, MA_OWNED);
500
501 if (d == NULL) {
502 MIDI_DEBUG(printf("mpu_callback: device not configured.\n"));
503 return (ENXIO);
504 }
505
506 unit = d->unit;
507 scp = d->softc;
508
509 switch (reason & MIDI_CB_REASON_MASK) {
510 case MIDI_CB_START:
511 if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) == 0)
512 /* Begin recording. */
513 d->flags |= MIDI_F_READING;
514 if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) == 0)
515 /* Start playing. */
516 mpu_startplay(scp);
517 break;
518 case MIDI_CB_STOP:
519 case MIDI_CB_ABORT:
520 if ((reason & MIDI_CB_RD) != 0 && (d->flags & MIDI_F_READING) != 0)
521 /* Stop recording. */
522 d->flags &= ~MIDI_F_READING;
523 if ((reason & MIDI_CB_WR) != 0 && (d->flags & MIDI_F_WRITING) != 0)
524 /* Stop Playing. */
525 d->flags &= ~MIDI_F_WRITING;
526 break;
527 }
528
529 return (0);
530 }
531
532 /*
533 * The functions below here are the libraries for the above ones.
534 */
535
536 /*
537 * Starts to play the data in the output queue.
538 */
539 static void
540 mpu_startplay(sc_p scp)
541 {
542 mididev_info *devinfo;
543
544 devinfo = scp->devinfo;
545
546 mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
547
548 /* Can we play now? */
549 if (devinfo->midi_dbuf_out.rl == 0)
550 return;
551
552 devinfo->flags |= MIDI_F_WRITING;
553 mpu_xmit(scp);
554 }
555
556 static void
557 mpu_xmit(sc_p scp)
558 {
559 register mididev_info *devinfo;
560 register midi_dbuf *dbuf;
561 u_char c;
562 int leno;
563
564 devinfo = scp->devinfo;
565
566 mtx_assert(&devinfo->flagqueue_mtx, MA_OWNED);
567
568 /* See which source to use. */
569 if ((devinfo->flags & MIDI_F_PASSTHRU) == 0 || ((devinfo->flags & MIDI_F_BUSY) != 0 && (devinfo->fflags & FWRITE) != 0))
570 dbuf = &devinfo->midi_dbuf_out;
571 else
572 dbuf = &devinfo->midi_dbuf_passthru;
573
574 /* Transmit the data in the queue. */
575 while ((devinfo->flags & MIDI_F_WRITING) != 0) {
576 if (dbuf->rl == 0)
577 break;
578 else {
579 mtx_lock(&scp->mtx);
580 /* XXX Wait until we can write the data. */
581 if ((mpu_status(scp) & MPU_OUTPUTBUSY) == 0) {
582 /* Send the data. */
583 midibuf_output_intr(dbuf, &c, sizeof(c), &leno);
584 mpu_writedata(scp, c);
585 /* We are playing now. */
586 devinfo->flags |= MIDI_F_WRITING;
587 }
588 mtx_unlock(&scp->mtx);
589 }
590 }
591 /* Stop playing. */
592 devinfo->flags &= ~MIDI_F_WRITING;
593 }
594
595
596 /*
597 * Reset mpu.
598 * The caller must lock scp->mtx before calling this function if needed.
599 */
600 static int
601 mpu_resetmode(sc_p scp)
602 {
603 int i, resp;
604
605 /* Reset the mpu. */
606 resp = 0;
607 for (i = 0 ; i < MPU_TRYDATA ; i++) {
608 resp = mpu_command(scp, MPU_RESET);
609 if (resp == 0)
610 break;
611 }
612 if (resp != 0)
613 return (1);
614
615 DELAY(MPU_DELAY);
616 return (0);
617 }
618
619 /*
620 * Switch to uart mode.
621 * The caller must lock scp->mtx before calling this function if needed.
622 */
623 static int
624 mpu_uartmode(sc_p scp)
625 {
626 int i, resp;
627
628 /* Switch to uart mode. */
629 resp = 0;
630 for (i = 0 ; i < MPU_TRYDATA ; i++) {
631 resp = mpu_command(scp, MPU_UART);
632 if (resp == 0)
633 break;
634 }
635 if (resp != 0)
636 return (1);
637
638 DELAY(MPU_DELAY);
639 return (0);
640 }
641
642 /*
643 * Wait to see an ACK.
644 * The caller must lock scp->mtx before calling this function if needed.
645 */
646 static int
647 mpu_waitack(sc_p scp)
648 {
649 int i;
650 u_int8_t resp;
651
652 resp = 0;
653 for (i = 0 ; i < MPU_TRYDATA ; i++) {
654 if (mpu_readdata(scp, &resp) == 0)
655 break;
656 }
657 if (resp != MPU_ACK)
658 return (1);
659
660 DELAY(MPU_DELAY);
661 return (0);
662 }
663
664 /* Reads the status. */
665 static int
666 mpu_status(sc_p scp)
667 {
668 return mpu_readport(scp, MPU_STATPORT);
669 }
670
671 /* Writes a command. */
672 static int
673 mpu_command(sc_p scp, u_int8_t value)
674 {
675 u_int status;
676
677 /* Is the interface ready to write? */
678 status = mpu_status(scp);
679 if ((status & MPU_OUTPUTBUSY) != 0)
680 /* The interface is busy. */
681 return (EAGAIN);
682
683 mpu_writeport(scp, MPU_CMDPORT, value);
684
685 return (0);
686 }
687
688 /* Reads a byte of data. */
689 static int
690 mpu_readdata(sc_p scp, u_int8_t *value)
691 {
692 u_int status;
693
694 if (value == NULL)
695 return (EINVAL);
696
697 /* Is the interface ready to write? */
698 status = mpu_status(scp);
699 if ((status & MPU_INPUTBUSY) != 0)
700 /* The interface is busy. */
701 return (EAGAIN);
702
703 *value = (u_int8_t)(mpu_readport(scp, MPU_DATAPORT) & 0xff);
704
705 return (0);
706 }
707
708 /* Writes a byte of data. */
709 static int
710 mpu_writedata(sc_p scp, u_int8_t value)
711 {
712 u_int status;
713
714 /* Is the interface ready to write? */
715 status = mpu_status(scp);
716 if ((status & MPU_OUTPUTBUSY) != 0)
717 /* The interface is busy. */
718 return (EAGAIN);
719
720 mpu_writeport(scp, MPU_DATAPORT, value);
721
722 return (0);
723 }
724
725 /* Reads from a port. */
726 static u_int
727 mpu_readport(sc_p scp, int off)
728 {
729 return bus_space_read_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off) & 0xff;
730 }
731
732 /* Writes to a port. */
733 static void
734 mpu_writeport(sc_p scp, int off, u_int8_t value)
735 {
736 bus_space_write_1(rman_get_bustag(scp->io), rman_get_bushandle(scp->io), off, value);
737 }
738
739 /* Allocates resources. */
740 static int
741 mpu_allocres(sc_p scp, device_t dev)
742 {
743 if (scp->io == NULL) {
744 scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
745 if (scp->io == NULL)
746 return (1);
747 }
748 if (scp->irq == NULL && !(device_get_flags(dev) & MPU_DF_NO_IRQ)) {
749 if (scp->irq_val == 0)
750 scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &scp->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
751 else
752 scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &scp->irq_rid, scp->irq_val, scp->irq_val, 1, RF_ACTIVE | RF_SHAREABLE);
753 if (scp->irq == NULL)
754 return (1);
755 }
756
757 return (0);
758 }
759
760 /* Releases resources. */
761 static void
762 mpu_releaseres(sc_p scp, device_t dev)
763 {
764 if (scp->irq != NULL) {
765 bus_release_resource(dev, SYS_RES_IRQ, scp->irq_rid, scp->irq);
766 scp->irq = NULL;
767 }
768 if (scp->io != NULL) {
769 bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, scp->io);
770 scp->io = NULL;
771 }
772 }
773
774 static device_method_t mpu_methods[] = {
775 /* Device interface */
776 DEVMETHOD(device_probe , mpu_probe ),
777 DEVMETHOD(device_attach, mpu_attach),
778
779 { 0, 0 },
780 };
781
782 static driver_t mpu_driver = {
783 "midi",
784 mpu_methods,
785 sizeof(struct mpu_softc),
786 };
787
788 DRIVER_MODULE(mpu, isa, mpu_driver, midi_devclass, 0, 0);
789
790 static device_method_t mpusbc_methods[] = {
791 /* Device interface */
792 DEVMETHOD(device_probe , mpusbc_probe ),
793 DEVMETHOD(device_attach, mpusbc_attach),
794
795 { 0, 0 },
796 };
797
798 static driver_t mpusbc_driver = {
799 "midi",
800 mpusbc_methods,
801 sizeof(struct mpu_softc),
802 };
803
804 DRIVER_MODULE(mpusbc, sbc, mpusbc_driver, midi_devclass, 0, 0);
Cache object: 7d901c11521b38a72feebf23d074d7ea
|