File:  [DragonFly] / src / sys / dev / sound / isa / i386 / Attic / soundcard.c
Revision 1.6: download - view: text, annotated - select for diffs
Thu May 13 23:49:20 2004 UTC (10 years, 7 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*
    2:  * sound/386bsd/soundcard.c
    3:  * 
    4:  * Soundcard driver for 386BSD.
    5:  * 
    6:  * Copyright by Hannu Savolainen 1993
    7:  * 
    8:  * Redistribution and use in source and binary forms, with or without
    9:  * modification, are permitted provided that the following conditions are
   10:  * met: 1. Redistributions of source code must retain the above copyright
   11:  * notice, this list of conditions and the following disclaimer. 2.
   12:  * Redistributions in binary form must reproduce the above copyright notice,
   13:  * this list of conditions and the following disclaimer in the documentation
   14:  * and/or other materials provided with the distribution.
   15:  * 
   16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
   17:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   20:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   23:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26:  * SUCH DAMAGE.
   27:  *
   28:  * $FreeBSD: src/sys/i386/isa/sound/soundcard.c,v 1.87 1999/12/20 18:05:01 eivind Exp $
   29:  * $DragonFly: src/sys/dev/sound/isa/i386/soundcard.c,v 1.6 2004/05/13 23:49:20 dillon Exp $
   30:  *
   31:  */
   32: #include "use_snd.h"
   33: #include "sound_config.h"
   34: #if NSND > 0	/* from "snd.h" */
   35: #include "use_uart.h"
   36: 
   37: #include <sys/select.h>
   38: #include <vm/vm.h>
   39: #include <vm/pmap.h>
   40: #include <sys/mman.h>
   41: 
   42: #include <bus/isa/i386/isa_device.h>
   43: 
   44: 
   45: /*
   46: **  Register definitions for DMA controller 1 (channels 0..3):
   47: */
   48: #define	DMA1_CHN(c)	(IO_DMA1 + 1*(2*(c)))	/* addr reg for channel c */
   49: #define	DMA1_SMSK	(IO_DMA1 + 1*10)	/* single mask register */
   50: #define	DMA1_MODE	(IO_DMA1 + 1*11)	/* mode register */
   51: #define	DMA1_FFC	(IO_DMA1 + 1*12)	/* clear first/last FF */
   52: 
   53: /*
   54: **  Register definitions for DMA controller 2 (channels 4..7):
   55: */
   56: #define	DMA2_CHN(c)	(IO_DMA2 + 2*(2*(c)))	/* addr reg for channel c */
   57: #define	DMA2_SMSK	(IO_DMA2 + 2*10)	/* single mask register */
   58: #define	DMA2_MODE	(IO_DMA2 + 2*11)	/* mode register */
   59: #define	DMA2_FFC	(IO_DMA2 + 2*12)	/* clear first/last FF */
   60: 
   61: 
   62: #define FIX_RETURN(ret) {if ((ret)<0) return -(ret); else return 0;}
   63: 
   64: static int      soundcards_installed = 0; /* Number of installed soundcards */
   65: static int      soundcard_configured = 0;
   66: 
   67: static struct fileinfo files[SND_NDEVS];
   68: struct selinfo  selinfo[SND_NDEVS >> 4];
   69: 
   70: int
   71: MIDIbuf_poll (int dev, struct fileinfo *file, int events, select_table * wait);
   72: 
   73: int
   74: audio_poll(int dev, struct fileinfo * file, int events, select_table * wait);
   75: 
   76: int
   77: sequencer_poll (int dev, struct fileinfo *file, int events, select_table * wait);
   78: 
   79: static int sndprobe    (struct isa_device *);
   80: static int sndattach   (struct isa_device *);
   81: 
   82: static d_open_t sndopen;
   83: static d_close_t sndclose;
   84: static d_ioctl_t sndioctl;
   85: static d_read_t sndread;
   86: static d_write_t sndwrite;
   87: static d_poll_t sndpoll;
   88: static d_mmap_t sndmmap;
   89: 
   90: static char     driver_name[] = "snd";
   91: 
   92: #define CDEV_MAJOR 30
   93: static struct cdevsw snd_cdevsw = {
   94: 	/* name */	driver_name,
   95: 	/* maj */	CDEV_MAJOR,
   96: 	/* flags */	0,
   97: 	/* port */	NULL,
   98: 	/* clone */	NULL,
   99: 
  100: 	/* open */	sndopen,
  101: 	/* close */	sndclose,
  102: 	/* read */	sndread,
  103: 	/* write */	sndwrite,
  104: 	/* ioctl */	sndioctl,
  105: 	/* poll */	sndpoll,
  106: 	/* mmap */	sndmmap,
  107: 	/* strategy */	nostrategy,
  108: 	/* dump */	nodump,
  109: 	/* psize */	nopsize
  110: };
  111: 
  112: 
  113: 
  114: 
  115: static void     sound_mem_init(void);
  116: 
  117: /*
  118:  * for each "device XXX" entry in the config file, we have
  119:  * a struct isa_driver which is linked into isa_devtab_null[]
  120:  *
  121:  * XXX It is a bit stupid to call the generic routine so many times and
  122:  * switch then to the specific one, but the alternative way would be
  123:  * to replicate some code in the probe/attach routines.
  124:  */
  125: 
  126: struct isa_driver opldriver = {sndprobe, sndattach, "opl"};
  127: struct isa_driver trixdriver = {sndprobe, sndattach, "trix"};
  128: struct isa_driver trixsbdriver = {sndprobe, sndattach, "trixsb"};
  129: struct isa_driver sbdriver = {sndprobe, sndattach, "sb"};
  130: struct isa_driver sbxvidriver = {sndprobe, sndattach, "sbxvi"};
  131: struct isa_driver sbmididriver = {sndprobe, sndattach, "sbmidi"};
  132: struct isa_driver awedriver    = {sndprobe, sndattach, "awe"};
  133: struct isa_driver pasdriver = {sndprobe, sndattach, "pas"};
  134: struct isa_driver mpudriver = {sndprobe, sndattach, "mpu"};
  135: struct isa_driver gusdriver = {sndprobe, sndattach, "gus"};
  136: struct isa_driver gusxvidriver = {sndprobe, sndattach, "gusxvi"};
  137: struct isa_driver gusmaxdriver = {sndprobe, sndattach, "gusmax"};
  138: struct isa_driver uartdriver = {sndprobe, sndattach, "uart"};
  139: struct isa_driver mssdriver = {sndprobe, sndattach, "mss"};
  140: struct isa_driver cssdriver = {sndprobe, sndattach, "css"};
  141: struct isa_driver sscapedriver = {sndprobe, sndattach, "sscape"};
  142: struct isa_driver sscape_mssdriver = {sndprobe, sndattach, "sscape_mss"};
  143: struct isa_driver nssdriver = {sndprobe, sndattach, "nss"};
  144: 
  145: short ipri_to_irq(u_short ipri);
  146: 
  147: static ointhand2_t sndintr;
  148: 
  149: u_long
  150: get_time(void)
  151: {
  152:     struct timeval  timecopy;
  153: 
  154:     getmicrotime(&timecopy);
  155:     return timecopy.tv_usec / (1000000 / hz) +
  156: 		(u_long) timecopy.tv_sec * hz;
  157: }
  158: 
  159: static int
  160: sndmmap( dev_t dev, vm_offset_t offset, int nprot )
  161: {
  162: 	struct dma_buffparms * dmap;
  163: 	u_int min = minor(dev) >> 4;
  164: 
  165: 	if (min > 0 ) return (-1);
  166: 
  167: 	dmap =	audio_devs[min]->dmap_out;
  168: 
  169: 	if (nprot & PROT_EXEC)
  170: 		return( -1 );
  171: 	dmap->mapping_flags |= DMA_MAP_MAPPED ;
  172: 	return( i386_btop(vtophys(dmap->raw_buf) + offset) );
  173: }
  174: 
  175: 
  176: static int
  177: sndread(dev_t dev, struct uio * buf, int flag)
  178: {
  179:     int             count = buf->uio_resid;
  180:     u_int min = minor(dev);
  181: 
  182:     FIX_RETURN(sound_read_sw(min, &files[min], buf, count));
  183: }
  184: 
  185: 
  186: static int
  187: sndwrite(dev_t dev, struct uio * buf, int flag)
  188: {
  189:     int             count = buf->uio_resid;
  190:     u_int min = minor(dev);
  191: 
  192:     FIX_RETURN(sound_write_sw(min, &files[min], buf, count));
  193: }
  194: 
  195: static int
  196: sndopen(dev_t dev, int flags, int mode, struct proc * p)
  197: {
  198:     int             retval;
  199:     struct fileinfo tmp_file;
  200:     u_int min = minor(dev);
  201: 
  202:     if (!soundcard_configured && min) {
  203: 	printf("SoundCard Error: soundcard system has not been configured\n");
  204: 	return ENODEV ;
  205:     }
  206:     tmp_file.mode = 0;
  207: 
  208:     if (flags & FREAD && flags & FWRITE)
  209: 	tmp_file.mode = OPEN_READWRITE;
  210:     else if (flags & FREAD)
  211: 	tmp_file.mode = OPEN_READ;
  212:     else if (flags & FWRITE)
  213: 	tmp_file.mode = OPEN_WRITE;
  214: 
  215:     selinfo[min >> 4].si_pid = 0;
  216:     selinfo[min >> 4].si_flags = 0;
  217:     if ((retval = sound_open_sw(min, &tmp_file)) < 0)
  218: 	FIX_RETURN(retval);
  219: 
  220:     bcopy((char *) &tmp_file, (char *) &files[min], sizeof(tmp_file));
  221: 
  222:     FIX_RETURN(retval);
  223: }
  224: 
  225: 
  226: static int
  227: sndclose(dev_t dev, int flags, int mode, struct proc * p)
  228: {
  229:     u_int min = minor(dev);
  230: 
  231:     sound_release_sw(min, &files[min]);
  232:     return 0 ;
  233: }
  234: 
  235: static int
  236: sndioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc * p)
  237: {
  238:     u_int min = minor(dev);
  239:     FIX_RETURN(sound_ioctl_sw(min, &files[min], cmd, arg));
  240: }
  241: 
  242: int
  243: sndpoll(dev_t dev, int events, struct proc * p)
  244: {
  245:     u_int min = minor(dev);
  246: 
  247:     /* printf ("snd_select(dev=%d, rw=%d, pid=%d)\n", min, rw, p->p_pid); */
  248: #ifdef ALLOW_POLL
  249:     switch (min & 0x0f) {
  250: #ifdef CONFIG_SEQUENCER
  251:     case SND_DEV_SEQ:
  252:     case SND_DEV_SEQ2:
  253: 	return sequencer_poll(min, &files[min], events, p);
  254: 	break;
  255: #endif
  256: 
  257: #ifdef CONFIG_MIDI
  258:     case SND_DEV_MIDIN:
  259: 	return MIDIbuf_poll(min, &files[min], events, p);
  260: 	break;
  261: #endif
  262: 
  263: #ifdef CONFIG_AUDIO
  264:     case SND_DEV_DSP:
  265:     case SND_DEV_DSP16:
  266:     case SND_DEV_AUDIO:
  267: 
  268: 	return audio_poll(min, &files[min], events, p);
  269: 	break;
  270: #endif
  271: 
  272:     default:
  273: 	return 0;
  274:     }
  275: 
  276: #endif	/* ALLOW_POLL */
  277:     DEB(printf("sound_ioctl(min=%d, cmd=0x%x, arg=0x%x)\n", min, cmd, arg));
  278: 
  279:     return 0 ;
  280: }
  281: 
  282: /* XXX this should become ffs(ipri), perhaps -1 lr 970705 */
  283: short
  284: ipri_to_irq(u_short ipri)
  285: {
  286:     /*
  287:      * Converts the ipri (bitmask) to the corresponding irq number
  288:      */
  289:     int             irq;
  290: 
  291:     for (irq = 0; irq < 16; irq++)
  292: 	if (ipri == (1 << irq))
  293: 	    return irq;
  294: 
  295:     return -1;		/* Invalid argument */
  296: }
  297: 
  298: static int
  299: driver_to_voxunit(struct isa_driver * driver)
  300: {
  301:     /*
  302:      * converts a sound driver pointer into the equivalent VoxWare device
  303:      * unit number
  304:      */
  305:     if (driver == &opldriver)
  306: 	return (SNDCARD_ADLIB);
  307:     else if (driver == &sbdriver)
  308: 	return (SNDCARD_SB);
  309:     else if (driver == &pasdriver)
  310: 	return (SNDCARD_PAS);
  311:     else if (driver == &gusdriver)
  312: 	return (SNDCARD_GUS);
  313:     else if (driver == &mpudriver)
  314: 	return (SNDCARD_MPU401);
  315:     else if (driver == &sbxvidriver)
  316: 	return (SNDCARD_SB16);
  317:     else if (driver == &sbmididriver)
  318: 	return (SNDCARD_SB16MIDI);
  319:     else if(driver == &awedriver)
  320: 	return(SNDCARD_AWE32);
  321:     else if (driver == &uartdriver)
  322: 	return (SNDCARD_UART6850);
  323:     else if (driver == &gusdriver)
  324: 	return (SNDCARD_GUS16);
  325:     else if (driver == &mssdriver)
  326: 	return (SNDCARD_MSS);
  327:     else if (driver == &cssdriver)
  328: 	return (SNDCARD_CS4232);
  329:     else if (driver == &sscapedriver)
  330: 	return(SNDCARD_SSCAPE);
  331:     else if (driver == &sscape_mssdriver)
  332: 	return(SNDCARD_SSCAPE_MSS);
  333:     else if (driver == &trixdriver)
  334: 	return (SNDCARD_TRXPRO);
  335:     else if (driver == &trixsbdriver)
  336: 	return (SNDCARD_TRXPRO_SB);
  337:     else if (driver == &nssdriver)
  338: 	return (SNDCARD_NSS);
  339:     else
  340: 	return (0);
  341: }
  342: 
  343: /*
  344:  * very dirty: tmp_osp is allocated in sndprobe, and used at the next
  345:  * call in sndattach
  346:  */
  347: 
  348: static sound_os_info *temp_osp;
  349: 
  350: /*
  351:  * sndprobe is called for each isa_device. From here, a voxware unit
  352:  * number is determined, and the appropriate probe routine is selected.
  353:  * The parameters from the config line are passed to the hw_config struct.
  354:  */
  355: 
  356: static int
  357: sndprobe(struct isa_device * dev)
  358: {
  359:     struct address_info hw_config;
  360:     int             unit;
  361: 
  362:     temp_osp = (sound_os_info *)malloc(sizeof(sound_os_info),
  363: 	    M_DEVBUF, M_NOWAIT);
  364:     if (!temp_osp)
  365: 	panic("SOUND: Cannot allocate memory\n");
  366: 
  367:     /*
  368:      * get config info from the kernel config. These may be overridden
  369:      * by the local autoconfiguration routines though (e.g. pnp stuff).
  370:      */
  371: 
  372:     hw_config.io_base = dev->id_iobase;
  373:     hw_config.irq = ipri_to_irq(dev->id_irq);
  374:     hw_config.dma = dev->id_drq;
  375: 
  376:     /*
  377:      * misuse the flags field for read dma. Note that, to use 0 as
  378:      * read dma channel, one of the high bits should be set.  lr970705 XXX
  379:      */
  380: 
  381:     if (dev->id_flags != 0)
  382: 	hw_config.dma2 = dev->id_flags & 0x7;
  383:     else
  384: 	hw_config.dma2 = -1;
  385: 
  386:     hw_config.always_detect = 0;
  387:     hw_config.name = NULL;
  388:     hw_config.card_subtype = 0;
  389: 
  390:     temp_osp->unit = dev->id_unit;
  391:     hw_config.osp = temp_osp;
  392:     unit = driver_to_voxunit(dev->id_driver);
  393: 
  394:     if (sndtable_probe(unit, &hw_config)) {
  395: 	dev->id_iobase = hw_config.io_base;
  396: 	dev->id_irq =  hw_config.irq == -1 ? 0 : (1 << hw_config.irq);
  397: 	dev->id_drq = hw_config.dma;
  398: 
  399: 	if (hw_config.dma != hw_config.dma2 && ( hw_config.dma2 != -1))
  400: 	    dev->id_flags = hw_config.dma2 | 0x100; /* XXX lr */
  401: 	else
  402: 	    dev->id_flags = 0;
  403: 	return TRUE;
  404:     }
  405:     return 0;
  406: }
  407: 
  408: static int
  409: sndattach(struct isa_device * dev)
  410: {
  411:     int             unit;
  412:     static int      midi_initialized = 0;
  413:     static int      seq_initialized = 0;
  414:     struct address_info hw_config;
  415:     char   *dname;
  416: 
  417:     /*
  418:      * Associate interrupt handlers with devices.  XXX this may be incomplete.
  419:      */
  420:     dname = dev->id_driver->name;
  421: #if defined(CONFIG_AD1848)
  422:     if (strcmp(dname, "css") == 0 || strcmp(dname, "gusxvi") == 0 ||
  423: 	strcmp(dname, "mss") == 0)
  424: 	dev->id_ointr = adintr;
  425: #endif
  426: #ifdef CONFIG_GUS
  427:     if (strcmp(dname, "gus") == 0)
  428: 	dev->id_ointr = gusintr;
  429: #endif
  430: #ifdef CONFIG_PAS
  431:     if (strcmp(dname, "pas") == 0)
  432: 	dev->id_ointr = pasintr;
  433: #endif
  434: #if NSB > 0 && (defined(CONFIG_MIDI) || defined(CONFIG_AUDIO))
  435:     if (strcmp(dname, "sb") == 0)
  436: 	dev->id_ointr = sbintr;
  437: #endif
  438:     if (strcmp(dname, "sscape_mss") == 0)
  439: 	dev->id_ointr = sndintr;
  440: #if NSSCAPE > 0
  441:     if (strcmp(dname, "sscape") == 0 || strcmp(dname, "trix") == 0)
  442: 	dev->id_ointr = sscapeintr;
  443: #endif
  444: #if NUART > 0
  445:     if (strcmp(dname, "uart0") == 0)
  446: 	dev->id_ointr = m6850intr;
  447: #endif
  448: #if NMPU > 0 && defined(CONFIG_MIDI)
  449:     if (strcmp(dname, "mpu") == 0)
  450: 	dev->id_ointr = mpuintr;
  451: #endif
  452: #if NNSS > 0
  453:     if (strcmp(dname, "nss") == 0)
  454: 	dev->id_ointr = nssintr;
  455: #endif
  456: 
  457:     unit = driver_to_voxunit(dev->id_driver);
  458:     hw_config.io_base = dev->id_iobase;
  459:     hw_config.irq = ipri_to_irq(dev->id_irq);
  460:     hw_config.dma = dev->id_drq;
  461: 
  462:     /* misuse the flags field for read dma */
  463:     if (dev->id_flags != 0)
  464: 	hw_config.dma2 = dev->id_flags & 0x7;
  465:     else
  466: 	hw_config.dma2 = -1;
  467: 
  468:     hw_config.card_subtype = 0;
  469:     hw_config.osp = temp_osp;
  470: 
  471:     if (!unit)
  472: 	return FALSE;
  473: 
  474:     if (!(sndtable_init_card(unit, &hw_config))) {	/* init card */
  475: 	printf(" <Driver not configured>");
  476: 	return FALSE;
  477:     }
  478:     /*
  479:      * Init the high level sound driver
  480:      */
  481: 
  482:     if (!(soundcards_installed = sndtable_get_cardcount())) {
  483: 	DDB(printf("No drivers actually installed\n"));
  484: 	return FALSE;	/* No cards detected */
  485:     }
  486:     printf("\n");
  487: 
  488: #ifdef CONFIG_AUDIO
  489:     if (num_audiodevs) {	/* Audio devices present */
  490: 	DMAbuf_init();
  491: 	sound_mem_init();
  492:     }
  493:     soundcard_configured = 1;
  494: #endif
  495: 
  496:     if (num_midis && !midi_initialized)
  497: 	midi_initialized = 1;
  498: 
  499:     if ((num_midis + num_synths) && !seq_initialized) {
  500: 	seq_initialized = 1;
  501: 	sequencer_init();
  502:     }
  503: 
  504:     cdevsw_add(&snd_cdevsw);
  505: #define GID_SND GID_GAMES
  506: #define UID_SND UID_ROOT
  507: #define PERM_SND 0660
  508:     /*
  509:      *	make links to first successfully probed device, don't do it if
  510:      *	duplicate creation of same node failed (ie. bad cookie returned)
  511:      */
  512:     if (dev->id_driver == &opldriver){
  513: 	make_dev(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_SEQ,
  514: 	    UID_SND, GID_SND, PERM_SND, "sequencer%r", dev->id_unit);
  515:     } else if (dev->id_driver == &mpudriver || 
  516:                dev->id_driver == &sbmididriver ||
  517: 	       dev->id_driver == &uartdriver){
  518: 	make_dev(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_MIDIN,
  519: 	    UID_SND, GID_SND, PERM_SND, "midi%r", dev->id_unit);
  520:     } else {
  521: 	make_dev(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP,
  522: 	    UID_SND, GID_SND, PERM_SND, "dsp%r", dev->id_unit);
  523: 	make_dev(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_DSP16,
  524: 	    UID_SND, GID_SND, PERM_SND, "dspW%r", dev->id_unit);
  525: 	make_dev(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_AUDIO,
  526: 	    UID_SND, GID_SND, PERM_SND, "audio%r", dev->id_unit);
  527: 	make_dev(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_CTL,
  528: 	    UID_SND, GID_SND, PERM_SND, "mixer%r", dev->id_unit);
  529: 	make_dev(&snd_cdevsw, (dev->id_unit << 4) | SND_DEV_STATUS,
  530: 	    UID_SND, GID_SND, PERM_SND, "sndstat%r", dev->id_unit);
  531:     }
  532:     return TRUE;
  533: }
  534: 
  535: 
  536: #ifdef CONFIG_AUDIO
  537: 
  538: static void
  539: alloc_dmap(int dev, int chan, struct dma_buffparms * dmap)
  540: {
  541:     char           *tmpbuf;
  542:     int            i;
  543: 
  544:     tmpbuf = contigmalloc(audio_devs[dev]->buffsize, M_DEVBUF, M_NOWAIT,
  545: 		0ul, 0xfffffful, 1ul, chan & 4 ? 0x20000ul : 0x10000ul);
  546:     if (tmpbuf == NULL)
  547: 	printf("soundcard buffer alloc failed \n");
  548: 
  549:     if (tmpbuf == NULL) {
  550: 	printf("snd: Unable to allocate %d bytes of buffer\n",
  551: 	       2 * (int) audio_devs[dev]->buffsize);
  552: 	return;
  553:     }
  554:     dmap->raw_buf = tmpbuf;
  555:     /*
  556:      * Use virtual address as the physical address, since isa_dmastart
  557:      * performs the phys address computation.
  558:      */
  559: 
  560:     dmap->raw_buf_phys = (uintptr_t) tmpbuf;
  561:     for (i = 0; i < audio_devs[dev]->buffsize; i++)   *tmpbuf++ = 0x80; 
  562: 
  563: }
  564: 
  565: static void
  566: sound_mem_init(void)
  567: {
  568:     int             dev;
  569:     static u_long dsp_init_mask = 0;
  570: 
  571:     for (dev = 0; dev < num_audiodevs; dev++)	/* Enumerate devices */
  572: 	if (!(dsp_init_mask & (1 << dev)))	/* Not already done */
  573: 	    if (audio_devs[dev]->dmachan1 >= 0) {
  574: 		dsp_init_mask |= (1 << dev);
  575: 		audio_devs[dev]->buffsize = DSP_BUFFSIZE;
  576: 		/* Now allocate the buffers */
  577: 		alloc_dmap(dev, audio_devs[dev]->dmachan1,
  578: 			audio_devs[dev]->dmap_out);
  579: 		if (audio_devs[dev]->flags & DMA_DUPLEX)
  580: 		    alloc_dmap(dev, audio_devs[dev]->dmachan2,
  581: 			    audio_devs[dev]->dmap_in);
  582: 	    }	/* for dev */
  583: }
  584: 
  585: #endif
  586: 
  587: 
  588: int
  589: snd_ioctl_return(int *addr, int value)
  590: {
  591:     if (value < 0)
  592: 	return value;	/* Error */
  593:     suword(addr, value);
  594:     return 0;
  595: }
  596: 
  597: #define MAX_UNIT 50
  598: typedef void    (*irq_proc_t) (int irq);
  599: static irq_proc_t irq_proc[MAX_UNIT] = {NULL};
  600: static int      irq_irq[MAX_UNIT] = {0};
  601: 
  602: int
  603: snd_set_irq_handler(int int_lvl, void (*hndlr) (int), sound_os_info * osp)
  604: {
  605:     if (osp->unit >= MAX_UNIT) {
  606: 	printf("Sound error: Unit number too high (%d)\n", osp->unit);
  607: 	return 0;
  608:     }
  609:     irq_proc[osp->unit] = hndlr;
  610:     irq_irq[osp->unit] = int_lvl;
  611:     return 1;
  612: }
  613: 
  614: static void
  615: sndintr(int unit)
  616: {
  617:     if ( (unit >= MAX_UNIT) || (irq_proc[unit] == NULL) )
  618: 	return;
  619: 
  620:     irq_proc[unit] (irq_irq[unit]);	/* Call the installed handler */
  621: }
  622: 
  623: void
  624: conf_printf(char *name, struct address_info * hw_config)
  625: {
  626:     if (!trace_init)
  627: 	return;
  628: 
  629:     printf("snd0: <%s> ", name);
  630: #if 0
  631:     if (hw_config->io_base != -1 ) 
  632:     printf("at 0x%03x", hw_config->io_base);
  633: 
  634:     if (hw_config->irq != -1 )
  635: 	printf(" irq %d", hw_config->irq);
  636: 
  637:     if (hw_config->dma != -1 || hw_config->dma2 != -1) {
  638: 	printf(" dma %d", hw_config->dma);
  639: 	if (hw_config->dma2 != -1)
  640: 	    printf(",%d", hw_config->dma2);
  641:     }
  642: #endif
  643: 
  644: }
  645: 
  646: void
  647: conf_printf2(char *name, int base, int irq, int dma, int dma2)
  648: {
  649:     if (!trace_init)
  650: 	return;
  651: 
  652:     printf("snd0: <%s> ", name);
  653: #if 0
  654:     if (hw_config->io_base != -1 ) 
  655:     printf("at 0x%03x", hw_config->io_base);
  656: 
  657:     if (irq)
  658: 	printf(" irq %d", irq);
  659: 
  660:     if (dma != -1 || dma2 != -1) {
  661: 	printf(" dma %d", dma);
  662: 	if (dma2 != -1)
  663: 	    printf(",%d", dma2);
  664:     }
  665: #endif
  666: 
  667: }
  668: 
  669: 
  670: void tenmicrosec (int j)
  671: {
  672:   int             i, k;
  673:   for (k = 0; k < j/10 ; k++) {
  674:       for (i = 0; i < 16; i++)
  675: 	  inb (0x80);
  676:   }
  677: }
  678: 
  679: #endif	/* NSND > 0 */
  680: 
  681: 
  682: 
  683: