Home | History | Annotate | Line # | Download | only in obio
asc.c revision 1.16
      1 /*	$NetBSD: asc.c,v 1.16 1997/02/03 17:36:00 scottr Exp $	*/
      2 
      3 /*-
      4  * Copyright (C) 1993	Allen K. Briggs, Chris P. Caputo,
      5  *			Michael L. Finch, Bradley A. Grantham, and
      6  *			Lawrence A. Kesteloot
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed by the Alice Group.
     20  * 4. The names of the Alice Group or any of its members may not be used
     21  *    to endorse or promote products derived from this software without
     22  *    specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
     25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27  * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
     28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     33  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  */
     35 
     36 /*
     37  * ASC driver code and asc_ringbell() support
     38  */
     39 
     40 #include <sys/types.h>
     41 #include <sys/cdefs.h>
     42 #include <sys/errno.h>
     43 #include <sys/time.h>
     44 #include <sys/systm.h>
     45 #include <sys/param.h>
     46 #include <sys/device.h>
     47 
     48 #include <machine/autoconf.h>
     49 #include <machine/cpu.h>
     50 #include <machine/bus.h>
     51 
     52 #include "ascvar.h"
     53 #include "obiovar.h"
     54 
     55 #define	MAC68K_ASC_BASE	((caddr_t) 0x50f14000)
     56 #define	MAC68K_ASC_LEN	0x01000
     57 
     58 /* bell support data */
     59 static int		asc_configured = 0;
     60 static bus_space_tag_t	asc_tag = MAC68K_BUS_SPACE_MEM;
     61 static bus_space_handle_t asc_handle;
     62 
     63 static int bell_freq = 1880;
     64 static int bell_length = 10;
     65 static int bell_volume = 100;
     66 static int bell_ringing = 0;
     67 
     68 static int  ascmatch __P((struct device *, struct cfdata *, void *));
     69 static void ascattach __P((struct device *, struct device *, void *));
     70 
     71 struct cfattach asc_ca = {
     72 	sizeof(struct device), ascmatch, ascattach
     73 };
     74 
     75 struct cfdriver asc_cd = {
     76 	NULL, "asc", DV_DULL, NULL, 0
     77 };
     78 
     79 static int
     80 ascmatch(parent, cf, aux)
     81 	struct device *parent;
     82 	struct cfdata *cf;
     83 	void *aux;
     84 {
     85 	static int asc_matched = 0;
     86 	struct obio_attach_args *oa = aux;
     87 	bus_space_tag_t bst = MAC68K_BUS_SPACE_MEM;
     88 	bus_space_handle_t bsh;
     89 	bus_addr_t addr;
     90 	int rval = 0;
     91 
     92 	/* Allow only one instance. */
     93 	if (asc_matched)
     94 		return (0);
     95 	asc_matched = 1;
     96 
     97 	addr = (bus_addr_t) (oa->oa_addr ? oa->oa_addr : MAC68K_ASC_BASE);
     98 
     99 	if (bus_space_map(bst, addr, MAC68K_ASC_LEN, 0, &bsh))
    100 		return (0);
    101 
    102 	if (bus_probe(bst, bsh, 0, 1))
    103 		rval = 1;
    104 	else
    105 		rval = 0;
    106 
    107 	bus_space_unmap(bst, bsh, MAC68K_ASC_LEN);
    108 
    109 	return rval;
    110 }
    111 
    112 static void
    113 ascattach(parent, self, aux)
    114 	struct device *parent, *self;
    115 	void *aux;
    116 {
    117 	struct obio_attach_args *oa = aux;
    118 	bus_addr_t addr;
    119 
    120 	addr = (bus_addr_t) (oa->oa_addr ? oa->oa_addr : MAC68K_ASC_BASE);
    121 	if (bus_space_map(asc_tag, addr, MAC68K_ASC_LEN, 0,
    122 	    &asc_handle)) {
    123 		printf("%s: can't map memory space\n", self->dv_xname);
    124 		return;
    125 	}
    126 
    127 	printf(" Apple sound chip\n");
    128 	asc_configured = 1;
    129 }
    130 
    131 int
    132 asc_setbellparams(freq, length, volume)
    133 	int freq;
    134 	int length;
    135 	int volume;
    136 {
    137 	if (!asc_configured)
    138 		return (ENODEV);
    139 
    140 	/*
    141 	 * I only perform these checks for sanity.  I suppose
    142 	 * someone might want a bell that rings all day, but then
    143 	 * they can make kernel mods themselves.
    144 	 */
    145 
    146 	if (freq < 10 || freq > 40000)
    147 		return (EINVAL);
    148 	if (length < 0 || length > 3600)
    149 		return (EINVAL);
    150 	if (volume < 0 || volume > 100)
    151 		return (EINVAL);
    152 
    153 	bell_freq = freq;
    154 	bell_length = length;
    155 	bell_volume = volume;
    156 
    157 	return (0);
    158 }
    159 
    160 
    161 int
    162 asc_getbellparams(freq, length, volume)
    163     int *freq;
    164     int *length;
    165     int *volume;
    166 {
    167 	if (!asc_configured)
    168 		return (ENODEV);
    169 
    170 	*freq = bell_freq;
    171 	*length = bell_length;
    172 	*volume = bell_volume;
    173 
    174 	return (0);
    175 }
    176 
    177 
    178 void
    179 asc_bellstop(param)
    180     int param;
    181 {
    182 	if (!asc_configured)
    183 		return;
    184 
    185 	if (bell_ringing > 1000 || bell_ringing < 0)
    186 		panic("bell got out of sync?");
    187 
    188 	if (--bell_ringing == 0)	/* disable ASC */
    189 		bus_space_write_1(asc_tag, asc_handle, 0x801, 0);
    190 }
    191 
    192 
    193 int
    194 asc_ringbell()
    195 {
    196 	int     i;
    197 	unsigned long freq;
    198 
    199 	if (!asc_configured)
    200 		return (ENODEV);
    201 
    202 	if (bell_ringing == 0) {
    203 
    204 		for (i = 0; i < 0x800; i++)
    205 			bus_space_write_1(asc_tag, asc_handle, i, 0);
    206 
    207 		for (i = 0; i < 256; i++) {
    208 			bus_space_write_1(asc_tag, asc_handle, i, i / 4);
    209 			bus_space_write_1(asc_tag, asc_handle, i + 512, i / 4);
    210 			bus_space_write_1(asc_tag, asc_handle, i + 1024, i / 4);
    211 			bus_space_write_1(asc_tag, asc_handle, i + 1536, i / 4);
    212 		}		/* up part of wave, four voices ? */
    213 		for (i = 0; i < 256; i++) {
    214 			bus_space_write_1(asc_tag, asc_handle, i + 256,
    215 			    0x3f - (i / 4));
    216 			bus_space_write_1(asc_tag, asc_handle, i + 768,
    217 			    0x3f - (i / 4));
    218 			bus_space_write_1(asc_tag, asc_handle, i + 1280,
    219 			    0x3f - (i / 4));
    220 			bus_space_write_1(asc_tag, asc_handle, i + 1792,
    221 			    0x3f - (i / 4));
    222 		}		/* down part of wave, four voices ? */
    223 
    224 		/* Fix this.  Need to find exact ASC sampling freq */
    225 		freq = 65536 * bell_freq / 466;
    226 
    227 		/* printf("beep: from %d, %02x %02x %02x %02x\n",
    228 		 * cur_beep.freq, (freq >> 24) & 0xff, (freq >> 16) & 0xff,
    229 		 * (freq >> 8) & 0xff, (freq) & 0xff); */
    230 		for (i = 0; i < 8; i++) {
    231 			bus_space_write_1(asc_tag, asc_handle, 0x814 + 8 * i,
    232 			    (freq >> 24) & 0xff);
    233 			bus_space_write_1(asc_tag, asc_handle, 0x815 + 8 * i,
    234 			    (freq >> 16) & 0xff);
    235 			bus_space_write_1(asc_tag, asc_handle, 0x816 + 8 * i,
    236 			    (freq >> 8) & 0xff);
    237 			bus_space_write_1(asc_tag, asc_handle, 0x817 + 8 * i,
    238 			    (freq) & 0xff);
    239 		}		/* frequency; should put cur_beep.freq in here
    240 				 * somewhere. */
    241 
    242 		bus_space_write_1(asc_tag, asc_handle, 0x807, 3); /* 44 ? */
    243 		bus_space_write_1(asc_tag, asc_handle, 0x806,
    244 		    255 * bell_volume / 100);
    245 		bus_space_write_1(asc_tag, asc_handle, 0x805, 0);
    246 		bus_space_write_1(asc_tag, asc_handle, 0x80f, 0);
    247 		bus_space_write_1(asc_tag, asc_handle, 0x802, 2); /* sampled */
    248 		bus_space_write_1(asc_tag, asc_handle, 0x801, 2); /* enable sampled */
    249 	}
    250 	bell_ringing++;
    251 	timeout((void *) asc_bellstop, 0, bell_length);
    252 
    253 	return (0);
    254 }
    255