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.0/sys/dev/sound/isa/mpu.c 93818 2002-04-04 21:03:38Z jhb $
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/sio/sioreg.h>
46 #include <dev/ic/ns16550.h>
47
48 static devclass_t midi_devclass;
49
50 #ifndef DDB
51 #undef DDB
52 #define DDB(x)
53 #endif /* DDB */
54
55 #define MPU_DATAPORT 0
56 #define MPU_CMDPORT 1
57 #define MPU_STATPORT 1
58
59 #define MPU_RESET 0xff
60 #define MPU_UART 0x3f
61 #define MPU_ACK 0xfe
62
63 #define MPU_STATMASK 0xc0
64 #define MPU_OUTPUTBUSY 0x40
65 #define MPU_INPUTBUSY 0x80
66
67 #define MPU_TRYDATA 50
68 #define MPU_DELAY 25000
69
70 /* Device flag. */
71 #define MPU_DF_NO_IRQ 1
72
73 extern synthdev_info midisynth_op_desc;
74
75 /* PnP IDs */
76 static struct isa_pnp_id mpu_ids[] = {
77 {0x01200001, "@H@2001 Midi Interface"}, /* @H@2001 */
78 {0x01100001, "@H@1001 Midi Interface"}, /* @H@1001 */
79 #if notdef
80 /* TODO: write bridge driver for these devices */
81 {0x0000630e, "CSC0000 Midi Interface"}, /* CSC0000 */
82 {0x2100a865, "YMH0021 Midi Interface"}, /* YMH0021 */
83 {0x80719304, "ADS7180 Midi Interface"}, /* ADS7180 */
84 {0x0300561e, "GRV0003 Midi Interface"}, /* GRV0003 */
85 #endif
86 };
87
88 /* These are the synthesizer and the midi interface information. */
89 static struct synth_info mpu_synthinfo = {
90 "MPU401 MIDI",
91 0,
92 SYNTH_TYPE_MIDI,
93 0,
94 0,
95 128,
96 128,
97 128,
98 SYNTH_CAP_INPUT,
99 };
100
101 static struct midi_info mpu_midiinfo = {
102 "MPU401 MIDI",
103 0,
104 0,
105 0,
106 };
107
108 /*
109 * These functions goes into mpu_op_desc to get called
110 * from sound.c.
111 */
112
113 static int mpu_probe(device_t dev);
114 static int mpu_probe1(device_t dev);
115 static int mpu_probe2(device_t dev);
116 static int mpu_attach(device_t dev);
117 static int mpusbc_probe(device_t dev);
118 static int mpusbc_attach(device_t dev);
119
120 static d_ioctl_t mpu_ioctl;
121 static driver_intr_t mpu_intr;
122 static midi_callback_t mpu_callback;
123
124 /* Here is the parameter structure per a device. */
125 struct mpu_softc {
126 device_t dev; /* device information */
127 mididev_info *devinfo; /* midi device information */
128
129 struct mtx mtx; /* Mutex to protect the device. */
130
131 struct resource *io; /* Base of io port */
132 int io_rid; /* Io resource ID */
133 u_long irq_val; /* Irq value */
134 struct resource *irq; /* Irq */
135 int irq_rid; /* Irq resource ID */
136 void *ih; /* Interrupt cookie */
137
138 int fflags; /* File flags */
139 };
140
141 typedef struct mpu_softc *sc_p;
142
143 /* These functions are local. */
144 static void mpu_startplay(sc_p scp);
145 static void mpu_xmit(sc_p scp);
146 static int mpu_resetmode(sc_p scp);
147 static int mpu_uartmode(sc_p scp);
148 static int mpu_waitack(sc_p scp);
149 static int mpu_status(sc_p scp);
150 static int mpu_command(sc_p scp, u_int8_t value);
151 static int mpu_readdata(sc_p scp, u_int8_t *value);
152 static int mpu_writedata(sc_p scp, u_int8_t value);
153 static u_int mpu_readport(sc_p scp, int off);
154 static void mpu_writeport(sc_p scp, int off, u_int8_t value);
155 static int mpu_allocres(sc_p scp, device_t dev);
156 static void mpu_releaseres(sc_p scp, device_t dev);
157
158 /*
159 * This is the device descriptor for the midi device.
160 */
161 static mididev_info mpu_op_desc = {
162 "MPU401 midi",
163
164 SNDCARD_MPU401,
165
166 NULL,
167 NULL,
168 mpu_ioctl,
169
170 mpu_callback,
171
172 MIDI_BUFFSIZE, /* Queue Length */
173
174 0, /* XXX This is not an *audio* device! */
175 };
176
177 /*
178 * Here are the main functions to interact to the user process.
179 */
180
181 static int
182 mpu_probe(device_t dev)
183 {
184 sc_p scp;
185 int ret;
186
187 /* Check isapnp ids */
188 if (isa_get_logicalid(dev) != 0)
189 return (ISA_PNP_PROBE(device_get_parent(dev), dev, mpu_ids));
190
191 scp = device_get_softc(dev);
192
193 device_set_desc(dev, mpu_op_desc.name);
194 bzero(scp, sizeof(*scp));
195
196 scp->io_rid = 0;
197 ret = mpu_probe1(dev);
198 if (ret != 0)
199 return (ret);
200 ret = mpu_probe2(dev);
201 if (ret != 0)
202 return (ret);
203
204 return (0);
205 }
206
207 /*
208 * Make sure this is an MPU401, not an 16550 uart.
209 * Called only for non-pnp devices.
210 */
211 static int
212 mpu_probe1(device_t dev)
213 {
214 sc_p scp;
215 int iir;
216 struct resource *io;
217
218 scp = device_get_softc(dev);
219
220 /*
221 * If an MPU401 is ready to both input and output,
222 * the status register value is zero, which may
223 * confuse an 16550 uart to probe as an MPU401.
224 * We read the IIR (base + 2), which is not used
225 * by an MPU401.
226 */
227 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 3, RF_ACTIVE);
228 iir = bus_space_read_1(rman_get_bustag(io), rman_get_bushandle(io), com_iir) & 0xff;
229 bus_release_resource(dev, SYS_RES_IOPORT, scp->io_rid, io);
230 if ((iir & ~(IIR_IMASK | IIR_FIFO_MASK)) == 0)
231 /* Likely to be an 16550. */
232 return (ENXIO);
233
234 return (0);
235 }
236
237 /* Look up the irq. */
238 static int
239 mpu_probe2(device_t dev)
240 {
241 sc_p scp;
242 int unit, i;
243 intrmask_t irqp0, irqp1;
244
245 scp = device_get_softc(dev);
246 unit = device_get_unit(dev);
247
248 scp->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &scp->io_rid, 0, ~0, 2, RF_ACTIVE);
249 if (scp->io == NULL)
250 return (ENXIO);
251
252 MIDI_DEBUG(printf("mpu%d: probing.\n", unit));
253
254 /* Reset the interface. */
255 if (mpu_resetmode(scp) != 0 || mpu_waitack(scp) != 0) {
256 printf("mpu%d: reset failed.\n", unit);
257 mpu_releaseres(scp, dev);
258 return (ENXIO);
259 }
260
261 /*
262 * At this point, we are likely to have an interface.
263 *
264 * Switching the interface to uart mode gives us an interrupt.
265 * We can make use of it to determine the irq.
266 * Idea-stolen-from: sys/isa/sio.c:sioprobe()
267 */
268
269 critical_enter();
270
271 /*
272 * See the initial irq. We have to do this now,
273 * otherwise a midi module/instrument might send
274 * an active sensing, to mess up the irq.
275 */
276 irqp0 = isa_irq_pending();
277 irqp1 = 0;
278
279 /* Switch to uart mode. */
280 if (mpu_uartmode(scp) != 0) {
281 critical_exit();
282 printf("mpu%d: mode switching failed.\n", unit);
283 mpu_releaseres(scp, dev);
284 return (ENXIO);
285 }
286
287 if (device_get_flags(dev) & MPU_DF_NO_IRQ) {
288 irqp0 = irqp1 = 0;
289 goto no_irq;
290 }
291
292 /* See which irq we have now. */
293 for (i = 0 ; i < MPU_TRYDATA ; i++) {
294 DELAY(MPU_DELAY);
295 irqp1 = isa_irq_pending();
296 if (irqp1 != irqp0)
297 break;
298 }
299 if (irqp1 == irqp0) {
300 critical_exit();
301 printf("mpu%d: switching the mode gave no interrupt.\n", unit);
302 mpu_releaseres(scp, dev);
303 return (ENXIO);
304 }
305
306 no_irq:
307 /* Wait to see an ACK. */
308 if (mpu_waitack(scp) != 0) {
309 critical_exit();
310 printf("mpu%d: not acked.\n", unit);
311 mpu_releaseres(scp, dev);
312 return (ENXIO);
313 }
314
315 critical_exit();
316
317 if (device_get_flags(dev) & MPU_DF_NO_IRQ)
318 scp->irq_val = 0;
319 else
320 /* We have found the irq. */
321 scp->irq_val = ffs(~irqp0 & irqp1) - 1;
322
323 MIDI_DEBUG(printf("mpu%d: probed.\n", unit));
324
325 return (0);
326 }
327
328 static int
329 mpusbc_probe(device_t dev)
330 {
331 char *s;
332 sc_p scp;
333 struct sndcard_func *func;
334
335 /* The parent device has already been probed. */
336
337 func = device_get_ivars(dev);
338 if (func == NULL || func->func != SCF_MIDI)
339 return (ENXIO);
340
341 s = "SB Midi Interface";
342
343 scp = device_get_softc(dev);
344 bzero(scp, sizeof(*scp));
345 scp->io_rid = 1;
346 scp->irq_rid = 0;
347 device_set_desc(dev, s);
348 return (0);
349 }
350
351 static int
352 mpu_attach(device_t dev)
353 {
354 sc_p scp;
355 mididev_info *devinfo;
356
357 scp = device_get_softc(dev);
358
359 MIDI_DEBUG(printf("mpu: attaching.\n"));
360
361 mtx_init(&scp->mtx, "mpumid", NULL, MTX_DEF);
362
363 /* Allocate the resources, switch to uart mode. */
364 if (mpu_allocres(scp, dev) || mpu_uartmode(scp)) {
365 mpu_releaseres(scp, dev);
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 mtx_destroy(&scp->mtx);
773 }
774
775 static device_method_t mpu_methods[] = {
776 /* Device interface */
777 DEVMETHOD(device_probe , mpu_probe ),
778 DEVMETHOD(device_attach, mpu_attach),
779
780 { 0, 0 },
781 };
782
783 static driver_t mpu_driver = {
784 "midi",
785 mpu_methods,
786 sizeof(struct mpu_softc),
787 };
788
789 DRIVER_MODULE(mpu, isa, mpu_driver, midi_devclass, 0, 0);
790
791 static device_method_t mpusbc_methods[] = {
792 /* Device interface */
793 DEVMETHOD(device_probe , mpusbc_probe ),
794 DEVMETHOD(device_attach, mpusbc_attach),
795
796 { 0, 0 },
797 };
798
799 static driver_t mpusbc_driver = {
800 "midi",
801 mpusbc_methods,
802 sizeof(struct mpu_softc),
803 };
804
805 DRIVER_MODULE(mpusbc, sbc, mpusbc_driver, midi_devclass, 0, 0);
Cache object: ddf6f6581ca78f94a9bc1c2bbe13eb94
|