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