1 /* $NetBSD: esm.c,v 1.25 2004/04/30 14:14:55 simonb Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2003 Matt Fredette 5 * All rights reserved. 6 * 7 * Copyright (c) 2000, 2001 Rene Hexel <rh@NetBSD.org> 8 * All rights reserved. 9 * 10 * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp> 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * Taku Id: maestro.c,v 1.12 2000/09/06 03:32:34 taku Exp 35 * FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.4 2000/12/18 01:36:35 cg Exp 36 */ 37 38 /* 39 * TODO: 40 * - hardware volume support 41 * - fix 16-bit stereo recording, add 8-bit recording 42 * - MIDI support 43 * - joystick support 44 * 45 * 46 * Credits: 47 * 48 * This code is based on the FreeBSD driver written by Taku YAMAMOTO 49 * 50 * 51 * Original credits from the FreeBSD driver: 52 * 53 * Part of this code (especially in many magic numbers) was heavily inspired 54 * by the Linux driver originally written by 55 * Alan Cox <alan.cox@linux.org>, modified heavily by 56 * Zach Brown <zab@zabbo.net>. 57 * 58 * busdma()-ize and buffer size reduction were suggested by 59 * Cameron Grant <gandalf@vilnya.demon.co.uk>. 60 * Also he showed me the way to use busdma() suite. 61 * 62 * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500 63 * were looked at by 64 * Munehiro Matsuda <haro@tk.kubota.co.jp>, 65 * who brought patches based on the Linux driver with some simplification. 66 */ 67 68 #include <sys/cdefs.h> 69 __KERNEL_RCSID(0, "$NetBSD: esm.c,v 1.25 2004/04/30 14:14:55 simonb Exp $"); 70 71 #include <sys/param.h> 72 #include <sys/systm.h> 73 #include <sys/kernel.h> 74 #include <sys/malloc.h> 75 #include <sys/device.h> 76 77 #include <machine/bus.h> 78 79 #include <sys/audioio.h> 80 #include <dev/audio_if.h> 81 #include <dev/mulaw.h> 82 #include <dev/auconv.h> 83 #include <dev/ic/ac97var.h> 84 #include <dev/ic/ac97reg.h> 85 86 #include <dev/pci/pcidevs.h> 87 #include <dev/pci/pcivar.h> 88 89 #include <dev/pci/esmreg.h> 90 #include <dev/pci/esmvar.h> 91 92 #define PCI_CBIO 0x10 /* Configuration Base I/O Address */ 93 94 /* Debug */ 95 #ifdef AUDIO_DEBUG 96 #define DPRINTF(l,x) do { if (esm_debug & (l)) printf x; } while(0) 97 #define DUMPREG(x) do { if (esm_debug & ESM_DEBUG_REG) \ 98 esm_dump_regs(x); } while(0) 99 int esm_debug = 0xfffc; 100 #define ESM_DEBUG_CODECIO 0x0001 101 #define ESM_DEBUG_IRQ 0x0002 102 #define ESM_DEBUG_DMA 0x0004 103 #define ESM_DEBUG_TIMER 0x0008 104 #define ESM_DEBUG_REG 0x0010 105 #define ESM_DEBUG_PARAM 0x0020 106 #define ESM_DEBUG_APU 0x0040 107 #define ESM_DEBUG_CODEC 0x0080 108 #define ESM_DEBUG_PCI 0x0100 109 #define ESM_DEBUG_RESUME 0x0200 110 #else 111 #define DPRINTF(x,y) /* nothing */ 112 #define DUMPREG(x) /* nothing */ 113 #endif 114 115 #ifdef DIAGNOSTIC 116 #define RANGE(n, l, h) if ((n) < (l) || (n) >= (h)) \ 117 printf (#n "=%d out of range (%d, %d) in " \ 118 __FILE__ ", line %d\n", (n), (l), (h), __LINE__) 119 #else 120 #define RANGE(x,y,z) /* nothing */ 121 #endif 122 123 #define inline __inline 124 125 static inline void ringbus_setdest(struct esm_softc *, int, int); 126 127 static inline u_int16_t wp_rdreg(struct esm_softc *, u_int16_t); 128 static inline void wp_wrreg(struct esm_softc *, u_int16_t, u_int16_t); 129 static inline u_int16_t wp_rdapu(struct esm_softc *, int, u_int16_t); 130 static inline void wp_wrapu(struct esm_softc *, int, u_int16_t, 131 u_int16_t); 132 static inline void wp_settimer(struct esm_softc *, u_int); 133 static inline void wp_starttimer(struct esm_softc *); 134 static inline void wp_stoptimer(struct esm_softc *); 135 136 static inline u_int16_t wc_rdreg(struct esm_softc *, u_int16_t); 137 static inline void wc_wrreg(struct esm_softc *, u_int16_t, u_int16_t); 138 static inline u_int16_t wc_rdchctl(struct esm_softc *, int); 139 static inline void wc_wrchctl(struct esm_softc *, int, u_int16_t); 140 141 static inline u_int calc_timer_freq(struct esm_chinfo*); 142 static void set_timer(struct esm_softc *); 143 144 static void esmch_set_format(struct esm_chinfo *, 145 struct audio_params *p); 146 static void esmch_combine_input(struct esm_softc *, 147 struct esm_chinfo *ch); 148 149 /* Power Management */ 150 void esm_powerhook(int, void *); 151 152 CFATTACH_DECL(esm, sizeof(struct esm_softc), 153 esm_match, esm_attach, NULL, NULL); 154 155 struct audio_hw_if esm_hw_if = { 156 esm_open, 157 esm_close, 158 NULL, /* drain */ 159 esm_query_encoding, 160 esm_set_params, 161 esm_round_blocksize, 162 NULL, /* commit_settings */ 163 esm_init_output, 164 esm_init_input, 165 NULL, /* start_output */ 166 NULL, /* start_input */ 167 esm_halt_output, 168 esm_halt_input, 169 NULL, /* speaker_ctl */ 170 esm_getdev, 171 NULL, /* getfd */ 172 esm_set_port, 173 esm_get_port, 174 esm_query_devinfo, 175 esm_malloc, 176 esm_free, 177 esm_round_buffersize, 178 esm_mappage, 179 esm_get_props, 180 esm_trigger_output, 181 esm_trigger_input, 182 NULL, 183 }; 184 185 struct audio_device esm_device = { 186 "ESS Maestro", 187 "", 188 "esm" 189 }; 190 191 192 static audio_encoding_t esm_encoding[] = { 193 { 0, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0 }, 194 { 1, AudioEmulaw, AUDIO_ENCODING_ULAW, 8, 195 AUDIO_ENCODINGFLAG_EMULATED }, 196 { 2, AudioEalaw, AUDIO_ENCODING_ALAW, 8, AUDIO_ENCODINGFLAG_EMULATED }, 197 { 3, AudioEslinear, AUDIO_ENCODING_SLINEAR, 8, 0 }, 198 { 4, AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0 }, 199 { 5, AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16, 200 AUDIO_ENCODINGFLAG_EMULATED }, 201 { 6, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16, 202 AUDIO_ENCODINGFLAG_EMULATED }, 203 { 7, AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16, 204 AUDIO_ENCODINGFLAG_EMULATED }, 205 }; 206 207 #define MAESTRO_NENCODINGS 8 208 209 210 static const struct esm_quirks esm_quirks[] = { 211 /* COMPAL 38W2 OEM Notebook, e.g. Dell INSPIRON 5000e */ 212 { PCI_VENDOR_COMPAL, PCI_PRODUCT_COMPAL_38W2, ESM_QUIRKF_SWAPPEDCH }, 213 214 /* COMPAQ Armada M700 Notebook */ 215 { PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_M700, ESM_QUIRKF_SWAPPEDCH }, 216 217 /* NEC Versa Pro LX VA26D */ 218 { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VA26D, ESM_QUIRKF_GPIO }, 219 220 /* NEC Versa LX */ 221 { PCI_VENDOR_NEC, PCI_PRODUCT_NEC_VERSALX, ESM_QUIRKF_GPIO }, 222 223 /* Toshiba Portege */ 224 { PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_PORTEGE, ESM_QUIRKF_SWAPPEDCH } 225 }; 226 227 enum esm_quirk_flags 228 esm_get_quirks(pcireg_t subid) 229 { 230 int i; 231 232 for (i = 0; i < (sizeof esm_quirks / sizeof esm_quirks[0]); i++) { 233 if (PCI_VENDOR(subid) == esm_quirks[i].eq_vendor && 234 PCI_PRODUCT(subid) == esm_quirks[i].eq_product) { 235 return esm_quirks[i].eq_quirks; 236 } 237 } 238 239 return 0; 240 } 241 242 243 #ifdef AUDIO_DEBUG 244 struct esm_reg_info { 245 int offset; /* register offset */ 246 int width; /* 1/2/4 bytes */ 247 } dump_regs[] = { 248 { PORT_WAVCACHE_CTRL, 2 }, 249 { PORT_HOSTINT_CTRL, 2 }, 250 { PORT_HOSTINT_STAT, 2 }, 251 { PORT_HWVOL_VOICE_SHADOW, 1 }, 252 { PORT_HWVOL_VOICE, 1 }, 253 { PORT_HWVOL_MASTER_SHADOW, 1 }, 254 { PORT_HWVOL_MASTER, 1 }, 255 { PORT_RINGBUS_CTRL, 4 }, 256 { PORT_GPIO_DATA, 2 }, 257 { PORT_GPIO_MASK, 2 }, 258 { PORT_GPIO_DIR, 2 }, 259 { PORT_ASSP_CTRL_A, 1 }, 260 { PORT_ASSP_CTRL_B, 1 }, 261 { PORT_ASSP_CTRL_C, 1 }, 262 { PORT_ASSP_INT_STAT, 1 } 263 }; 264 265 static void 266 esm_dump_regs(struct esm_softc *ess) 267 { 268 int i; 269 270 printf("%s registers:", ess->sc_dev.dv_xname); 271 for (i = 0; i < (sizeof dump_regs / sizeof dump_regs[0]); i++) { 272 if (i % 5 == 0) 273 printf("\n"); 274 printf("0x%2.2x: ", dump_regs[i].offset); 275 switch(dump_regs[i].width) { 276 case 4: 277 printf("%8.8x, ", bus_space_read_4(ess->st, ess->sh, 278 dump_regs[i].offset)); 279 break; 280 case 2: 281 printf("%4.4x, ", bus_space_read_2(ess->st, ess->sh, 282 dump_regs[i].offset)); 283 break; 284 default: 285 printf("%2.2x, ", 286 bus_space_read_1(ess->st, ess->sh, 287 dump_regs[i].offset)); 288 } 289 } 290 printf("\n"); 291 } 292 #endif 293 294 295 /* ----------------------------- 296 * Subsystems. 297 */ 298 299 /* Codec/Ringbus */ 300 301 /* -------------------------------------------------------------------- */ 302 303 int 304 esm_read_codec(void *sc, u_int8_t regno, u_int16_t *result) 305 { 306 struct esm_softc *ess = sc; 307 unsigned t; 308 309 /* We have to wait for a SAFE time to write addr/data */ 310 for (t = 0; t < 20; t++) { 311 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 312 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 313 break; 314 delay(2); /* 20.8us / 13 */ 315 } 316 if (t == 20) 317 printf("%s: esm_read_codec() PROGLESS timed out.\n", 318 ess->sc_dev.dv_xname); 319 320 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 321 CODEC_CMD_READ | regno); 322 delay(21); /* AC97 cycle = 20.8usec */ 323 324 /* Wait for data retrieve */ 325 for (t = 0; t < 20; t++) { 326 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 327 & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE) 328 break; 329 delay(2); /* 20.8us / 13 */ 330 } 331 if (t == 20) 332 /* Timed out, but perform dummy read. */ 333 printf("%s: esm_read_codec() RW_DONE timed out.\n", 334 ess->sc_dev.dv_xname); 335 336 *result = bus_space_read_2(ess->st, ess->sh, PORT_CODEC_REG); 337 338 return 0; 339 } 340 341 int 342 esm_write_codec(void *sc, u_int8_t regno, u_int16_t data) 343 { 344 struct esm_softc *ess = sc; 345 unsigned t; 346 347 /* We have to wait for a SAFE time to write addr/data */ 348 for (t = 0; t < 20; t++) { 349 if ((bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 350 & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS) 351 break; 352 delay(2); /* 20.8us / 13 */ 353 } 354 if (t == 20) { 355 /* Timed out. Abort writing. */ 356 printf("%s: esm_write_codec() PROGLESS timed out.\n", 357 ess->sc_dev.dv_xname); 358 return -1; 359 } 360 361 bus_space_write_2(ess->st, ess->sh, PORT_CODEC_REG, data); 362 bus_space_write_1(ess->st, ess->sh, PORT_CODEC_CMD, 363 CODEC_CMD_WRITE | regno); 364 365 return 0; 366 } 367 368 /* -------------------------------------------------------------------- */ 369 370 static inline void 371 ringbus_setdest(struct esm_softc *ess, int src, int dest) 372 { 373 u_int32_t data; 374 375 data = bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL); 376 data &= ~(0xfU << src); 377 data |= (0xfU & dest) << src; 378 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, data); 379 } 380 381 /* Wave Processor */ 382 383 static inline u_int16_t 384 wp_rdreg(struct esm_softc *ess, u_int16_t reg) 385 { 386 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 387 return bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA); 388 } 389 390 static inline void 391 wp_wrreg(struct esm_softc *ess, u_int16_t reg, u_int16_t data) 392 { 393 bus_space_write_2(ess->st, ess->sh, PORT_DSP_INDEX, reg); 394 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 395 } 396 397 static inline void 398 apu_setindex(struct esm_softc *ess, u_int16_t reg) 399 { 400 int t; 401 402 wp_wrreg(ess, WPREG_CRAM_PTR, reg); 403 /* Sometimes WP fails to set apu register index. */ 404 for (t = 0; t < 1000; t++) { 405 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == reg) 406 break; 407 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, reg); 408 } 409 if (t == 1000) 410 printf("%s: apu_setindex() timed out.\n", ess->sc_dev.dv_xname); 411 } 412 413 static inline u_int16_t 414 wp_rdapu(struct esm_softc *ess, int ch, u_int16_t reg) 415 { 416 u_int16_t ret; 417 418 apu_setindex(ess, ((unsigned)ch << 4) + reg); 419 ret = wp_rdreg(ess, WPREG_DATA_PORT); 420 return ret; 421 } 422 423 static inline void 424 wp_wrapu(struct esm_softc *ess, int ch, u_int16_t reg, u_int16_t data) 425 { 426 int t; 427 428 DPRINTF(ESM_DEBUG_APU, 429 ("wp_wrapu(%p, ch=%d, reg=0x%x, data=0x%04x)\n", 430 ess, ch, reg, data)); 431 432 apu_setindex(ess, ((unsigned)ch << 4) + reg); 433 wp_wrreg(ess, WPREG_DATA_PORT, data); 434 for (t = 0; t < 1000; t++) { 435 if (bus_space_read_2(ess->st, ess->sh, PORT_DSP_DATA) == data) 436 break; 437 bus_space_write_2(ess->st, ess->sh, PORT_DSP_DATA, data); 438 } 439 if (t == 1000) 440 printf("%s: wp_wrapu() timed out.\n", ess->sc_dev.dv_xname); 441 } 442 443 static inline void 444 wp_settimer(struct esm_softc *ess, u_int freq) 445 { 446 u_int clock = 48000 << 2; 447 u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0; 448 449 RANGE(divide, WPTIMER_MINDIV, WPTIMER_MAXDIV); 450 451 for (; divide > 32 << 1; divide >>= 1) 452 prescale++; 453 divide = (divide + 1) >> 1; 454 455 for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1) 456 prescale++; 457 458 DPRINTF(ESM_DEBUG_TIMER, 459 ("wp_settimer(%p, %u): clock = %u, prescale = %u, divide = %u\n", 460 ess, freq, clock, prescale, divide)); 461 462 wp_wrreg(ess, WPREG_TIMER_ENABLE, 0); 463 wp_wrreg(ess, WPREG_TIMER_FREQ, 464 (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1)); 465 wp_wrreg(ess, WPREG_TIMER_ENABLE, 1); 466 } 467 468 static inline void 469 wp_starttimer(struct esm_softc *ess) 470 { 471 wp_wrreg(ess, WPREG_TIMER_START, 1); 472 } 473 474 static inline void 475 wp_stoptimer(struct esm_softc *ess) 476 { 477 wp_wrreg(ess, WPREG_TIMER_START, 0); 478 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 479 } 480 481 /* WaveCache */ 482 483 static inline u_int16_t 484 wc_rdreg(struct esm_softc *ess, u_int16_t reg) 485 { 486 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 487 return bus_space_read_2(ess->st, ess->sh, PORT_WAVCACHE_DATA); 488 } 489 490 static inline void 491 wc_wrreg(struct esm_softc *ess, u_int16_t reg, u_int16_t data) 492 { 493 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_INDEX, reg); 494 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_DATA, data); 495 } 496 497 static inline u_int16_t 498 wc_rdchctl(struct esm_softc *ess, int ch) 499 { 500 return wc_rdreg(ess, ch << 3); 501 } 502 503 static inline void 504 wc_wrchctl(struct esm_softc *ess, int ch, u_int16_t data) 505 { 506 wc_wrreg(ess, ch << 3, data); 507 } 508 509 /* Power management */ 510 511 void 512 esm_power(struct esm_softc *ess, int status) 513 { 514 pcireg_t data; 515 int pmcapreg; 516 517 if (pci_get_capability(ess->pc, ess->tag, PCI_CAP_PWRMGMT, 518 &pmcapreg, 0)) { 519 data = pci_conf_read(ess->pc, ess->tag, pmcapreg + PCI_PMCSR); 520 if ((data && PCI_PMCSR_STATE_MASK) != status) 521 pci_conf_write(ess->pc, ess->tag, 522 pmcapreg + PCI_PMCSR, status); 523 } 524 } 525 526 527 /* ----------------------------- 528 * Controller. 529 */ 530 531 int 532 esm_attach_codec(void *sc, struct ac97_codec_if *codec_if) 533 { 534 struct esm_softc *ess = sc; 535 536 ess->codec_if = codec_if; 537 538 return 0; 539 } 540 541 void 542 esm_reset_codec(void *sc) 543 { 544 } 545 546 547 enum ac97_host_flags 548 esm_flags_codec(void *sc) 549 { 550 struct esm_softc *ess = sc; 551 552 return ess->codec_flags; 553 } 554 555 556 void 557 esm_initcodec(struct esm_softc *ess) 558 { 559 u_int16_t data; 560 561 DPRINTF(ESM_DEBUG_CODEC, ("esm_initcodec(%p)\n", ess)); 562 563 if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL) 564 & RINGBUS_CTRL_ACLINK_ENABLED) { 565 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 566 delay(104); /* 20.8us * (4 + 1) */ 567 } 568 /* XXX - 2nd codec should be looked at. */ 569 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 570 RINGBUS_CTRL_AC97_SWRESET); 571 delay(2); 572 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 573 RINGBUS_CTRL_ACLINK_ENABLED); 574 delay(21); 575 576 esm_read_codec(ess, 0, &data); 577 if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 578 & CODEC_STAT_MASK) { 579 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 580 delay(21); 581 582 /* Try cold reset. */ 583 printf("%s: will perform cold reset.\n", ess->sc_dev.dv_xname); 584 data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR); 585 if (pci_conf_read(ess->pc, ess->tag, 0x58) & 1) 586 data |= 0x10; 587 data |= 0x009 & 588 ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA); 589 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6); 590 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 591 data | 0x009); 592 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000); 593 delay(2); 594 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001); 595 delay(1); 596 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009); 597 delay(500000); 598 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data); 599 delay(84); /* 20.8us * 4 */ 600 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 601 RINGBUS_CTRL_ACLINK_ENABLED); 602 delay(21); 603 } 604 } 605 606 void 607 esm_init(struct esm_softc *ess) 608 { 609 /* Reset direct sound. */ 610 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 611 HOSTINT_CTRL_DSOUND_RESET); 612 delay(10000); 613 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 614 delay(10000); 615 616 /* Enable direct sound interruption. */ 617 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 618 HOSTINT_CTRL_DSOUND_INT_ENABLED); 619 620 /* Setup Wave Processor. */ 621 622 /* Enable WaveCache */ 623 wp_wrreg(ess, WPREG_WAVE_ROMRAM, 624 WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED); 625 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL, 626 WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB); 627 628 /* Setup Codec/Ringbus. */ 629 esm_initcodec(ess); 630 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 631 RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED); 632 633 /* Undocumented registers from the Linux driver. */ 634 wp_wrreg(ess, 0x8, 0xB004); 635 wp_wrreg(ess, 0x9, 0x001B); 636 wp_wrreg(ess, 0xA, 0x8000); 637 wp_wrreg(ess, 0xB, 0x3F37); 638 wp_wrreg(ess, 0xD, 0x7632); 639 640 wp_wrreg(ess, WPREG_BASE, 0x8598); /* Parallel I/O */ 641 ringbus_setdest(ess, RINGBUS_SRC_ADC, 642 RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN); 643 ringbus_setdest(ess, RINGBUS_SRC_DSOUND, 644 RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC); 645 646 /* Setup ASSP. Needed for Dell Inspiron 7500? */ 647 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00); 648 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03); 649 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00); 650 651 /* 652 * Setup GPIO. 653 * There seems to be speciality with NEC systems. 654 */ 655 if (esm_get_quirks(ess->subid) & ESM_QUIRKF_GPIO) { 656 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 657 0x9ff); 658 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 659 bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 660 0x600); 661 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 662 0x200); 663 } 664 665 DUMPREG(ess); 666 } 667 668 669 /* Channel controller. */ 670 671 int 672 esm_init_output (void *sc, void *start, int size) 673 { 674 struct esm_softc *ess = sc; 675 struct esm_dma *p; 676 677 p = &ess->sc_dma; 678 if ((caddr_t)start != p->addr + MAESTRO_PLAYBUF_OFF) { 679 printf("%s: esm_init_output: bad addr %p\n", 680 ess->sc_dev.dv_xname, start); 681 return EINVAL; 682 } 683 684 ess->pch.base = DMAADDR(p) + MAESTRO_PLAYBUF_OFF; 685 686 DPRINTF(ESM_DEBUG_DMA, ("%s: pch.base = 0x%x\n", 687 ess->sc_dev.dv_xname, ess->pch.base)); 688 689 return 0; 690 } 691 692 int 693 esm_init_input (void *sc, void *start, int size) 694 { 695 struct esm_softc *ess = sc; 696 struct esm_dma *p; 697 698 p = &ess->sc_dma; 699 if ((caddr_t)start != p->addr + MAESTRO_RECBUF_OFF) { 700 printf("%s: esm_init_input: bad addr %p\n", 701 ess->sc_dev.dv_xname, start); 702 return EINVAL; 703 } 704 705 switch (ess->rch.aputype) { 706 case APUTYPE_16BITSTEREO: 707 ess->rch.base = DMAADDR(p) + MAESTRO_RECBUF_L_OFF; 708 break; 709 default: 710 ess->rch.base = DMAADDR(p) + MAESTRO_RECBUF_OFF; 711 break; 712 } 713 714 DPRINTF(ESM_DEBUG_DMA, ("%s: rch.base = 0x%x\n", 715 ess->sc_dev.dv_xname, ess->rch.base)); 716 717 return 0; 718 } 719 720 int 721 esm_trigger_output(void *sc, void *start, void *end, int blksize, 722 void (*intr)(void *), void *arg, struct audio_params *param) 723 { 724 struct esm_softc *ess = sc; 725 struct esm_chinfo *ch = &ess->pch; 726 struct esm_dma *p; 727 int pan = 0, choffset; 728 int i, nch = 1; 729 unsigned speed = ch->sample_rate, offset, wpwa, dv; 730 size_t size; 731 u_int16_t apuch = ch->num << 1; 732 733 DPRINTF(ESM_DEBUG_DMA, 734 ("esm_trigger_output(%p, %p, %p, 0x%x, %p, %p, %p)\n", 735 sc, start, end, blksize, intr, arg, param)); 736 737 #ifdef DIAGNOSTIC 738 if (ess->pactive) { 739 printf("%s: esm_trigger_output: already running", 740 ess->sc_dev.dv_xname); 741 return EINVAL; 742 } 743 #endif 744 745 ess->sc_pintr = intr; 746 ess->sc_parg = arg; 747 p = &ess->sc_dma; 748 if ((caddr_t)start != p->addr + MAESTRO_PLAYBUF_OFF) { 749 printf("%s: esm_trigger_output: bad addr %p\n", 750 ess->sc_dev.dv_xname, start); 751 return EINVAL; 752 } 753 754 ess->pch.blocksize = blksize; 755 ess->pch.apublk = blksize >> 1; 756 ess->pactive = 1; 757 758 size = (size_t)(((caddr_t)end - (caddr_t)start) >> 1); 759 choffset = MAESTRO_PLAYBUF_OFF; 760 offset = choffset >> 1; 761 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 762 763 DPRINTF(ESM_DEBUG_DMA, 764 ("choffs=0x%x, wpwa=0x%x, size=0x%x words\n", 765 choffset, wpwa, size)); 766 767 switch (ch->aputype) { 768 case APUTYPE_16BITSTEREO: 769 ess->pch.apublk >>= 1; 770 wpwa >>= 1; 771 size >>= 1; 772 offset >>= 1; 773 /* FALLTHROUGH */ 774 case APUTYPE_8BITSTEREO: 775 if (ess->codec_flags & AC97_HOST_SWAPPED_CHANNELS) 776 pan = 8; 777 else 778 pan = -8; 779 nch++; 780 break; 781 case APUTYPE_8BITLINEAR: 782 ess->pch.apublk <<= 1; 783 speed >>= 1; 784 break; 785 } 786 787 ess->pch.apubase = offset; 788 ess->pch.apubuf = size; 789 ess->pch.nextirq = ess->pch.apublk; 790 791 set_timer(ess); 792 wp_starttimer(ess); 793 794 dv = (((speed % 48000) << 16) + 24000) / 48000 795 + ((speed / 48000) << 16); 796 797 for (i = nch-1; i >= 0; i--) { 798 wp_wrapu(ess, apuch + i, APUREG_WAVESPACE, wpwa & 0xff00); 799 wp_wrapu(ess, apuch + i, APUREG_CURPTR, offset); 800 wp_wrapu(ess, apuch + i, APUREG_ENDPTR, offset + size); 801 wp_wrapu(ess, apuch + i, APUREG_LOOPLEN, size - 1); 802 wp_wrapu(ess, apuch + i, APUREG_AMPLITUDE, 0xe800); 803 wp_wrapu(ess, apuch + i, APUREG_POSITION, 0x8f00 804 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 805 | ((PAN_FRONT + pan) << APU_PAN_SHIFT)); 806 wp_wrapu(ess, apuch + i, APUREG_FREQ_LOBYTE, APU_plus6dB 807 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT)); 808 wp_wrapu(ess, apuch + i, APUREG_FREQ_HIWORD, dv >> 8); 809 810 if (ch->aputype == APUTYPE_16BITSTEREO) 811 wpwa |= APU_STEREO >> 1; 812 pan = -pan; 813 } 814 815 wc_wrchctl(ess, apuch, ch->wcreg_tpl); 816 if (nch > 1) 817 wc_wrchctl(ess, apuch + 1, ch->wcreg_tpl); 818 819 wp_wrapu(ess, apuch, APUREG_APUTYPE, 820 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 821 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) 822 wp_wrapu(ess, apuch + 1, APUREG_APUTYPE, 823 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 824 825 return 0; 826 } 827 828 829 int 830 esm_trigger_input(void *sc, void *start, void *end, int blksize, 831 void (*intr)(void *), void *arg, struct audio_params *param) 832 { 833 struct esm_softc *ess = sc; 834 struct esm_chinfo *ch = &ess->rch; 835 struct esm_dma *p; 836 u_int32_t chctl, choffset; 837 int i, nch = 1; 838 u_int32_t speed = ch->sample_rate, offset, wpwa, dv; 839 size_t size; 840 u_int16_t apuch = ch->num << 1; 841 u_int32_t mixoffset, mixdv; 842 size_t mixsize; 843 u_int16_t reg; 844 845 DPRINTF(ESM_DEBUG_DMA, 846 ("esm_trigger_input(%p, %p, %p, 0x%x, %p, %p, %p)\n", 847 sc, start, end, blksize, intr, arg, param)); 848 849 #ifdef DIAGNOSTIC 850 if (ess->ractive) { 851 printf("%s: esm_trigger_input: already running", 852 ess->sc_dev.dv_xname); 853 return EINVAL; 854 } 855 #endif 856 857 ess->sc_rintr = intr; 858 ess->sc_rarg = arg; 859 p = &ess->sc_dma; 860 if ((caddr_t)start != p->addr + MAESTRO_RECBUF_OFF) { 861 printf("%s: esm_trigger_input: bad addr %p\n", 862 ess->sc_dev.dv_xname, start); 863 return EINVAL; 864 } 865 866 ess->rch.buffer = (caddr_t)start; 867 ess->rch.offset = 0; 868 ess->rch.blocksize = blksize; 869 ess->rch.bufsize = ((caddr_t)end - (caddr_t)start); 870 ess->rch.apublk = blksize >> 1; 871 ess->ractive = 1; 872 873 size = (size_t)(((caddr_t)end - (caddr_t)start) >> 1); 874 choffset = MAESTRO_RECBUF_OFF; 875 switch (ch->aputype) { 876 case APUTYPE_16BITSTEREO: 877 size >>= 1; 878 choffset = MAESTRO_RECBUF_L_OFF; 879 ess->rch.apublk >>= 1; 880 nch++; 881 break; 882 case APUTYPE_16BITLINEAR: 883 break; 884 default: 885 ess->ractive = 0; 886 return EINVAL; 887 } 888 889 mixsize = (MAESTRO_MIXBUF_SZ >> 1) >> 1; 890 mixoffset = MAESTRO_MIXBUF_OFF; 891 892 ess->rch.apubase = (choffset >> 1); 893 ess->rch.apubuf = size; 894 ess->rch.nextirq = ess->rch.apublk; 895 896 set_timer(ess); 897 wp_starttimer(ess); 898 899 if (speed > 47999) speed = 47999; 900 if (speed < 4000) speed = 4000; 901 dv = (((speed % 48000) << 16) + 24000) / 48000 902 + ((speed / 48000) << 16); 903 mixdv = 65536; /* 48KHz */ 904 905 for (i = 0; i < nch; i++) { 906 907 /* Clear all rate conversion WP channel registers first. */ 908 for (reg = 0; reg < 15; reg++) 909 wp_wrapu(ess, apuch + i, reg, 0); 910 911 /* Program the WaveCache for the rate conversion WP channel. */ 912 chctl = (DMAADDR(p) + choffset - 0x10) & 913 WAVCACHE_CHCTL_ADDRTAG_MASK; 914 wc_wrchctl(ess, apuch + i, chctl); 915 916 /* Program the rate conversion WP channel. */ 917 wp_wrapu(ess, apuch + i, APUREG_FREQ_LOBYTE, APU_plus6dB 918 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT) | 0x08); 919 wp_wrapu(ess, apuch + i, APUREG_FREQ_HIWORD, dv >> 8); 920 offset = choffset >> 1; 921 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 922 wp_wrapu(ess, apuch + i, APUREG_WAVESPACE, wpwa); 923 wp_wrapu(ess, apuch + i, APUREG_CURPTR, offset); 924 wp_wrapu(ess, apuch + i, APUREG_ENDPTR, offset + size); 925 wp_wrapu(ess, apuch + i, APUREG_LOOPLEN, size - 1); 926 wp_wrapu(ess, apuch + i, APUREG_EFFECTS_ENV, 0x00f0); 927 wp_wrapu(ess, apuch + i, APUREG_AMPLITUDE, 0xe800); 928 wp_wrapu(ess, apuch + i, APUREG_POSITION, 0x8f00 929 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 930 | (PAN_FRONT << APU_PAN_SHIFT)); 931 wp_wrapu(ess, apuch + i, APUREG_ROUTE, apuch + 2 + i); 932 933 DPRINTF(ESM_DEBUG_DMA, 934 ("choffs=0x%x, wpwa=0x%x, offset=0x%x words, size=0x%x words\n", 935 choffset, wpwa, offset, size)); 936 937 /* Clear all mixer WP channel registers first. */ 938 for (reg = 0; reg < 15; reg++) 939 wp_wrapu(ess, apuch + 2 + i, reg, 0); 940 941 /* Program the WaveCache for the mixer WP channel. */ 942 chctl = (ess->rch.base + mixoffset - 0x10) & 943 WAVCACHE_CHCTL_ADDRTAG_MASK; 944 wc_wrchctl(ess, apuch + 2 + i, chctl); 945 946 /* Program the mixer WP channel. */ 947 wp_wrapu(ess, apuch + 2 + i, APUREG_FREQ_LOBYTE, APU_plus6dB 948 | ((mixdv & 0xff) << APU_FREQ_LOBYTE_SHIFT) | 0x08); 949 wp_wrapu(ess, apuch + 2 + i, APUREG_FREQ_HIWORD, mixdv >> 8); 950 offset = mixoffset >> 1; 951 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 952 wp_wrapu(ess, apuch + 2 + i, APUREG_WAVESPACE, wpwa); 953 wp_wrapu(ess, apuch + 2 + i, APUREG_CURPTR, offset); 954 wp_wrapu(ess, apuch + 2 + i, APUREG_ENDPTR, 955 offset + mixsize); 956 wp_wrapu(ess, apuch + 2 + i, APUREG_LOOPLEN, mixsize); 957 wp_wrapu(ess, apuch + 2 + i, APUREG_EFFECTS_ENV, 0x00f0); 958 wp_wrapu(ess, apuch + 2 + i, APUREG_AMPLITUDE, 0xe800); 959 wp_wrapu(ess, apuch + 2 + i, APUREG_POSITION, 0x8f00 960 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 961 | (PAN_FRONT << APU_PAN_SHIFT)); 962 wp_wrapu(ess, apuch + 2 + i, APUREG_ROUTE, 963 ROUTE_PARALLEL + i); 964 965 DPRINTF(ESM_DEBUG_DMA, 966 ("mixoffs=0x%x, wpwa=0x%x, offset=0x%x words, size=0x%x words\n", 967 mixoffset, wpwa, offset, mixsize)); 968 969 /* Assume we're going to loop to do the right channel. */ 970 choffset += MAESTRO_RECBUF_L_SZ; 971 mixoffset += MAESTRO_MIXBUF_SZ >> 1; 972 } 973 974 wp_wrapu(ess, apuch, APUREG_APUTYPE, 975 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 976 APU_DMA_ENABLED | 0xf); 977 if (nch > 1) 978 wp_wrapu(ess, apuch + 1, APUREG_APUTYPE, 979 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 980 APU_DMA_ENABLED | 0xf); 981 wp_wrapu(ess, apuch + 2, APUREG_APUTYPE, 982 (APUTYPE_INPUTMIXER << APU_APUTYPE_SHIFT) | 983 APU_DMA_ENABLED | 0xf); 984 if (nch > 1) 985 wp_wrapu(ess, apuch + 3, APUREG_APUTYPE, 986 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 987 APU_DMA_ENABLED | 0xf); 988 989 return 0; 990 } 991 992 993 int 994 esm_halt_output(void *sc) 995 { 996 struct esm_softc *ess = sc; 997 struct esm_chinfo *ch = &ess->pch; 998 999 DPRINTF(ESM_DEBUG_PARAM, ("esm_halt_output(%p)\n", sc)); 1000 1001 wp_wrapu(ess, (ch->num << 1), APUREG_APUTYPE, 1002 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1003 wp_wrapu(ess, (ch->num << 1) + 1, APUREG_APUTYPE, 1004 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1005 1006 ess->pactive = 0; 1007 if (!ess->ractive) 1008 wp_stoptimer(ess); 1009 1010 return 0; 1011 } 1012 1013 1014 int 1015 esm_halt_input(void *sc) 1016 { 1017 struct esm_softc *ess = sc; 1018 struct esm_chinfo *ch = &ess->rch; 1019 1020 DPRINTF(ESM_DEBUG_PARAM, ("esm_halt_input(%p)\n", sc)); 1021 1022 wp_wrapu(ess, (ch->num << 1), APUREG_APUTYPE, 1023 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1024 wp_wrapu(ess, (ch->num << 1) + 1, APUREG_APUTYPE, 1025 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1026 wp_wrapu(ess, (ch->num << 1) + 2, APUREG_APUTYPE, 1027 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1028 wp_wrapu(ess, (ch->num << 1) + 3, APUREG_APUTYPE, 1029 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1030 1031 ess->ractive = 0; 1032 if (!ess->pactive) 1033 wp_stoptimer(ess); 1034 1035 return 0; 1036 } 1037 1038 1039 static inline u_int 1040 calc_timer_freq(struct esm_chinfo *ch) 1041 { 1042 u_int freq; 1043 1044 freq = (ch->sample_rate + ch->apublk - 1) / ch->apublk; 1045 1046 DPRINTF(ESM_DEBUG_TIMER, 1047 ("calc_timer_freq(%p): rate = %u, blk = 0x%x (0x%x): freq = %u\n", 1048 ch, ch->sample_rate, ch->apublk, ch->blocksize, freq)); 1049 1050 return freq; 1051 } 1052 1053 static void 1054 set_timer(struct esm_softc *ess) 1055 { 1056 unsigned freq = 0, freq2; 1057 1058 if (ess->pactive) 1059 freq = calc_timer_freq(&ess->pch); 1060 1061 if (ess->ractive) { 1062 freq2 = calc_timer_freq(&ess->rch); 1063 if (freq2 > freq) 1064 freq = freq2; 1065 } 1066 1067 KASSERT(freq != 0); 1068 1069 for (; freq < MAESTRO_MINFREQ; freq <<= 1) 1070 ; 1071 1072 if (freq > 0) 1073 wp_settimer(ess, freq); 1074 } 1075 1076 1077 static void 1078 esmch_set_format(struct esm_chinfo *ch, struct audio_params *p) 1079 { 1080 u_int16_t wcreg_tpl = (ch->base - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK; 1081 u_int16_t aputype = APUTYPE_16BITLINEAR; 1082 1083 if (p->channels == 2) { 1084 wcreg_tpl |= WAVCACHE_CHCTL_STEREO; 1085 aputype++; 1086 } 1087 if (p->precision * p->factor == 8) { 1088 aputype += 2; 1089 switch (p->encoding) { 1090 case AUDIO_ENCODING_ULINEAR: 1091 case AUDIO_ENCODING_ULINEAR_BE: 1092 case AUDIO_ENCODING_ULINEAR_LE: 1093 wcreg_tpl |= WAVCACHE_CHCTL_U8; 1094 break; 1095 } 1096 } 1097 ch->wcreg_tpl = wcreg_tpl; 1098 ch->aputype = aputype; 1099 ch->sample_rate = p->sample_rate; 1100 1101 DPRINTF(ESM_DEBUG_PARAM, ("esmch_set_format: " 1102 "numch=%d, prec=%d*%d, tpl=0x%x, aputype=%d, rate=%ld\n", 1103 p->channels, p->precision, p->factor, wcreg_tpl, aputype, 1104 p->sample_rate)); 1105 } 1106 1107 /* 1108 * Since we can't record in true stereo, this function combines 1109 * the separately recorded left and right channels into the final 1110 * buffer for the upper layer. 1111 */ 1112 static void 1113 esmch_combine_input(struct esm_softc *ess, struct esm_chinfo *ch) 1114 { 1115 u_int32_t *dst32s; 1116 size_t offset, resid, count; 1117 const u_int32_t *left32s, *right32s; 1118 u_int32_t left32, right32; 1119 1120 /* The current offset into the upper layer buffer. */ 1121 offset = ch->offset; 1122 1123 /* The number of bytes left to combine. */ 1124 resid = ch->blocksize; 1125 1126 while (resid > 0) { 1127 1128 /* The 32-bit words for the left channel. */ 1129 left32s = (const u_int32_t *)(ess->sc_dma.addr + 1130 MAESTRO_RECBUF_L_OFF + offset / 2); 1131 1132 /* The 32-bit words for the right channel. */ 1133 right32s = (const u_int32_t *)(ess->sc_dma.addr + 1134 MAESTRO_RECBUF_R_OFF + offset / 2); 1135 1136 /* The pointer to the 32-bit words we will write. */ 1137 dst32s = (u_int32_t *)(ch->buffer + offset); 1138 1139 /* Get the number of bytes we will combine now. */ 1140 count = ch->bufsize - offset; 1141 if (count > resid) 1142 count = resid; 1143 resid -= count; 1144 offset += count; 1145 if (offset == ch->bufsize) 1146 offset = 0; 1147 1148 /* Combine, writing two 32-bit words at a time. */ 1149 KASSERT((count & (sizeof(uint32_t) * 2 - 1)) == 0); 1150 count /= (sizeof(u_int32_t) * 2); 1151 while (count > 0) { 1152 left32 = *(left32s++); 1153 right32 = *(right32s++); 1154 /* XXX this endian handling is half-baked at best */ 1155 #if BYTE_ORDER == LITTLE_ENDIAN 1156 *(dst32s++) = (left32 & 0xFFFF) | (right32 << 16); 1157 *(dst32s++) = (left32 >> 16) | (right32 & 0xFFFF0000); 1158 #else /* BYTE_ORDER == BIG_ENDIAN */ 1159 *(dst32s++) = (left32 & 0xFFFF0000) | (right32 >> 16); 1160 *(dst32s++) = (left32 << 16) | (right32 & 0xFFFF); 1161 #endif /* BYTE_ORDER == BIG_ENDIAN */ 1162 count--; 1163 } 1164 } 1165 1166 /* Update the offset. */ 1167 ch->offset = offset; 1168 } 1169 1170 /* 1171 * Audio interface glue functions 1172 */ 1173 1174 int 1175 esm_open(void *sc, int flags) 1176 { 1177 DPRINTF(ESM_DEBUG_PARAM, ("esm_open(%p, 0x%x)\n", sc, flags)); 1178 1179 return 0; 1180 } 1181 1182 1183 void 1184 esm_close(void *sc) 1185 { 1186 DPRINTF(ESM_DEBUG_PARAM, ("esm_close(%p)\n", sc)); 1187 } 1188 1189 1190 int 1191 esm_getdev (void *sc, struct audio_device *adp) 1192 { 1193 *adp = esm_device; 1194 return 0; 1195 } 1196 1197 1198 int 1199 esm_round_blocksize (void *sc, int blk) 1200 { 1201 DPRINTF(ESM_DEBUG_PARAM, 1202 ("esm_round_blocksize(%p, 0x%x)", sc, blk)); 1203 1204 blk &= ~0x3f; /* keep good alignment */ 1205 1206 DPRINTF(ESM_DEBUG_PARAM, (" = 0x%x\n", blk)); 1207 1208 return blk; 1209 } 1210 1211 1212 int 1213 esm_query_encoding(void *sc, struct audio_encoding *fp) 1214 { 1215 DPRINTF(ESM_DEBUG_PARAM, 1216 ("esm_query_encoding(%p, %d)\n", sc, fp->index)); 1217 1218 if (fp->index < 0 || fp->index >= MAESTRO_NENCODINGS) 1219 return EINVAL; 1220 1221 *fp = esm_encoding[fp->index]; 1222 return 0; 1223 } 1224 1225 1226 int 1227 esm_set_params(void *sc, int setmode, int usemode, 1228 struct audio_params *play, struct audio_params *rec) 1229 { 1230 struct esm_softc *ess = sc; 1231 struct audio_params *p; 1232 int mode; 1233 1234 DPRINTF(ESM_DEBUG_PARAM, 1235 ("esm_set_params(%p, 0x%x, 0x%x, %p, %p)\n", 1236 sc, setmode, usemode, play, rec)); 1237 1238 for (mode = AUMODE_RECORD; mode != -1; 1239 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 1240 if ((setmode & mode) == 0) 1241 continue; 1242 1243 p = mode == AUMODE_PLAY ? play : rec; 1244 1245 if (p->sample_rate < 4000 || p->sample_rate > 48000 || 1246 (p->precision != 8 && p->precision != 16) || 1247 (p->channels != 1 && p->channels != 2)) 1248 return EINVAL; 1249 1250 p->factor = 1; 1251 p->sw_code = 0; 1252 switch (p->encoding) { 1253 case AUDIO_ENCODING_SLINEAR_BE: 1254 if (p->precision == 16) 1255 p->sw_code = swap_bytes; 1256 else 1257 p->sw_code = change_sign8; 1258 break; 1259 case AUDIO_ENCODING_SLINEAR_LE: 1260 if (p->precision != 16) 1261 p->sw_code = change_sign8; 1262 break; 1263 case AUDIO_ENCODING_ULINEAR_BE: 1264 if (p->precision == 16) { 1265 if (mode == AUMODE_PLAY) 1266 p->sw_code = swap_bytes_change_sign16_le; 1267 else 1268 p->sw_code = change_sign16_swap_bytes_le; 1269 } 1270 break; 1271 case AUDIO_ENCODING_ULINEAR_LE: 1272 if (p->precision == 16) 1273 p->sw_code = change_sign16_le; 1274 break; 1275 case AUDIO_ENCODING_ULAW: 1276 if (mode == AUMODE_PLAY) { 1277 p->factor = 2; 1278 p->sw_code = mulaw_to_slinear16_le; 1279 } else 1280 p->sw_code = ulinear8_to_mulaw; 1281 break; 1282 case AUDIO_ENCODING_ALAW: 1283 if (mode == AUMODE_PLAY) { 1284 p->factor = 2; 1285 p->sw_code = alaw_to_slinear16_le; 1286 } else 1287 p->sw_code = ulinear8_to_alaw; 1288 break; 1289 default: 1290 return EINVAL; 1291 } 1292 } 1293 1294 if (setmode & AUMODE_PLAY) 1295 esmch_set_format(&ess->pch, play); 1296 1297 if (setmode & AUMODE_RECORD) 1298 esmch_set_format(&ess->rch, rec); 1299 1300 return 0; 1301 } 1302 1303 1304 int 1305 esm_set_port(void *sc, mixer_ctrl_t *cp) 1306 { 1307 struct esm_softc *ess = sc; 1308 1309 return (ess->codec_if->vtbl->mixer_set_port(ess->codec_if, cp)); 1310 } 1311 1312 1313 int 1314 esm_get_port(void *sc, mixer_ctrl_t *cp) 1315 { 1316 struct esm_softc *ess = sc; 1317 1318 return (ess->codec_if->vtbl->mixer_get_port(ess->codec_if, cp)); 1319 } 1320 1321 1322 int 1323 esm_query_devinfo(void *sc, mixer_devinfo_t *dip) 1324 { 1325 struct esm_softc *ess = sc; 1326 1327 return (ess->codec_if->vtbl->query_devinfo(ess->codec_if, dip)); 1328 } 1329 1330 1331 void * 1332 esm_malloc(void *sc, int direction, size_t size, struct malloc_type *pool, 1333 int flags) 1334 { 1335 struct esm_softc *ess = sc; 1336 int off; 1337 1338 DPRINTF(ESM_DEBUG_DMA, 1339 ("esm_malloc(%p, %d, 0x%x, %p, 0x%x)", 1340 sc, direction, size, pool, flags)); 1341 1342 /* 1343 * Each buffer can only be allocated once. 1344 */ 1345 if (ess->rings_alloced & direction) { 1346 DPRINTF(ESM_DEBUG_DMA, (" = 0 (ENOMEM)\n")); 1347 return 0; 1348 } 1349 1350 /* 1351 * Mark this buffer as allocated and return its 1352 * kernel virtual address. 1353 */ 1354 ess->rings_alloced |= direction; 1355 off = (direction == AUMODE_PLAY ? 1356 MAESTRO_PLAYBUF_OFF : MAESTRO_RECBUF_OFF); 1357 DPRINTF(ESM_DEBUG_DMA, (" = %p (DMAADDR 0x%x)\n", 1358 ess->sc_dma.addr + off, 1359 (int)DMAADDR(&ess->sc_dma) + off)); 1360 return (ess->sc_dma.addr + off); 1361 } 1362 1363 1364 void 1365 esm_free(void *sc, void *ptr, struct malloc_type *pool) 1366 { 1367 struct esm_softc *ess = sc; 1368 1369 DPRINTF(ESM_DEBUG_DMA, 1370 ("esm_free(%p, %p, %p)\n", 1371 sc, ptr, pool)); 1372 1373 if ((caddr_t)ptr == ess->sc_dma.addr + MAESTRO_PLAYBUF_OFF) 1374 ess->rings_alloced &= ~AUMODE_PLAY; 1375 else if ((caddr_t)ptr == ess->sc_dma.addr + MAESTRO_RECBUF_OFF) 1376 ess->rings_alloced &= ~AUMODE_RECORD; 1377 } 1378 1379 1380 size_t 1381 esm_round_buffersize(void *sc, int direction, size_t size) 1382 { 1383 if (size > MAESTRO_PLAYBUF_SZ) 1384 size = MAESTRO_PLAYBUF_SZ; 1385 if (size > MAESTRO_RECBUF_SZ) 1386 size = MAESTRO_RECBUF_SZ; 1387 return size; 1388 } 1389 1390 1391 paddr_t 1392 esm_mappage(void *sc, void *mem, off_t off, int prot) 1393 { 1394 struct esm_softc *ess = sc; 1395 1396 DPRINTF(ESM_DEBUG_DMA, 1397 ("esm_mappage(%p, %p, 0x%lx, 0x%x)\n", 1398 sc, mem, (unsigned long)off, prot)); 1399 1400 if (off < 0) 1401 return (-1); 1402 1403 if ((caddr_t)mem == ess->sc_dma.addr + MAESTRO_PLAYBUF_OFF) 1404 off += MAESTRO_PLAYBUF_OFF; 1405 else if ((caddr_t)mem == ess->sc_dma.addr + MAESTRO_RECBUF_OFF) 1406 off += MAESTRO_RECBUF_OFF; 1407 else 1408 return -1; 1409 return bus_dmamem_mmap(ess->dmat, ess->sc_dma.segs, ess->sc_dma.nsegs, 1410 off, prot, BUS_DMA_WAITOK); 1411 } 1412 1413 1414 int 1415 esm_get_props(void *sc) 1416 { 1417 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1418 } 1419 1420 1421 /* ----------------------------- 1422 * Bus space. 1423 */ 1424 1425 int 1426 esm_intr(void *sc) 1427 { 1428 struct esm_softc *ess = sc; 1429 u_int16_t status; 1430 u_int16_t pos; 1431 int ret = 0; 1432 1433 status = bus_space_read_1(ess->st, ess->sh, PORT_HOSTINT_STAT); 1434 if (!status) 1435 return 0; 1436 1437 /* Acknowledge all. */ 1438 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 1439 bus_space_write_1(ess->st, ess->sh, PORT_HOSTINT_STAT, 0); 1440 #if 0 /* XXX - HWVOL */ 1441 if (status & HOSTINT_STAT_HWVOL) { 1442 u_int delta; 1443 delta = bus_space_read_1(ess->st, ess->sh, PORT_HWVOL_MASTER) 1444 - 0x88; 1445 if (delta & 0x11) 1446 mixer_set(device_get_softc(ess->dev), 1447 SOUND_MIXER_VOLUME, 0); 1448 else { 1449 mixer_set(device_get_softc(ess->dev), 1450 SOUND_MIXER_VOLUME, 1451 mixer_get(device_get_softc(ess->dev), 1452 SOUND_MIXER_VOLUME) 1453 + ((delta >> 5) & 0x7) - 4 1454 + ((delta << 7) & 0x700) - 0x400); 1455 } 1456 bus_space_write_1(ess->st, ess->sh, PORT_HWVOL_MASTER, 0x88); 1457 ret++; 1458 } 1459 #endif /* XXX - HWVOL */ 1460 1461 if (ess->pactive) { 1462 pos = wp_rdapu(ess, ess->pch.num << 1, APUREG_CURPTR); 1463 1464 DPRINTF(ESM_DEBUG_IRQ, (" %4.4x/%4.4x ", pos, 1465 wp_rdapu(ess, (ess->pch.num<<1)+1, APUREG_CURPTR))); 1466 1467 pos -= ess->pch.apubase; 1468 if (pos >= ess->pch.nextirq && 1469 pos - ess->pch.nextirq < ess->pch.apubuf / 2) { 1470 ess->pch.nextirq += ess->pch.apublk; 1471 1472 if (ess->pch.nextirq >= ess->pch.apubuf) 1473 ess->pch.nextirq = 0; 1474 1475 if (ess->sc_pintr) { 1476 DPRINTF(ESM_DEBUG_IRQ, ("P\n")); 1477 ess->sc_pintr(ess->sc_parg); 1478 } 1479 1480 } 1481 ret++; 1482 } 1483 1484 if (ess->ractive) { 1485 pos = wp_rdapu(ess, ess->rch.num << 1, APUREG_CURPTR); 1486 1487 DPRINTF(ESM_DEBUG_IRQ, (" %4.4x/%4.4x ", pos, 1488 wp_rdapu(ess, (ess->rch.num<<1)+1, APUREG_CURPTR))); 1489 1490 pos -= ess->rch.apubase; 1491 if (pos >= ess->rch.nextirq && 1492 pos - ess->rch.nextirq < ess->rch.apubuf / 2) { 1493 ess->rch.nextirq += ess->rch.apublk; 1494 1495 if (ess->rch.nextirq >= ess->rch.apubuf) 1496 ess->rch.nextirq = 0; 1497 1498 if (ess->sc_rintr) { 1499 DPRINTF(ESM_DEBUG_IRQ, ("R\n")); 1500 switch(ess->rch.aputype) { 1501 case APUTYPE_16BITSTEREO: 1502 esmch_combine_input(ess, &ess->rch); 1503 break; 1504 } 1505 ess->sc_rintr(ess->sc_rarg); 1506 } 1507 1508 } 1509 ret++; 1510 } 1511 1512 return ret; 1513 } 1514 1515 1516 int 1517 esm_allocmem(struct esm_softc *sc, size_t size, size_t align, 1518 struct esm_dma *p) 1519 { 1520 int error; 1521 1522 p->size = size; 1523 error = bus_dmamem_alloc(sc->dmat, p->size, align, 0, 1524 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 1525 &p->nsegs, BUS_DMA_NOWAIT); 1526 if (error) 1527 return error; 1528 1529 error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size, 1530 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 1531 if (error) 1532 goto free; 1533 1534 error = bus_dmamap_create(sc->dmat, p->size, 1, p->size, 1535 0, BUS_DMA_NOWAIT, &p->map); 1536 if (error) 1537 goto unmap; 1538 1539 error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL, 1540 BUS_DMA_NOWAIT); 1541 if (error) 1542 goto destroy; 1543 1544 return 0; 1545 1546 destroy: 1547 bus_dmamap_destroy(sc->dmat, p->map); 1548 unmap: 1549 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 1550 free: 1551 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 1552 1553 return error; 1554 } 1555 1556 1557 int 1558 esm_match(struct device *dev, struct cfdata *match, void *aux) 1559 { 1560 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 1561 1562 switch (PCI_VENDOR(pa->pa_id)) { 1563 case PCI_VENDOR_ESSTECH: 1564 switch (PCI_PRODUCT(pa->pa_id)) { 1565 case PCI_PRODUCT_ESSTECH_MAESTRO1: 1566 case PCI_PRODUCT_ESSTECH_MAESTRO2: 1567 case PCI_PRODUCT_ESSTECH_MAESTRO2E: 1568 return 1; 1569 } 1570 1571 case PCI_VENDOR_ESSTECH2: 1572 switch (PCI_PRODUCT(pa->pa_id)) { 1573 case PCI_PRODUCT_ESSTECH2_MAESTRO1: 1574 return 1; 1575 } 1576 } 1577 return 0; 1578 } 1579 1580 void 1581 esm_attach(struct device *parent, struct device *self, void *aux) 1582 { 1583 struct esm_softc *ess = (struct esm_softc *)self; 1584 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 1585 pci_chipset_tag_t pc = pa->pa_pc; 1586 pcitag_t tag = pa->pa_tag; 1587 pci_intr_handle_t ih; 1588 pcireg_t csr, data; 1589 u_int16_t codec_data; 1590 u_int16_t pcmbar; 1591 const char *intrstr; 1592 int revision; 1593 char devinfo[256]; 1594 1595 aprint_naive(": Audio controller\n"); 1596 1597 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 1598 revision = PCI_REVISION(pa->pa_class); 1599 aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision); 1600 1601 /* Enable the device. */ 1602 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 1603 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, 1604 csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE); 1605 1606 /* Map I/O register */ 1607 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, 1608 &ess->st, &ess->sh, NULL, NULL)) { 1609 aprint_error("%s: can't map i/o space\n", ess->sc_dev.dv_xname); 1610 return; 1611 } 1612 1613 /* Initialize softc */ 1614 ess->pch.num = 0; 1615 ess->rch.num = 1; 1616 ess->dmat = pa->pa_dmat; 1617 ess->tag = tag; 1618 ess->pc = pc; 1619 ess->subid = pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG); 1620 1621 DPRINTF(ESM_DEBUG_PCI, 1622 ("%s: sub-system vendor 0x%4.4x, product 0x%4.4x\n", 1623 ess->sc_dev.dv_xname, 1624 PCI_VENDOR(ess->subid), PCI_PRODUCT(ess->subid))); 1625 1626 /* Map and establish the interrupt. */ 1627 if (pci_intr_map(pa, &ih)) { 1628 aprint_error("%s: can't map interrupt\n", ess->sc_dev.dv_xname); 1629 return; 1630 } 1631 intrstr = pci_intr_string(pc, ih); 1632 ess->ih = pci_intr_establish(pc, ih, IPL_AUDIO, esm_intr, self); 1633 if (ess->ih == NULL) { 1634 aprint_error("%s: can't establish interrupt", 1635 ess->sc_dev.dv_xname); 1636 if (intrstr != NULL) 1637 aprint_normal(" at %s", intrstr); 1638 aprint_normal("\n"); 1639 return; 1640 } 1641 aprint_normal("%s: interrupting at %s\n", 1642 ess->sc_dev.dv_xname, intrstr); 1643 1644 /* 1645 * Setup PCI config registers 1646 */ 1647 1648 /* set to power state D0 */ 1649 esm_power(ess, PCI_PMCSR_STATE_D0); 1650 delay(100000); 1651 1652 /* Disable all legacy emulations. */ 1653 data = pci_conf_read(pc, tag, CONF_LEGACY); 1654 pci_conf_write(pc, tag, CONF_LEGACY, data | LEGACY_DISABLED); 1655 1656 /* Disconnect from CHI. (Makes Dell inspiron 7500 work?) 1657 * Enable posted write. 1658 * Prefer PCI timing rather than that of ISA. 1659 * Don't swap L/R. */ 1660 data = pci_conf_read(pc, tag, CONF_MAESTRO); 1661 data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING; 1662 data &= ~MAESTRO_SWAP_LR; 1663 pci_conf_write(pc, tag, CONF_MAESTRO, data); 1664 1665 /* initialize sound chip */ 1666 esm_init(ess); 1667 1668 esm_read_codec(ess, 0, &codec_data); 1669 if (codec_data == 0x80) { 1670 aprint_error("%s: PT101 codec detected!\n", 1671 ess->sc_dev.dv_xname); 1672 return; 1673 } 1674 1675 /* 1676 * Some cards and Notebooks appear to have left and right channels 1677 * reversed. Check if there is a corresponding quirk entry for 1678 * the subsystem vendor and product and if so, set the appropriate 1679 * codec flag. 1680 */ 1681 if (esm_get_quirks(ess->subid) & ESM_QUIRKF_SWAPPEDCH) { 1682 ess->codec_flags |= AC97_HOST_SWAPPED_CHANNELS; 1683 } 1684 ess->codec_flags |= AC97_HOST_DONT_READ; 1685 1686 /* initialize AC97 host interface */ 1687 ess->host_if.arg = self; 1688 ess->host_if.attach = esm_attach_codec; 1689 ess->host_if.read = esm_read_codec; 1690 ess->host_if.write = esm_write_codec; 1691 ess->host_if.reset = esm_reset_codec; 1692 ess->host_if.flags = esm_flags_codec; 1693 1694 if (ac97_attach(&ess->host_if) != 0) 1695 return; 1696 1697 /* allocate our DMA region */ 1698 if (esm_allocmem(ess, MAESTRO_DMA_SZ, MAESTRO_DMA_ALIGN, 1699 &ess->sc_dma)) { 1700 aprint_error("%s: couldn't allocate memory!\n", 1701 ess->sc_dev.dv_xname); 1702 return; 1703 } 1704 ess->rings_alloced = 0; 1705 1706 /* set DMA base address */ 1707 for (pcmbar = WAVCACHE_PCMBAR; pcmbar < WAVCACHE_PCMBAR + 4; pcmbar++) 1708 wc_wrreg(ess, pcmbar, 1709 DMAADDR(&ess->sc_dma) >> WAVCACHE_BASEADDR_SHIFT); 1710 1711 audio_attach_mi(&esm_hw_if, self, &ess->sc_dev); 1712 1713 ess->esm_suspend = PWR_RESUME; 1714 ess->esm_powerhook = powerhook_establish(esm_powerhook, ess); 1715 } 1716 1717 /* Power Hook */ 1718 void 1719 esm_powerhook(why, v) 1720 int why; 1721 void *v; 1722 { 1723 struct esm_softc *ess = (struct esm_softc *)v; 1724 1725 DPRINTF(ESM_DEBUG_PARAM, 1726 ("%s: ESS maestro 2E why=%d\n", ess->sc_dev.dv_xname, why)); 1727 switch (why) { 1728 case PWR_SUSPEND: 1729 case PWR_STANDBY: 1730 ess->esm_suspend = why; 1731 esm_suspend(ess); 1732 DPRINTF(ESM_DEBUG_RESUME, ("esm_suspend\n")); 1733 break; 1734 1735 case PWR_RESUME: 1736 ess->esm_suspend = why; 1737 esm_resume(ess); 1738 DPRINTF(ESM_DEBUG_RESUME, ("esm_resumed\n")); 1739 break; 1740 } 1741 } 1742 1743 int 1744 esm_suspend(struct esm_softc *ess) 1745 { 1746 int x; 1747 1748 x = splaudio(); 1749 wp_stoptimer(ess); 1750 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 1751 1752 esm_halt_output(ess); 1753 esm_halt_input(ess); 1754 splx(x); 1755 1756 /* Power down everything except clock. */ 1757 esm_write_codec(ess, AC97_REG_POWER, 0xdf00); 1758 delay(20); 1759 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 1760 delay(1); 1761 esm_power(ess, PCI_PMCSR_STATE_D3); 1762 1763 return 0; 1764 } 1765 1766 int 1767 esm_resume(struct esm_softc *ess) 1768 { 1769 int x; 1770 1771 esm_power(ess, PCI_PMCSR_STATE_D0); 1772 delay(100000); 1773 esm_init(ess); 1774 1775 (*ess->codec_if->vtbl->restore_ports)(ess->codec_if); 1776 #if 0 1777 if (mixer_reinit(dev)) { 1778 printf("%s: unable to reinitialize the mixer\n", 1779 ess->sc_dev.dv_xname); 1780 return ENXIO; 1781 } 1782 #endif 1783 1784 x = splaudio(); 1785 #if TODO 1786 if (ess->pactive) 1787 esm_start_output(ess); 1788 if (ess->ractive) 1789 esm_start_input(ess); 1790 #endif 1791 if (ess->pactive || ess->ractive) { 1792 set_timer(ess); 1793 wp_starttimer(ess); 1794 } 1795 splx(x); 1796 return 0; 1797 } 1798 1799 #if 0 1800 int 1801 esm_shutdown(struct esm_softc *ess) 1802 { 1803 int i; 1804 1805 wp_stoptimer(ess); 1806 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 1807 1808 esm_halt_output(ess); 1809 esm_halt_input(ess); 1810 1811 return 0; 1812 } 1813 #endif 1814