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