1 /* $NetBSD: opl.c,v 1.12 2001/01/18 20:28:18 jdolecek Exp $ */ 2 3 /* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (augustss@netbsd.org). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * The OPL3 (YMF262) manual can be found at 41 * ftp://ftp.yamahayst.com/Fax_Back_Doc/sound/YMF262.PDF 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/errno.h> 47 #include <sys/ioctl.h> 48 #include <sys/syslog.h> 49 #include <sys/device.h> 50 #include <sys/select.h> 51 52 #include <machine/cpu.h> 53 #include <machine/bus.h> 54 55 #include <sys/audioio.h> 56 #include <sys/midiio.h> 57 #include <dev/audio_if.h> 58 59 #include <dev/midi_if.h> 60 #include <dev/midivar.h> 61 #include <dev/midisynvar.h> 62 63 #include <dev/ic/oplreg.h> 64 #include <dev/ic/oplvar.h> 65 66 #ifdef AUDIO_DEBUG 67 #define DPRINTF(x) if (opldebug) printf x 68 #define DPRINTFN(n,x) if (opldebug >= (n)) printf x 69 int opldebug = 0; 70 #else 71 #define DPRINTF(x) 72 #define DPRINTFN(n,x) 73 #endif 74 75 struct real_voice { 76 u_int8_t voice_num; 77 u_int8_t voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */ 78 u_int8_t iooffs; /* I/O port (left or right side) */ 79 u_int8_t op[4]; /* Operator offsets */ 80 }; 81 82 const struct opl_voice voicetab[] = { 83 /* No I/O offs OP1 OP2 OP3 OP4 */ 84 /* --------------------------------------------- */ 85 { 0, OPL_L, {0x00, 0x03, 0x08, 0x0b}}, 86 { 1, OPL_L, {0x01, 0x04, 0x09, 0x0c}}, 87 { 2, OPL_L, {0x02, 0x05, 0x0a, 0x0d}}, 88 89 { 3, OPL_L, {0x08, 0x0b, 0x00, 0x00}}, 90 { 4, OPL_L, {0x09, 0x0c, 0x00, 0x00}}, 91 { 5, OPL_L, {0x0a, 0x0d, 0x00, 0x00}}, 92 93 { 6, OPL_L, {0x10, 0x13, 0x00, 0x00}}, 94 { 7, OPL_L, {0x11, 0x14, 0x00, 0x00}}, 95 { 8, OPL_L, {0x12, 0x15, 0x00, 0x00}}, 96 97 { 0, OPL_R, {0x00, 0x03, 0x08, 0x0b}}, 98 { 1, OPL_R, {0x01, 0x04, 0x09, 0x0c}}, 99 { 2, OPL_R, {0x02, 0x05, 0x0a, 0x0d}}, 100 { 3, OPL_R, {0x08, 0x0b, 0x00, 0x00}}, 101 { 4, OPL_R, {0x09, 0x0c, 0x00, 0x00}}, 102 { 5, OPL_R, {0x0a, 0x0d, 0x00, 0x00}}, 103 104 { 6, OPL_R, {0x10, 0x13, 0x00, 0x00}}, 105 { 7, OPL_R, {0x11, 0x14, 0x00, 0x00}}, 106 { 8, OPL_R, {0x12, 0x15, 0x00, 0x00}} 107 }; 108 109 static void opl_command(struct opl_softc *, int, int, int); 110 void opl_reset(struct opl_softc *); 111 void opl_freq_to_fnum (int freq, int *block, int *fnum); 112 113 int oplsyn_open __P((midisyn *ms, int)); 114 void oplsyn_close __P((midisyn *)); 115 void oplsyn_reset __P((void *)); 116 void oplsyn_noteon __P((midisyn *, u_int32_t, u_int32_t, u_int32_t)); 117 void oplsyn_noteoff __P((midisyn *, u_int32_t, u_int32_t, u_int32_t)); 118 void oplsyn_keypressure __P((midisyn *, u_int32_t, u_int32_t, u_int32_t)); 119 void oplsyn_ctlchange __P((midisyn *, u_int32_t, u_int32_t, u_int32_t)); 120 void oplsyn_programchange __P((midisyn *, u_int32_t, u_int32_t)); 121 void oplsyn_pitchbend __P((midisyn *, u_int32_t, u_int32_t, u_int32_t)); 122 void oplsyn_loadpatch __P((midisyn *, struct sysex_info *, struct uio *)); 123 124 125 void opl_set_op_reg __P((struct opl_softc *, int, int, int, u_char)); 126 void opl_set_ch_reg __P((struct opl_softc *, int, int, u_char)); 127 void opl_load_patch __P((struct opl_softc *, int)); 128 u_int32_t opl_get_block_fnum __P((int freq)); 129 int opl_calc_vol __P((int regbyte, int volume, int main_vol)); 130 131 struct midisyn_methods opl3_midi = { 132 oplsyn_open, 133 oplsyn_close, 134 0, 135 0, 136 oplsyn_noteon, 137 oplsyn_noteoff, 138 oplsyn_keypressure, 139 oplsyn_ctlchange, 140 oplsyn_programchange, 141 0, 142 oplsyn_pitchbend, 143 0 144 }; 145 146 void 147 opl_attach(sc) 148 struct opl_softc *sc; 149 { 150 int i; 151 152 if (!opl_find(sc)) { 153 printf("\nopl: find failed\n"); 154 return; 155 } 156 157 sc->syn.mets = &opl3_midi; 158 sprintf(sc->syn.name, "%sYamaha OPL%d", sc->syn.name, sc->model); 159 sc->syn.data = sc; 160 sc->syn.nvoice = sc->model == OPL_2 ? OPL2_NVOICE : OPL3_NVOICE; 161 sc->syn.flags = MS_DOALLOC | MS_FREQXLATE; 162 midisyn_attach(&sc->mididev, &sc->syn); 163 164 /* Set up voice table */ 165 for (i = 0; i < OPL3_NVOICE; i++) 166 sc->voices[i] = voicetab[i]; 167 168 opl_reset(sc); 169 170 printf(": model OPL%d\n", sc->model); 171 172 midi_attach_mi(&midisyn_hw_if, &sc->syn, &sc->mididev.dev); 173 } 174 175 static void 176 opl_command(sc, offs, addr, data) 177 struct opl_softc *sc; 178 int offs; 179 int addr, data; 180 { 181 DPRINTFN(4, ("opl_command: sc=%p, offs=%d addr=0x%02x data=0x%02x\n", 182 sc, offs, addr, data)); 183 offs += sc->offs; 184 bus_space_write_1(sc->iot, sc->ioh, OPL_ADDR+offs, addr); 185 if (sc->model == OPL_2) 186 delay(10); 187 else 188 delay(6); 189 bus_space_write_1(sc->iot, sc->ioh, OPL_DATA+offs, data); 190 if (sc->model == OPL_2) 191 delay(30); 192 else 193 delay(6); 194 } 195 196 int 197 opl_find(sc) 198 struct opl_softc *sc; 199 { 200 u_int8_t status1, status2; 201 202 DPRINTFN(2,("opl_find: ioh=0x%x\n", (int)sc->ioh)); 203 sc->model = OPL_2; /* worst case assumtion */ 204 205 /* Reset timers 1 and 2 */ 206 opl_command(sc, OPL_L, OPL_TIMER_CONTROL, 207 OPL_TIMER1_MASK | OPL_TIMER2_MASK); 208 /* Reset the IRQ of the FM chip */ 209 opl_command(sc, OPL_L, OPL_TIMER_CONTROL, OPL_IRQ_RESET); 210 211 /* get status bits */ 212 status1 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs); 213 214 opl_command(sc, OPL_L, OPL_TIMER1, -2); /* wait 2 ticks */ 215 opl_command(sc, OPL_L, OPL_TIMER_CONTROL, /* start timer1 */ 216 OPL_TIMER1_START | OPL_TIMER2_MASK); 217 delay(1000); /* wait for timer to expire */ 218 219 /* get status bits again */ 220 status2 = bus_space_read_1(sc->iot,sc->ioh,OPL_STATUS+OPL_L+sc->offs); 221 222 opl_command(sc, OPL_L, OPL_TIMER_CONTROL, 223 OPL_TIMER1_MASK | OPL_TIMER2_MASK); 224 opl_command(sc, OPL_L, OPL_TIMER_CONTROL, OPL_IRQ_RESET); 225 226 DPRINTFN(2,("opl_find: %02x %02x\n", status1, status2)); 227 228 if ((status1 & OPL_STATUS_MASK) != 0 || 229 (status2 & OPL_STATUS_MASK) != (OPL_STATUS_IRQ | OPL_STATUS_FT1)) 230 return (0); 231 232 switch(status1) { 233 case 0x00: 234 case 0x0f: 235 sc->model = OPL_3; 236 break; 237 case 0x06: 238 sc->model = OPL_2; 239 break; 240 default: 241 return (0); 242 } 243 244 DPRINTFN(2,("opl_find: OPL%d at 0x%x detected\n", 245 sc->model, (int)sc->ioh)); 246 return (1); 247 } 248 249 void 250 opl_set_op_reg(sc, base, voice, op, value) 251 struct opl_softc *sc; 252 int base; 253 int voice; 254 int op; 255 u_char value; 256 { 257 struct opl_voice *v = &sc->voices[voice]; 258 opl_command(sc, v->iooffs, base + v->op[op], value); 259 } 260 261 void 262 opl_set_ch_reg(sc, base, voice, value) 263 struct opl_softc *sc; 264 int base; 265 int voice; 266 u_char value; 267 { 268 struct opl_voice *v = &sc->voices[voice]; 269 opl_command(sc, v->iooffs, base + v->voiceno, value); 270 } 271 272 273 void 274 opl_load_patch(sc, v) 275 struct opl_softc *sc; 276 int v; 277 { 278 const struct opl_operators *p = sc->voices[v].patch; 279 280 opl_set_op_reg(sc, OPL_AM_VIB, v, 0, p->ops[OO_CHARS+0]); 281 opl_set_op_reg(sc, OPL_AM_VIB, v, 1, p->ops[OO_CHARS+1]); 282 opl_set_op_reg(sc, OPL_KSL_LEVEL, v, 0, p->ops[OO_KSL_LEV+0]); 283 opl_set_op_reg(sc, OPL_KSL_LEVEL, v, 1, p->ops[OO_KSL_LEV+1]); 284 opl_set_op_reg(sc, OPL_ATTACK_DECAY, v, 0, p->ops[OO_ATT_DEC+0]); 285 opl_set_op_reg(sc, OPL_ATTACK_DECAY, v, 1, p->ops[OO_ATT_DEC+1]); 286 opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 0, p->ops[OO_SUS_REL+0]); 287 opl_set_op_reg(sc, OPL_SUSTAIN_RELEASE, v, 1, p->ops[OO_SUS_REL+1]); 288 opl_set_op_reg(sc, OPL_WAVE_SELECT, v, 0, p->ops[OO_WAV_SEL+0]); 289 opl_set_op_reg(sc, OPL_WAVE_SELECT, v, 1, p->ops[OO_WAV_SEL+1]); 290 opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, v, p->ops[OO_FB_CONN]); 291 } 292 293 #define OPL_FNUM_FAIL 0xffff 294 u_int32_t 295 opl_get_block_fnum(freq) 296 int freq; 297 { 298 u_int32_t f_num = freq / 3125; 299 u_int32_t block = 0; 300 301 while (f_num > 0x3ff && block < 8) { 302 block++; 303 f_num >>= 1; 304 } 305 306 if (block > 7) 307 return (OPL_FNUM_FAIL); 308 else 309 return ((block << 10) | f_num); 310 } 311 312 313 void 314 opl_reset(sc) 315 struct opl_softc *sc; 316 { 317 int i; 318 319 for (i = 1; i <= OPL_MAXREG; i++) 320 opl_command(sc, OPL_L, OPL_KEYON_BLOCK + i, 0); 321 322 opl_command(sc, OPL_L, OPL_TEST, OPL_ENABLE_WAVE_SELECT); 323 opl_command(sc, OPL_L, OPL_PERCUSSION, 0); 324 if (sc->model == OPL_3) { 325 opl_command(sc, OPL_R, OPL_MODE, OPL3_ENABLE); 326 opl_command(sc, OPL_R,OPL_CONNECTION_SELECT,OPL_NOCONNECTION); 327 } 328 329 sc->volume = 64; 330 } 331 332 int 333 oplsyn_open(ms, flags) 334 midisyn *ms; 335 int flags; 336 { 337 struct opl_softc *sc = ms->data; 338 339 DPRINTFN(2, ("oplsyn_open: %d\n", flags)); 340 341 #ifndef AUDIO_NO_POWER_CTL 342 if (sc->powerctl) 343 sc->powerctl(sc->powerarg, 1); 344 #endif 345 opl_reset(ms->data); 346 if (sc->spkrctl) 347 sc->spkrctl(sc->spkrarg, 1); 348 return (0); 349 } 350 351 void 352 oplsyn_close(ms) 353 midisyn *ms; 354 { 355 struct opl_softc *sc = ms->data; 356 357 DPRINTFN(2, ("oplsyn_close:\n")); 358 359 /*opl_reset(ms->data);*/ 360 if (sc->spkrctl) 361 sc->spkrctl(sc->spkrarg, 0); 362 #ifndef AUDIO_NO_POWER_CTL 363 if (sc->powerctl) 364 sc->powerctl(sc->powerarg, 0); 365 #endif 366 } 367 368 #if 0 369 void 370 oplsyn_getinfo(addr, sd) 371 void *addr; 372 struct synth_dev *sd; 373 { 374 struct opl_softc *sc = addr; 375 376 sd->name = sc->model == OPL_2 ? "Yamaha OPL2" : "Yamaha OPL3"; 377 sd->type = SYNTH_TYPE_FM; 378 sd->subtype = sc->model == OPL_2 ? SYNTH_SUB_FM_TYPE_ADLIB 379 : SYNTH_SUB_FM_TYPE_OPL3; 380 sd->capabilities = 0; 381 } 382 #endif 383 384 void 385 oplsyn_reset(addr) 386 void *addr; 387 { 388 struct opl_softc *sc = addr; 389 DPRINTFN(3, ("oplsyn_reset:\n")); 390 opl_reset(sc); 391 } 392 393 const int8_t opl_volume_table[128] = 394 {-64, -48, -40, -35, -32, -29, -27, -26, 395 -24, -23, -21, -20, -19, -18, -18, -17, 396 -16, -15, -15, -14, -13, -13, -12, -12, 397 -11, -11, -10, -10, -10, -9, -9, -8, 398 -8, -8, -7, -7, -7, -6, -6, -6, 399 -5, -5, -5, -5, -4, -4, -4, -4, 400 -3, -3, -3, -3, -2, -2, -2, -2, 401 -2, -1, -1, -1, -1, 0, 0, 0, 402 0, 0, 0, 1, 1, 1, 1, 1, 403 1, 2, 2, 2, 2, 2, 2, 2, 404 3, 3, 3, 3, 3, 3, 3, 4, 405 4, 4, 4, 4, 4, 4, 4, 5, 406 5, 5, 5, 5, 5, 5, 5, 5, 407 6, 6, 6, 6, 6, 6, 6, 6, 408 6, 7, 7, 7, 7, 7, 7, 7, 409 7, 7, 7, 8, 8, 8, 8, 8}; 410 411 int 412 opl_calc_vol(regbyte, volume, mainvol) 413 int regbyte; 414 int volume; 415 int mainvol; 416 { 417 int level = ~regbyte & OPL_TOTAL_LEVEL_MASK; 418 419 if (mainvol > 127) 420 mainvol = 127; 421 422 volume = (volume * mainvol) / 127; 423 424 if (level) 425 level += opl_volume_table[volume]; 426 427 if (level > OPL_TOTAL_LEVEL_MASK) 428 level = OPL_TOTAL_LEVEL_MASK; 429 if (level < 0) 430 level = 0; 431 432 return (~level & OPL_TOTAL_LEVEL_MASK); 433 } 434 435 void 436 oplsyn_noteon(ms, voice, freq, vel) 437 midisyn *ms; 438 u_int32_t voice, freq, vel; 439 { 440 struct opl_softc *sc = ms->data; 441 struct opl_voice *v; 442 const struct opl_operators *p; 443 u_int32_t block_fnum; 444 int mult; 445 int c_mult, m_mult; 446 u_int8_t chars0, chars1, ksl0, ksl1, fbc; 447 u_int8_t r20m, r20c, r40m, r40c, rA0, rB0; 448 u_int8_t vol0, vol1; 449 450 DPRINTFN(3, ("oplsyn_noteon: %p %d %d\n", sc, voice, 451 MIDISYN_FREQ_TO_HZ(freq))); 452 453 #ifdef DIAGNOSTIC 454 if (voice < 0 || voice >= sc->syn.nvoice) { 455 printf("oplsyn_noteon: bad voice %d\n", voice); 456 return; 457 } 458 #endif 459 /* Turn off old note */ 460 opl_set_op_reg(sc, OPL_KSL_LEVEL, voice, 0, 0xff); 461 opl_set_op_reg(sc, OPL_KSL_LEVEL, voice, 1, 0xff); 462 opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice, 0); 463 464 v = &sc->voices[voice]; 465 466 p = &opl2_instrs[MS_GETPGM(ms, voice)]; 467 v->patch = p; 468 opl_load_patch(sc, voice); 469 470 mult = 1; 471 for (;;) { 472 block_fnum = opl_get_block_fnum(freq / mult); 473 if (block_fnum != OPL_FNUM_FAIL) 474 break; 475 mult *= 2; 476 if (mult == 16) 477 mult = 15; 478 } 479 480 chars0 = p->ops[OO_CHARS+0]; 481 chars1 = p->ops[OO_CHARS+1]; 482 m_mult = (chars0 & OPL_MULTIPLE_MASK) * mult; 483 c_mult = (chars1 & OPL_MULTIPLE_MASK) * mult; 484 if ((block_fnum == OPL_FNUM_FAIL) || (m_mult > 15) || (c_mult > 15)) { 485 printf("oplsyn_noteon: frequency out of range %d\n", 486 MIDISYN_FREQ_TO_HZ(freq)); 487 return; 488 } 489 r20m = (chars0 &~ OPL_MULTIPLE_MASK) | m_mult; 490 r20c = (chars1 &~ OPL_MULTIPLE_MASK) | c_mult; 491 492 /* 2 voice */ 493 ksl0 = p->ops[OO_KSL_LEV+0]; 494 ksl1 = p->ops[OO_KSL_LEV+1]; 495 if (p->ops[OO_FB_CONN] & 0x01) { 496 vol0 = opl_calc_vol(ksl0, vel, sc->volume); 497 vol1 = opl_calc_vol(ksl1, vel, sc->volume); 498 } else { 499 vol0 = ksl0; 500 vol1 = opl_calc_vol(ksl1, vel, sc->volume); 501 } 502 r40m = (ksl0 & OPL_KSL_MASK) | vol0; 503 r40c = (ksl1 & OPL_KSL_MASK) | vol1; 504 505 rA0 = block_fnum & 0xFF; 506 rB0 = (block_fnum >> 8) | OPL_KEYON_BIT; 507 508 v->rB0 = rB0; 509 510 fbc = p->ops[OO_FB_CONN]; 511 if (sc->model == OPL_3) { 512 fbc &= ~OPL_STEREO_BITS; 513 /* XXX use pan */ 514 fbc |= OPL_VOICE_TO_LEFT | OPL_VOICE_TO_RIGHT; 515 } 516 opl_set_ch_reg(sc, OPL_FEEDBACK_CONNECTION, voice, fbc); 517 518 opl_set_op_reg(sc, OPL_AM_VIB, voice, 0, r20m); 519 opl_set_op_reg(sc, OPL_AM_VIB, voice, 1, r20c); 520 opl_set_op_reg(sc, OPL_KSL_LEVEL, voice, 0, r40m); 521 opl_set_op_reg(sc, OPL_KSL_LEVEL, voice, 1, r40c); 522 opl_set_ch_reg(sc, OPL_FNUM_LOW, voice, rA0); 523 opl_set_ch_reg(sc, OPL_KEYON_BLOCK, voice, rB0); 524 } 525 526 void 527 oplsyn_noteoff(ms, voice, note, vel) 528 midisyn *ms; 529 u_int32_t voice, note, vel; 530 { 531 struct opl_softc *sc = ms->data; 532 struct opl_voice *v; 533 534 DPRINTFN(3, ("oplsyn_noteoff: %p %d %d\n", sc, voice, 535 MIDISYN_FREQ_TO_HZ(note))); 536 537 #ifdef DIAGNOSTIC 538 if (voice < 0 || voice >= sc->syn.nvoice) { 539 printf("oplsyn_noteoff: bad voice %d\n", voice); 540 return; 541 } 542 #endif 543 v = &sc->voices[voice]; 544 opl_set_ch_reg(sc, 0xB0, voice, v->rB0 & ~OPL_KEYON_BIT); 545 } 546 547 void 548 oplsyn_keypressure(ms, voice, note, vel) 549 midisyn *ms; 550 u_int32_t voice, note, vel; 551 { 552 #ifdef AUDIO_DEBUG 553 struct opl_softc *sc = ms->data; 554 DPRINTFN(1, ("oplsyn_keypressure: %p %d\n", sc, note)); 555 #endif 556 } 557 558 void 559 oplsyn_ctlchange(ms, voice, parm, w14) 560 midisyn *ms; 561 u_int32_t voice, parm, w14; 562 { 563 #ifdef AUDIO_DEBUG 564 struct opl_softc *sc = ms->data; 565 DPRINTFN(1, ("oplsyn_ctlchange: %p %d\n", sc, voice)); 566 #endif 567 } 568 569 /* PROGRAM CHANGE midi event: */ 570 void 571 oplsyn_programchange(ms, chan, prog) 572 midisyn *ms; 573 u_int32_t chan; 574 u_int32_t prog; 575 { 576 /* sanity checks */ 577 if (chan >= MIDI_MAX_CHANS || prog >= OPL_NINSTR) 578 return; 579 580 ms->pgms[chan] = prog; 581 } 582 583 void 584 oplsyn_pitchbend(ms, voice, parm, x) 585 midisyn *ms; 586 u_int32_t voice, parm, x; 587 { 588 #ifdef AUDIO_DEBUG 589 struct opl_softc *sc = ms->data; 590 DPRINTFN(1, ("oplsyn_pitchbend: %p %d\n", sc, voice)); 591 #endif 592 } 593 594 void 595 oplsyn_loadpatch(ms, sysex, uio) 596 midisyn *ms; 597 struct sysex_info *sysex; 598 struct uio *uio; 599 { 600 #if 0 601 struct opl_softc *sc = ms->data; 602 struct sbi_instrument ins; 603 604 DPRINTFN(1, ("oplsyn_loadpatch: %p\n", sc)); 605 606 memcpy(&ins, sysex, sizeof *sysex); 607 if (uio->uio_resid >= sizeof ins - sizeof *sysex) 608 return EINVAL; 609 uiomove((char *)&ins + sizeof *sysex, sizeof ins - sizeof *sysex, uio); 610 /* XXX */ 611 #endif 612 } 613