1 /* $NetBSD: asc.c,v 1.21 1997/06/10 20:29:10 veego Exp $ */ 2 3 /* 4 * Copyright (C) 1997 Scott Reynolds 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Scott Reynolds for 18 * the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /*- 34 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo, 35 * Michael L. Finch, Bradley A. Grantham, and 36 * Lawrence A. Kesteloot 37 * All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by the Alice Group. 50 * 4. The names of the Alice Group or any of its members may not be used 51 * to endorse or promote products derived from this software without 52 * specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR 55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 57 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT, 58 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 60 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 61 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 62 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 63 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66 /* 67 * ASC driver code and console bell support 68 */ 69 70 #include <sys/types.h> 71 #include <sys/cdefs.h> 72 #include <sys/errno.h> 73 #include <sys/time.h> 74 #include <sys/systm.h> 75 #include <sys/param.h> 76 #include <sys/device.h> 77 #include <sys/poll.h> 78 79 #include <vm/vm.h> 80 #include <vm/pmap.h> 81 82 #include <machine/autoconf.h> 83 #include <machine/cpu.h> 84 #include <machine/bus.h> 85 86 #include "ascvar.h" 87 #include "obiovar.h" 88 89 #define MAC68K_ASC_BASE 0x50f14000 90 #define MAC68K_ASC_LEN 0x01000 91 92 static u_int8_t asc_wave_tab[0x800]; 93 94 static int asc_ring_bell __P((void *, int, int, int)); 95 static void asc_stop_bell __P((void *)); 96 97 static int ascmatch __P((struct device *, struct cfdata *, void *)); 98 static void ascattach __P((struct device *, struct device *, void *)); 99 100 struct cfattach asc_ca = { 101 sizeof(struct asc_softc), ascmatch, ascattach 102 }; 103 104 struct cfdriver asc_cd = { 105 NULL, "asc", DV_DULL, NULL, 0 106 }; 107 108 static int 109 ascmatch(parent, cf, aux) 110 struct device *parent; 111 struct cfdata *cf; 112 void *aux; 113 { 114 struct obio_attach_args *oa = (struct obio_attach_args *)aux; 115 bus_addr_t addr; 116 bus_space_handle_t bsh; 117 int rval = 0; 118 119 addr = (bus_addr_t)(oa->oa_addr != (-1) ? 120 oa->oa_addr : MAC68K_ASC_BASE); 121 122 if (bus_space_map(oa->oa_tag, addr, MAC68K_ASC_LEN, 0, &bsh)) 123 return (0); 124 125 if (bus_probe(oa->oa_tag, bsh, 0, 1)) 126 rval = 1; 127 else 128 rval = 0; 129 130 bus_space_unmap(oa->oa_tag, bsh, MAC68K_ASC_LEN); 131 132 return rval; 133 } 134 135 static void 136 ascattach(parent, self, aux) 137 struct device *parent, *self; 138 void *aux; 139 { 140 struct asc_softc *sc = (struct asc_softc *)self; 141 struct obio_attach_args *oa = (struct obio_attach_args *)aux; 142 bus_addr_t addr; 143 int i; 144 145 sc->sc_tag = oa->oa_tag; 146 addr = (bus_addr_t)(oa->oa_addr != (-1) ? 147 oa->oa_addr : MAC68K_ASC_BASE); 148 if (bus_space_map(sc->sc_tag, addr, MAC68K_ASC_LEN, 0, 149 &sc->sc_handle)) { 150 printf(": can't map memory space\n"); 151 return; 152 } 153 sc->sc_open = 0; 154 sc->sc_ringing = 0; 155 156 for (i = 0; i < 256; i++) { /* up part of wave, four voices? */ 157 asc_wave_tab[i] = i / 4; 158 asc_wave_tab[i + 512] = i / 4; 159 asc_wave_tab[i + 1024] = i / 4; 160 asc_wave_tab[i + 1536] = i / 4; 161 } 162 for (i = 0; i < 256; i++) { /* down part of wave, four voices? */ 163 asc_wave_tab[i + 256] = 0x3f - (i / 4); 164 asc_wave_tab[i + 768] = 0x3f - (i / 4); 165 asc_wave_tab[i + 1280] = 0x3f - (i / 4); 166 asc_wave_tab[i + 1792] = 0x3f - (i / 4); 167 } 168 169 printf(": Apple Sound Chip"); 170 if (oa->oa_addr != (-1)) 171 printf(" at %x", oa->oa_addr); 172 printf("\n"); 173 174 mac68k_set_bell_callback(asc_ring_bell, sc); 175 } 176 177 int 178 ascopen(dev, flag, mode, p) 179 dev_t dev; 180 int flag; 181 int mode; 182 struct proc *p; 183 { 184 struct asc_softc *sc; 185 int unit; 186 187 unit = ASCUNIT(dev); 188 sc = asc_cd.cd_devs[unit]; 189 if (unit >= asc_cd.cd_ndevs) 190 return (ENXIO); 191 if (sc->sc_open) 192 return (EBUSY); 193 sc->sc_open = 1; 194 195 return (0); 196 } 197 198 int 199 ascclose(dev, flag, mode, p) 200 dev_t dev; 201 int flag; 202 int mode; 203 struct proc *p; 204 { 205 struct asc_softc *sc; 206 207 sc = asc_cd.cd_devs[ASCUNIT(dev)]; 208 sc->sc_open = 0; 209 210 return (0); 211 } 212 213 int 214 ascread(dev, uio, ioflag) 215 dev_t dev; 216 struct uio *uio; 217 int ioflag; 218 { 219 return (ENXIO); 220 } 221 222 int 223 ascwrite(dev, uio, ioflag) 224 dev_t dev; 225 struct uio *uio; 226 int ioflag; 227 { 228 return (ENXIO); 229 } 230 231 int 232 ascioctl(dev, cmd, data, flag, p) 233 dev_t dev; 234 int cmd; 235 caddr_t data; 236 int flag; 237 struct proc *p; 238 { 239 struct asc_softc *sc; 240 int error; 241 int unit = ASCUNIT(dev); 242 243 sc = asc_cd.cd_devs[unit]; 244 error = 0; 245 246 switch (cmd) { 247 default: 248 error = EINVAL; 249 break; 250 } 251 return (error); 252 } 253 254 int 255 ascpoll(dev, events, p) 256 dev_t dev; 257 int events; 258 struct proc *p; 259 { 260 return (events & (POLLOUT | POLLWRNORM)); 261 } 262 263 int 264 ascmmap(dev, off, prot) 265 dev_t dev; 266 int off; 267 int prot; 268 { 269 int unit = ASCUNIT(dev); 270 struct asc_softc *sc; 271 vm_offset_t pa; 272 273 sc = asc_cd.cd_devs[unit]; 274 if (off < MAC68K_ASC_LEN) { 275 pa = pmap_extract(pmap_kernel(), (vm_offset_t)sc->sc_handle); 276 return m68k_btop(pa + off); 277 } 278 279 return (-1); 280 } 281 282 static int 283 asc_ring_bell(arg, freq, length, volume) 284 void *arg; 285 int freq, length, volume; 286 { 287 struct asc_softc *sc = (struct asc_softc *)arg; 288 unsigned long cfreq; 289 int i; 290 291 if (!sc) 292 return (ENODEV); 293 294 if (sc->sc_ringing == 0) { 295 296 bus_space_write_multi_1(sc->sc_tag, sc->sc_handle, 297 0, 0, 0x800); 298 bus_space_write_region_1(sc->sc_tag, sc->sc_handle, 299 0, asc_wave_tab, 0x800); 300 301 /* Fix this. Need to find exact ASC sampling freq */ 302 cfreq = 65536 * freq / 466; 303 304 /* printf("beep: from %d, %02x %02x %02x %02x\n", 305 * cur_beep.freq, (cfreq >> 24) & 0xff, (cfreq >> 16) & 0xff, 306 * (cfreq >> 8) & 0xff, (cfreq) & 0xff); */ 307 for (i = 0; i < 8; i++) { 308 bus_space_write_1(sc->sc_tag, sc->sc_handle, 309 0x814 + 8 * i, (cfreq >> 24) & 0xff); 310 bus_space_write_1(sc->sc_tag, sc->sc_handle, 311 0x815 + 8 * i, (cfreq >> 16) & 0xff); 312 bus_space_write_1(sc->sc_tag, sc->sc_handle, 313 0x816 + 8 * i, (cfreq >> 8) & 0xff); 314 bus_space_write_1(sc->sc_tag, sc->sc_handle, 315 0x817 + 8 * i, (cfreq) & 0xff); 316 } /* frequency; should put cur_beep.freq in here 317 * somewhere. */ 318 319 bus_space_write_1(sc->sc_tag, sc->sc_handle, 0x807, 3); /* 44 ? */ 320 bus_space_write_1(sc->sc_tag, sc->sc_handle, 0x806, 321 255 * volume / 100); 322 bus_space_write_1(sc->sc_tag, sc->sc_handle, 0x805, 0); 323 bus_space_write_1(sc->sc_tag, sc->sc_handle, 0x80f, 0); 324 bus_space_write_1(sc->sc_tag, sc->sc_handle, 0x802, 2); /* sampled */ 325 bus_space_write_1(sc->sc_tag, sc->sc_handle, 0x801, 2); /* enable sampled */ 326 } 327 sc->sc_ringing++; 328 timeout(asc_stop_bell, sc, length); 329 330 return (0); 331 } 332 333 static void 334 asc_stop_bell(arg) 335 void *arg; 336 { 337 struct asc_softc *sc = (struct asc_softc *)arg; 338 339 if (!sc) 340 return; 341 342 if (sc->sc_ringing > 1000 || sc->sc_ringing < 0) 343 panic("bell got out of sync?"); 344 345 if (--sc->sc_ringing == 0) /* disable ASC */ 346 bus_space_write_1(sc->sc_tag, sc->sc_handle, 0x801, 0); 347 } 348