2 * Copyright (C) by Hannu Savolainen 1993-1997
6 * Initialization code for OPTi MAD16 compatible audio chips. Including
8 * OPTi 82C928 MAD16 (replaced by C929)
10 * OAK OTI-605 Mozart (later version with MPU401 Midi)
11 * OPTi 82C929 MAD16 Pro
15 * These audio interface chips don't produce sound themselves. They just
16 * connect some other components (OPL-[234] and a WSS compatible codec)
17 * to the PC bus and perform I/O, DMA and IRQ address decoding. There is
18 * also a UART for the MPU-401 mode (not 82C928/Mozart).
19 * The Mozart chip appears to be compatible with the 82C928, although later
20 * issues of the card, using the OTI-605 chip, have an MPU-401 compatible Midi
21 * port. This port is configured differently to that of the OPTi audio chips.
25 * Alan Cox Clean up, added module selections.
27 * A. Wik Added support for Opti924 PnP.
28 * Improved debugging support. 16-May-1998
29 * Fixed bug. 16-Jun-1998
31 * Torsten Duwe Made Opti924 PnP support non-destructive
34 * Paul Grayson Added support for Midi on later Mozart cards.
36 * Christoph Hellwig Adapted to module_init/module_exit.
37 * Arnaldo C. de Melo got rid of attach_uart401 21-Sep-2000
39 * Pavel Rabel Clean up Nov-2000
42 #include <linux/config.h>
43 #include <linux/init.h>
44 #include <linux/module.h>
45 #include <linux/gameport.h>
46 #include <linux/spinlock.h>
47 #include "sound_config.h"
53 static int mad16_conf
;
54 static int mad16_cdsel
;
55 static struct gameport
*gameport
;
56 static DEFINE_SPINLOCK(lock
);
67 * The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations).
68 * All ports are inactive by default. They can be activated by
69 * writing 0xE2 or 0xE3 to the password register. The password is valid
70 * only until the next I/O read or write.
72 * 82C930 uses 0xE4 as the password and indirect addressing to access
73 * the config registers.
76 #define MC0_PORT 0xf8c /* Dummy port */
77 #define MC1_PORT 0xf8d /* SB address, CD-ROM interface type, joystick */
78 #define MC2_PORT 0xf8e /* CD-ROM address, IRQ, DMA, plus OPL4 bit */
79 #define MC3_PORT 0xf8f
80 #define PASSWD_REG 0xf8f
81 #define MC4_PORT 0xf90
82 #define MC5_PORT 0xf91
83 #define MC6_PORT 0xf92
84 #define MC7_PORT 0xf93
85 #define MC8_PORT 0xf94
86 #define MC9_PORT 0xf95
87 #define MC10_PORT 0xf96
88 #define MC11_PORT 0xf97
89 #define MC12_PORT 0xf98
91 static int board_type
= C928
;
93 static int *mad16_osp
;
94 static int c931_detected
; /* minor differences from C930 */
95 static char c924pnp
; /* " " " C924 */
96 static int debug
; /* debugging output */
101 #define DDB(x) do {if (debug) x;} while (0)
103 static unsigned char mad_read(int port
)
108 spin_lock_irqsave(&lock
,flags
);
110 switch (board_type
) /* Output password */
114 outb((0xE2), PASSWD_REG
);
118 outb((0xE3), PASSWD_REG
);
122 /* outb(( 0xE4), PASSWD_REG); */
126 /* the c924 has its ports relocated by -128 if
127 PnP is enabled -aw */
129 outb((0xE5), PASSWD_REG
); else
130 outb((0xE5), PASSWD_REG
- 0x80);
134 if (board_type
== C930
)
136 outb((port
- MC0_PORT
), 0xe0e); /* Write to index reg */
137 tmp
= inb(0xe0f); /* Read from data reg */
141 tmp
= inb(port
); else
142 tmp
= inb(port
-0x80);
143 spin_unlock_irqrestore(&lock
,flags
);
148 static void mad_write(int port
, int value
)
152 spin_lock_irqsave(&lock
,flags
);
154 switch (board_type
) /* Output password */
158 outb((0xE2), PASSWD_REG
);
162 outb((0xE3), PASSWD_REG
);
166 /* outb(( 0xE4), PASSWD_REG); */
171 outb((0xE5), PASSWD_REG
); else
172 outb((0xE5), PASSWD_REG
- 0x80);
176 if (board_type
== C930
)
178 outb((port
- MC0_PORT
), 0xe0e); /* Write to index reg */
179 outb(((unsigned char) (value
& 0xff)), 0xe0f);
183 outb(((unsigned char) (value
& 0xff)), port
); else
184 outb(((unsigned char) (value
& 0xff)), port
-0x80);
185 spin_unlock_irqrestore(&lock
,flags
);
188 static int __init
detect_c930(void)
190 unsigned char tmp
= mad_read(MC1_PORT
);
192 if ((tmp
& 0x06) != 0x06)
194 DDB(printk("Wrong C930 signature (%x)\n", tmp
));
197 mad_write(MC1_PORT
, 0);
199 if (mad_read(MC1_PORT
) != 0x06)
201 DDB(printk("Wrong C930 signature2 (%x)\n", tmp
));
204 mad_write(MC1_PORT
, tmp
); /* Restore bits */
206 mad_write(MC7_PORT
, 0);
207 if ((tmp
= mad_read(MC7_PORT
)) != 0)
209 DDB(printk("MC7 not writable (%x)\n", tmp
));
212 mad_write(MC7_PORT
, 0xcb);
213 if ((tmp
= mad_read(MC7_PORT
)) != 0xcb)
215 DDB(printk("MC7 not writable2 (%x)\n", tmp
));
219 tmp
= mad_read(MC0_PORT
+18);
220 if (tmp
== 0xff || tmp
== 0x00)
222 /* We probably have a C931 */
223 DDB(printk("Detected C931 config=0x%02x\n", tmp
));
227 * We cannot configure the chip if it is in PnP mode.
228 * If we have a CSN assigned (bit 8 in MC13) we first try
229 * a software reset, then a software power off, finally
230 * Clearing PnP mode. The last option is not
233 if ((mad_read(MC0_PORT
+13) & 0x80) == 0)
237 mad_write(MC9_PORT
, 0x02);
238 mad_write(MC9_PORT
, 0x00);
240 if ((mad_read(MC0_PORT
+13) & 0x80) == 0)
243 /* Power off, and on again */
244 mad_write(MC9_PORT
, 0xc2);
245 mad_write(MC9_PORT
, 0xc0);
247 if ((mad_read(MC0_PORT
+13) & 0x80) == 0)
251 /* Force off PnP mode. This is not recommended because
252 * the PnP bios will not recognize the chip on the next
253 * warm boot and may assignd different resources to other
256 mad_write(MC0_PORT
+17, 0x04);
261 static int __init
detect_mad16(void)
263 unsigned char tmp
, tmp2
, bit
;
267 * Check that reading a register doesn't return bus float (0xff)
268 * when the card is accessed using password. This may fail in case
269 * the card is in low power mode. Normally at least the power saving
270 * mode bit should be 0.
273 if ((tmp
= mad_read(MC1_PORT
)) == 0xff)
275 DDB(printk("MC1_PORT returned 0xff\n"));
278 for (i
= 0xf8d; i
<= 0xf98; i
++)
280 DDB(printk("Port %0x (init value) = %0x\n", i
, mad_read(i
)));
282 DDB(printk("Port %0x (init value) = %0x\n", i
-0x80, mad_read(i
)));
284 if (board_type
== C930
)
285 return detect_c930();
288 * Now check that the gate is closed on first I/O after writing
289 * the password. (This is how a MAD16 compatible card works).
292 if ((tmp2
= inb(MC1_PORT
)) == tmp
) /* It didn't close */
294 DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2
));
298 bit
= (c924pnp
) ? 0x20 : 0x80;
299 port
= (c924pnp
) ? MC2_PORT
: MC1_PORT
;
301 tmp
= mad_read(port
);
302 mad_write(port
, tmp
^ bit
); /* Toggle a bit */
303 if ((tmp2
= mad_read(port
)) != (tmp
^ bit
)) /* Compare the bit */
305 mad_write(port
, tmp
); /* Restore */
306 DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp
, tmp2
));
309 mad_write(port
, tmp
); /* Restore */
310 return 1; /* Bingo */
313 static int __init
wss_init(struct address_info
*hw_config
)
316 * Check if the IO port returns valid signature. The original MS Sound
317 * system returns 0x04 while some cards (AudioTrix Pro for example)
321 if ((inb(hw_config
->io_base
+ 3) & 0x3f) != 0x04 &&
322 (inb(hw_config
->io_base
+ 3) & 0x3f) != 0x00)
324 DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config
->io_base
, inb(hw_config
->io_base
+ 3)));
328 * Check that DMA0 is not in use with a 8 bit board.
330 if (hw_config
->dma
== 0 && inb(hw_config
->io_base
+ 3) & 0x80)
332 printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
335 if (hw_config
->irq
> 9 && inb(hw_config
->io_base
+ 3) & 0x80)
336 printk(KERN_ERR
"MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config
->irq
);
340 static void __init
init_c930(struct address_info
*hw_config
, int base
)
342 unsigned char cfg
= 0;
344 cfg
|= (0x0f & mad16_conf
);
348 /* Bit 0 has reversd meaning. Bits 1 and 2 sese
350 Support only IDE cdrom. IDE port programmed
352 cfg
= (cfg
& 0x09) ^ 0x07;
355 mad_write(MC1_PORT
, cfg
);
357 /* MC2 is CD configuration. Don't touch it. */
359 mad_write(MC3_PORT
, 0); /* Disable SB mode IRQ and DMA */
361 /* bit 2 of MC4 reverses it's meaning between the C930
363 cfg
= c931_detected
? 0x04 : 0x00;
365 if(mad16_cdsel
& 0x20)
366 mad_write(MC4_PORT
, 0x62|cfg
); /* opl4 */
368 mad_write(MC4_PORT
, 0x52|cfg
); /* opl3 */
370 mad_write(MC5_PORT
, 0x3C); /* Init it into mode2 */
371 mad_write(MC6_PORT
, 0x02); /* Enable WSS, Disable MPU and SB */
372 mad_write(MC7_PORT
, 0xCB);
373 mad_write(MC10_PORT
, 0x11);
376 static int __init
chip_detect(void)
381 * Then try to detect with the old password
385 DDB(printk("Detect using password = 0xE5\n"));
387 if (detect_mad16()) {
393 DDB(printk("Detect using password = 0xE2\n"));
399 if (((model
= mad_read(MC3_PORT
)) & 0x03) == 0x03) {
400 DDB(printk("mad16.c: Mozart detected\n"));
403 DDB(printk("mad16.c: 82C928 detected???\n"));
411 DDB(printk("Detect using password = 0xE3\n"));
415 DDB(printk("mad16.c: 82C929 detected\n"));
419 if (inb(PASSWD_REG
) != 0xff)
423 * First relocate MC# registers to 0xe0e/0xe0f, disable password
426 outb((0xE4), PASSWD_REG
);
427 outb((0x80), PASSWD_REG
);
431 DDB(printk("Detect using password = 0xE4\n"));
433 for (i
= 0xf8d; i
<= 0xf93; i
++)
434 DDB(printk("port %03x = %02x\n", i
, mad_read(i
)));
437 DDB(printk("mad16.c: 82C930 detected\n"));
441 /* The C931 has the password reg at F8D */
444 DDB(printk("Detect using password = 0xE4 for C931\n"));
446 if (detect_mad16()) {
452 DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
453 if (detect_mad16()) {
454 DDB(printk("mad16.c: 82C924 PnP detected\n"));
463 static int __init
probe_mad16(struct address_info
*hw_config
)
467 unsigned char cs4231_mode
= 0;
473 static char dma_bits
[4] = {
477 int config_port
= hw_config
->io_base
+ 0, version_port
= hw_config
->io_base
+ 3;
478 int dma
= hw_config
->dma
, dma2
= hw_config
->dma2
;
479 unsigned char dma2_bit
= 0;
481 struct resource
*ports
;
483 mad16_osp
= hw_config
->osp
;
485 switch (hw_config
->io_base
) {
499 printk(KERN_ERR
"MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config
->io_base
);
503 if (dma
!= 0 && dma
!= 1 && dma
!= 3) {
504 printk(KERN_ERR
"MSS: Bad DMA %d\n", dma
);
509 * Check that all ports return 0xff (bus float) when no password
510 * is written to the password register.
513 DDB(printk("--- Detecting MAD16 / Mozart ---\n"));
517 switch (hw_config
->irq
) {
530 case 5: /* Also IRQ5 is possible on C930 */
531 if (board_type
== C930
|| c924pnp
) {
536 printk(KERN_ERR
"MAD16/Mozart: Bad IRQ %d\n", hw_config
->irq
);
540 ports
= request_region(hw_config
->io_base
+ 4, 4, "ad1848");
542 printk(KERN_ERR
"MSS: I/O port conflict\n");
545 if (!request_region(hw_config
->io_base
, 4, "mad16 WSS config")) {
546 release_region(hw_config
->io_base
+ 4, 4);
547 printk(KERN_ERR
"MSS: I/O port conflict\n");
551 if (board_type
== C930
) {
552 init_c930(hw_config
, base
);
556 for (i
= 0xf8d; i
<= 0xf93; i
++) {
558 DDB(printk("port %03x = %02x\n", i
, mad_read(i
)));
560 DDB(printk("port %03x = %02x\n", i
-0x80, mad_read(i
)));
564 * Set the WSS address
567 tmp
= (mad_read(MC1_PORT
) & 0x0f) | 0x80; /* Enable WSS, Disable SB */
568 tmp
|= base
<< 4; /* WSS port select bits */
571 * Set optional CD-ROM and joystick settings.
575 tmp
|= (mad16_conf
& 0x0f); /* CD-ROM and joystick bits */
576 mad_write(MC1_PORT
, tmp
);
579 mad_write(MC2_PORT
, tmp
);
580 mad_write(MC3_PORT
, 0xf0); /* Disable SB */
582 if (board_type
== C924
) /* Specific C924 init values */
584 mad_write(MC4_PORT
, 0xA0);
585 mad_write(MC5_PORT
, 0x05);
586 mad_write(MC6_PORT
, 0x03);
588 if (!ad1848_detect(ports
, &ad_flags
, mad16_osp
))
591 if (ad_flags
& (AD_F_CS4231
| AD_F_CS4248
))
592 cs4231_mode
= 0x02; /* CS4248/CS4231 sync delay switch */
594 if (board_type
== C929
)
596 mad_write(MC4_PORT
, 0xa2);
597 mad_write(MC5_PORT
, 0xA5 | cs4231_mode
);
598 mad_write(MC6_PORT
, 0x03); /* Disable MPU401 */
602 mad_write(MC4_PORT
, 0x02);
603 mad_write(MC5_PORT
, 0x30 | cs4231_mode
);
606 for (i
= 0xf8d; i
<= 0xf93; i
++) {
608 DDB(printk("port %03x after init = %02x\n", i
, mad_read(i
)));
610 DDB(printk("port %03x after init = %02x\n", i
-0x80, mad_read(i
)));
615 if (!ad1848_detect(ports
, &ad_flags
, mad16_osp
))
618 if (!wss_init(hw_config
))
622 * Set the IRQ and DMA addresses.
625 outb((bits
| 0x40), config_port
);
626 if ((inb(version_port
) & 0x40) == 0)
627 printk(KERN_ERR
"[IRQ Conflict?]\n");
630 * Handle the capture DMA channel
633 if (ad_flags
& AD_F_CS4231
&& dma2
!= -1 && dma2
!= dma
)
635 if (!((dma
== 0 && dma2
== 1) ||
636 (dma
== 1 && dma2
== 0) ||
637 (dma
== 3 && dma2
== 0)))
638 { /* Unsupported combination. Try to swap channels */
644 if ((dma
== 0 && dma2
== 1) || (dma
== 1 && dma2
== 0) ||
645 (dma
== 3 && dma2
== 0))
647 dma2_bit
= 0x04; /* Enable capture DMA */
651 printk("MAD16: Invalid capture DMA\n");
657 outb((bits
| dma_bits
[dma
] | dma2_bit
), config_port
); /* Write IRQ+DMA setup */
659 hw_config
->slots
[0] = ad1848_init("mad16 WSS", ports
,
668 release_region(hw_config
->io_base
+ 4, 4);
669 release_region(hw_config
->io_base
, 4);
673 static int __init
probe_mad16_mpu(struct address_info
*hw_config
)
677 if (board_type
< C929
) /* Early chip. No MPU support. Just SB MIDI */
680 #ifdef CONFIG_MAD16_OLDCARD
682 tmp
= mad_read(MC3_PORT
);
685 * MAD16 SB base is defined by the WSS base. It cannot be changed
687 * Ignore configured I/O base. Use the active setting.
690 if (mad_read(MC1_PORT
) & 0x20)
691 hw_config
->io_base
= 0x240;
693 hw_config
->io_base
= 0x220;
695 switch (hw_config
->irq
)
698 tmp
= (tmp
& 0x3f) | 0x80;
704 tmp
= (tmp
& 0x3f) | 0x40;
707 printk(KERN_ERR
"mad16/Mozart: Invalid MIDI IRQ\n");
711 mad_write(MC3_PORT
, tmp
| 0x04);
712 hw_config
->driver_use_1
= SB_MIDI_ONLY
;
713 if (!request_region(hw_config
->io_base
, 16, "soundblaster"))
715 if (!sb_dsp_detect(hw_config
, 0, 0, NULL
)) {
716 release_region(hw_config
->io_base
, 16);
720 if (mad_read(MC1_PORT
) & 0x20)
721 hw_config
->io_base
= 0x240;
723 hw_config
->io_base
= 0x220;
725 hw_config
->name
= "Mad16/Mozart";
726 sb_dsp_init(hw_config
, THIS_MODULE
);
729 /* assuming all later Mozart cards are identified as
730 * either 82C928 or Mozart. If so, following code attempts
731 * to set MPU register. TODO - add probing
734 tmp
= mad_read(MC8_PORT
);
736 switch (hw_config
->irq
)
754 printk(KERN_ERR
"mad16/MOZART: invalid mpu_irq\n");
758 switch (hw_config
->io_base
)
773 printk(KERN_ERR
"mad16/MOZART: invalid mpu_io\n");
777 mad_write(MC8_PORT
, tmp
); /* write MPU port parameters */
781 tmp
= mad_read(MC6_PORT
) & 0x83;
782 tmp
|= 0x80; /* MPU-401 enable */
784 /* Set the MPU base bits */
786 switch (hw_config
->io_base
)
801 printk(KERN_ERR
"MAD16: Invalid MIDI port 0x%x\n", hw_config
->io_base
);
805 /* Set the MPU IRQ bits */
807 switch (hw_config
->irq
)
822 printk(KERN_ERR
"MAD16: Invalid MIDI IRQ %d\n", hw_config
->irq
);
826 mad_write(MC6_PORT
, tmp
); /* Write MPU401 config */
828 #ifndef CONFIG_MAD16_OLDCARD
831 hw_config
->driver_use_1
= SB_MIDI_ONLY
;
832 hw_config
->name
= "Mad16/Mozart";
833 return probe_uart401(hw_config
, THIS_MODULE
);
836 static void __exit
unload_mad16(struct address_info
*hw_config
)
838 ad1848_unload(hw_config
->io_base
+ 4,
842 release_region(hw_config
->io_base
, 4);
843 sound_unload_audiodev(hw_config
->slots
[0]);
846 static void __exit
unload_mad16_mpu(struct address_info
*hw_config
)
848 #ifdef CONFIG_MAD16_OLDCARD
849 if (board_type
< C929
) /* Early chip. No MPU support. Just SB MIDI */
851 sb_dsp_unload(hw_config
, 0);
856 unload_uart401(hw_config
);
859 static struct address_info cfg
;
860 static struct address_info cfg_mpu
;
862 static int found_mpu
;
864 static int __initdata mpu_io
= 0;
865 static int __initdata mpu_irq
= 0;
866 static int __initdata io
= -1;
867 static int __initdata dma
= -1;
868 static int __initdata dma16
= -1; /* Set this for modules that need it */
869 static int __initdata irq
= -1;
870 static int __initdata cdtype
= 0;
871 static int __initdata cdirq
= 0;
872 static int __initdata cdport
= 0x340;
873 static int __initdata cddma
= -1;
874 static int __initdata opl4
= 0;
875 static int __initdata joystick
= 0;
877 module_param(mpu_io
, int, 0);
878 module_param(mpu_irq
, int, 0);
879 module_param(io
, int, 0);
880 module_param(dma
, int, 0);
881 module_param(dma16
, int, 0);
882 module_param(irq
, int, 0);
883 module_param(cdtype
, int, 0);
884 module_param(cdirq
, int, 0);
885 module_param(cdport
, int, 0);
886 module_param(cddma
, int, 0);
887 module_param(opl4
, int, 0);
888 module_param(joystick
, bool, 0);
889 module_param(debug
, bool, 0644);
891 static int __initdata dma_map
[2][8] =
893 {0x03, -1, -1, -1, -1, 0x00, 0x01, 0x02},
894 {0x03, -1, 0x01, 0x00, -1, -1, -1, -1}
897 static int __initdata irq_map
[16] =
901 -1, 0x10, 0x14, 0x18,
905 static int __devinit
mad16_register_gameport(int io_port
)
907 if (!request_region(io_port
, 1, "mad16 gameport")) {
908 printk(KERN_ERR
"mad16: gameport address 0x%#x already in use\n", io_port
);
912 gameport
= gameport_allocate_port();
914 printk(KERN_ERR
"mad16: can not allocate memory for gameport\n");
915 release_region(io_port
, 1);
919 gameport_set_name(gameport
, "MAD16 Gameport");
920 gameport_set_phys(gameport
, "isa%04x/gameport0", io_port
);
921 gameport
->io
= io_port
;
923 gameport_register_port(gameport
);
928 static int __devinit
init_mad16(void)
932 printk(KERN_INFO
"MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
934 printk(KERN_INFO
"CDROM ");
942 printk("Sony CDU31A");
944 if(cddma
== -1) cddma
= 3;
949 if(cddma
== -1) cddma
= 5;
952 printk("Panasonic Lasermate");
954 if(cddma
== -1) cddma
= 3;
957 printk("Secondary IDE");
959 if(cddma
== -1) cddma
= 5;
962 printk("Primary IDE");
964 if(cddma
== -1) cddma
= 5;
968 printk(KERN_ERR
"Invalid CDROM type\n");
973 * Build the config words
976 mad16_conf
= (joystick
^ 1) | cdtype
;
982 if (cddma
> 7 || cddma
< 0 || dma_map
[dmatype
][cddma
] == -1)
985 printk(KERN_ERR
"Invalid CDROM DMA\n");
989 printk(", DMA %d", cddma
);
995 else if (cdirq
< 0 || cdirq
> 15 || irq_map
[cdirq
] == -1)
997 printk(", invalid IRQ (disabling)");
1000 else printk(", IRQ %d", cdirq
);
1002 mad16_cdsel
|= dma_map
[dmatype
][cddma
];
1009 mad16_cdsel
|= 0x00;
1012 mad16_cdsel
|= 0x40;
1015 mad16_cdsel
|= 0x80;
1018 mad16_cdsel
|= 0xC0;
1021 printk(KERN_ERR
"Unknown CDROM I/O base %d\n", cdport
);
1025 mad16_cdsel
|= irq_map
[cdirq
];
1035 if (cfg
.io_base
== -1 || cfg
.dma
== -1 || cfg
.irq
== -1) {
1036 printk(KERN_ERR
"I/O, DMA and irq are mandatory\n");
1040 if (!request_region(MC0_PORT
, 12, "mad16"))
1043 if (!probe_mad16(&cfg
)) {
1044 release_region(MC0_PORT
, 12);
1048 cfg_mpu
.io_base
= mpu_io
;
1049 cfg_mpu
.irq
= mpu_irq
;
1051 found_mpu
= probe_mad16_mpu(&cfg_mpu
);
1054 mad16_register_gameport(0x201);
1059 static void __exit
cleanup_mad16(void)
1062 unload_mad16_mpu(&cfg_mpu
);
1064 /* the gameport was initialized so we must free it up */
1065 gameport_unregister_port(gameport
);
1067 release_region(0x201, 1);
1070 release_region(MC0_PORT
, 12);
1073 module_init(init_mad16
);
1074 module_exit(cleanup_mad16
);
1077 static int __init
setup_mad16(char *str
)
1082 str
= get_options(str
, ARRAY_SIZE(ints
), ints
);
1095 __setup("mad16=", setup_mad16
);
1097 MODULE_LICENSE("GPL");