1 /* $NetBSD: esm.c,v 1.28 2004/10/29 12:57:18 yamt 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.28 2004/10/29 12:57:18 yamt 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 const 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 int 542 esm_reset_codec(void *sc) 543 { 544 return 0; 545 } 546 547 548 enum ac97_host_flags 549 esm_flags_codec(void *sc) 550 { 551 struct esm_softc *ess = sc; 552 553 return ess->codec_flags; 554 } 555 556 557 void 558 esm_initcodec(struct esm_softc *ess) 559 { 560 u_int16_t data; 561 562 DPRINTF(ESM_DEBUG_CODEC, ("esm_initcodec(%p)\n", ess)); 563 564 if (bus_space_read_4(ess->st, ess->sh, PORT_RINGBUS_CTRL) 565 & RINGBUS_CTRL_ACLINK_ENABLED) { 566 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 567 delay(104); /* 20.8us * (4 + 1) */ 568 } 569 /* XXX - 2nd codec should be looked at. */ 570 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 571 RINGBUS_CTRL_AC97_SWRESET); 572 delay(2); 573 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 574 RINGBUS_CTRL_ACLINK_ENABLED); 575 delay(21); 576 577 esm_read_codec(ess, 0, &data); 578 if (bus_space_read_1(ess->st, ess->sh, PORT_CODEC_STAT) 579 & CODEC_STAT_MASK) { 580 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 581 delay(21); 582 583 /* Try cold reset. */ 584 printf("%s: will perform cold reset.\n", ess->sc_dev.dv_xname); 585 data = bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR); 586 if (pci_conf_read(ess->pc, ess->tag, 0x58) & 1) 587 data |= 0x10; 588 data |= 0x009 & 589 ~bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DATA); 590 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 0xff6); 591 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 592 data | 0x009); 593 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x000); 594 delay(2); 595 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x001); 596 delay(1); 597 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 0x009); 598 delay(500000); 599 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, data); 600 delay(84); /* 20.8us * 4 */ 601 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 602 RINGBUS_CTRL_ACLINK_ENABLED); 603 delay(21); 604 } 605 } 606 607 void 608 esm_init(struct esm_softc *ess) 609 { 610 /* Reset direct sound. */ 611 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 612 HOSTINT_CTRL_DSOUND_RESET); 613 delay(10000); 614 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 615 delay(10000); 616 617 /* Enable direct sound interruption. */ 618 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 619 HOSTINT_CTRL_DSOUND_INT_ENABLED); 620 621 /* Setup Wave Processor. */ 622 623 /* Enable WaveCache */ 624 wp_wrreg(ess, WPREG_WAVE_ROMRAM, 625 WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED); 626 bus_space_write_2(ess->st, ess->sh, PORT_WAVCACHE_CTRL, 627 WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB); 628 629 /* Setup Codec/Ringbus. */ 630 esm_initcodec(ess); 631 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 632 RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED); 633 634 /* Undocumented registers from the Linux driver. */ 635 wp_wrreg(ess, 0x8, 0xB004); 636 wp_wrreg(ess, 0x9, 0x001B); 637 wp_wrreg(ess, 0xA, 0x8000); 638 wp_wrreg(ess, 0xB, 0x3F37); 639 wp_wrreg(ess, 0xD, 0x7632); 640 641 wp_wrreg(ess, WPREG_BASE, 0x8598); /* Parallel I/O */ 642 ringbus_setdest(ess, RINGBUS_SRC_ADC, 643 RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN); 644 ringbus_setdest(ess, RINGBUS_SRC_DSOUND, 645 RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC); 646 647 /* Setup ASSP. Needed for Dell Inspiron 7500? */ 648 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_B, 0x00); 649 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_A, 0x03); 650 bus_space_write_1(ess->st, ess->sh, PORT_ASSP_CTRL_C, 0x00); 651 652 /* 653 * Setup GPIO. 654 * There seems to be speciality with NEC systems. 655 */ 656 if (esm_get_quirks(ess->subid) & ESM_QUIRKF_GPIO) { 657 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_MASK, 658 0x9ff); 659 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DIR, 660 bus_space_read_2(ess->st, ess->sh, PORT_GPIO_DIR) | 661 0x600); 662 bus_space_write_2(ess->st, ess->sh, PORT_GPIO_DATA, 663 0x200); 664 } 665 666 DUMPREG(ess); 667 } 668 669 670 /* Channel controller. */ 671 672 int 673 esm_init_output (void *sc, void *start, int size) 674 { 675 struct esm_softc *ess = sc; 676 struct esm_dma *p; 677 678 p = &ess->sc_dma; 679 if ((caddr_t)start != p->addr + MAESTRO_PLAYBUF_OFF) { 680 printf("%s: esm_init_output: bad addr %p\n", 681 ess->sc_dev.dv_xname, start); 682 return EINVAL; 683 } 684 685 ess->pch.base = DMAADDR(p) + MAESTRO_PLAYBUF_OFF; 686 687 DPRINTF(ESM_DEBUG_DMA, ("%s: pch.base = 0x%x\n", 688 ess->sc_dev.dv_xname, ess->pch.base)); 689 690 return 0; 691 } 692 693 int 694 esm_init_input (void *sc, void *start, int size) 695 { 696 struct esm_softc *ess = sc; 697 struct esm_dma *p; 698 699 p = &ess->sc_dma; 700 if ((caddr_t)start != p->addr + MAESTRO_RECBUF_OFF) { 701 printf("%s: esm_init_input: bad addr %p\n", 702 ess->sc_dev.dv_xname, start); 703 return EINVAL; 704 } 705 706 switch (ess->rch.aputype) { 707 case APUTYPE_16BITSTEREO: 708 ess->rch.base = DMAADDR(p) + MAESTRO_RECBUF_L_OFF; 709 break; 710 default: 711 ess->rch.base = DMAADDR(p) + MAESTRO_RECBUF_OFF; 712 break; 713 } 714 715 DPRINTF(ESM_DEBUG_DMA, ("%s: rch.base = 0x%x\n", 716 ess->sc_dev.dv_xname, ess->rch.base)); 717 718 return 0; 719 } 720 721 int 722 esm_trigger_output(void *sc, void *start, void *end, int blksize, 723 void (*intr)(void *), void *arg, struct audio_params *param) 724 { 725 struct esm_softc *ess = sc; 726 struct esm_chinfo *ch = &ess->pch; 727 struct esm_dma *p; 728 int pan = 0, choffset; 729 int i, nch = 1; 730 unsigned speed = ch->sample_rate, offset, wpwa, dv; 731 size_t size; 732 u_int16_t apuch = ch->num << 1; 733 734 DPRINTF(ESM_DEBUG_DMA, 735 ("esm_trigger_output(%p, %p, %p, 0x%x, %p, %p, %p)\n", 736 sc, start, end, blksize, intr, arg, param)); 737 738 #ifdef DIAGNOSTIC 739 if (ess->pactive) { 740 printf("%s: esm_trigger_output: already running", 741 ess->sc_dev.dv_xname); 742 return EINVAL; 743 } 744 #endif 745 746 ess->sc_pintr = intr; 747 ess->sc_parg = arg; 748 p = &ess->sc_dma; 749 if ((caddr_t)start != p->addr + MAESTRO_PLAYBUF_OFF) { 750 printf("%s: esm_trigger_output: bad addr %p\n", 751 ess->sc_dev.dv_xname, start); 752 return EINVAL; 753 } 754 755 ess->pch.blocksize = blksize; 756 ess->pch.apublk = blksize >> 1; 757 ess->pactive = 1; 758 759 size = (size_t)(((caddr_t)end - (caddr_t)start) >> 1); 760 choffset = MAESTRO_PLAYBUF_OFF; 761 offset = choffset >> 1; 762 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 763 764 DPRINTF(ESM_DEBUG_DMA, 765 ("choffs=0x%x, wpwa=0x%x, size=0x%lx words\n", 766 choffset, wpwa, (unsigned long int)size)); 767 768 switch (ch->aputype) { 769 case APUTYPE_16BITSTEREO: 770 ess->pch.apublk >>= 1; 771 wpwa >>= 1; 772 size >>= 1; 773 offset >>= 1; 774 /* FALLTHROUGH */ 775 case APUTYPE_8BITSTEREO: 776 if (ess->codec_flags & AC97_HOST_SWAPPED_CHANNELS) 777 pan = 8; 778 else 779 pan = -8; 780 nch++; 781 break; 782 case APUTYPE_8BITLINEAR: 783 ess->pch.apublk <<= 1; 784 speed >>= 1; 785 break; 786 } 787 788 ess->pch.apubase = offset; 789 ess->pch.apubuf = size; 790 ess->pch.nextirq = ess->pch.apublk; 791 792 set_timer(ess); 793 wp_starttimer(ess); 794 795 dv = (((speed % 48000) << 16) + 24000) / 48000 796 + ((speed / 48000) << 16); 797 798 for (i = nch-1; i >= 0; i--) { 799 wp_wrapu(ess, apuch + i, APUREG_WAVESPACE, wpwa & 0xff00); 800 wp_wrapu(ess, apuch + i, APUREG_CURPTR, offset); 801 wp_wrapu(ess, apuch + i, APUREG_ENDPTR, offset + size); 802 wp_wrapu(ess, apuch + i, APUREG_LOOPLEN, size - 1); 803 wp_wrapu(ess, apuch + i, APUREG_AMPLITUDE, 0xe800); 804 wp_wrapu(ess, apuch + i, APUREG_POSITION, 0x8f00 805 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 806 | ((PAN_FRONT + pan) << APU_PAN_SHIFT)); 807 wp_wrapu(ess, apuch + i, APUREG_FREQ_LOBYTE, APU_plus6dB 808 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT)); 809 wp_wrapu(ess, apuch + i, APUREG_FREQ_HIWORD, dv >> 8); 810 811 if (ch->aputype == APUTYPE_16BITSTEREO) 812 wpwa |= APU_STEREO >> 1; 813 pan = -pan; 814 } 815 816 wc_wrchctl(ess, apuch, ch->wcreg_tpl); 817 if (nch > 1) 818 wc_wrchctl(ess, apuch + 1, ch->wcreg_tpl); 819 820 wp_wrapu(ess, apuch, APUREG_APUTYPE, 821 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 822 if (ch->wcreg_tpl & WAVCACHE_CHCTL_STEREO) 823 wp_wrapu(ess, apuch + 1, APUREG_APUTYPE, 824 (ch->aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf); 825 826 return 0; 827 } 828 829 830 int 831 esm_trigger_input(void *sc, void *start, void *end, int blksize, 832 void (*intr)(void *), void *arg, struct audio_params *param) 833 { 834 struct esm_softc *ess = sc; 835 struct esm_chinfo *ch = &ess->rch; 836 struct esm_dma *p; 837 u_int32_t chctl, choffset; 838 int i, nch = 1; 839 u_int32_t speed = ch->sample_rate, offset, wpwa, dv; 840 size_t size; 841 u_int16_t apuch = ch->num << 1; 842 u_int32_t mixoffset, mixdv; 843 size_t mixsize; 844 u_int16_t reg; 845 846 DPRINTF(ESM_DEBUG_DMA, 847 ("esm_trigger_input(%p, %p, %p, 0x%x, %p, %p, %p)\n", 848 sc, start, end, blksize, intr, arg, param)); 849 850 #ifdef DIAGNOSTIC 851 if (ess->ractive) { 852 printf("%s: esm_trigger_input: already running", 853 ess->sc_dev.dv_xname); 854 return EINVAL; 855 } 856 #endif 857 858 ess->sc_rintr = intr; 859 ess->sc_rarg = arg; 860 p = &ess->sc_dma; 861 if ((caddr_t)start != p->addr + MAESTRO_RECBUF_OFF) { 862 printf("%s: esm_trigger_input: bad addr %p\n", 863 ess->sc_dev.dv_xname, start); 864 return EINVAL; 865 } 866 867 ess->rch.buffer = (caddr_t)start; 868 ess->rch.offset = 0; 869 ess->rch.blocksize = blksize; 870 ess->rch.bufsize = ((caddr_t)end - (caddr_t)start); 871 ess->rch.apublk = blksize >> 1; 872 ess->ractive = 1; 873 874 size = (size_t)(((caddr_t)end - (caddr_t)start) >> 1); 875 choffset = MAESTRO_RECBUF_OFF; 876 switch (ch->aputype) { 877 case APUTYPE_16BITSTEREO: 878 size >>= 1; 879 choffset = MAESTRO_RECBUF_L_OFF; 880 ess->rch.apublk >>= 1; 881 nch++; 882 break; 883 case APUTYPE_16BITLINEAR: 884 break; 885 default: 886 ess->ractive = 0; 887 return EINVAL; 888 } 889 890 mixsize = (MAESTRO_MIXBUF_SZ >> 1) >> 1; 891 mixoffset = MAESTRO_MIXBUF_OFF; 892 893 ess->rch.apubase = (choffset >> 1); 894 ess->rch.apubuf = size; 895 ess->rch.nextirq = ess->rch.apublk; 896 897 set_timer(ess); 898 wp_starttimer(ess); 899 900 if (speed > 47999) speed = 47999; 901 if (speed < 4000) speed = 4000; 902 dv = (((speed % 48000) << 16) + 24000) / 48000 903 + ((speed / 48000) << 16); 904 mixdv = 65536; /* 48KHz */ 905 906 for (i = 0; i < nch; i++) { 907 908 /* Clear all rate conversion WP channel registers first. */ 909 for (reg = 0; reg < 15; reg++) 910 wp_wrapu(ess, apuch + i, reg, 0); 911 912 /* Program the WaveCache for the rate conversion WP channel. */ 913 chctl = (DMAADDR(p) + choffset - 0x10) & 914 WAVCACHE_CHCTL_ADDRTAG_MASK; 915 wc_wrchctl(ess, apuch + i, chctl); 916 917 /* Program the rate conversion WP channel. */ 918 wp_wrapu(ess, apuch + i, APUREG_FREQ_LOBYTE, APU_plus6dB 919 | ((dv & 0xff) << APU_FREQ_LOBYTE_SHIFT) | 0x08); 920 wp_wrapu(ess, apuch + i, APUREG_FREQ_HIWORD, dv >> 8); 921 offset = choffset >> 1; 922 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 923 wp_wrapu(ess, apuch + i, APUREG_WAVESPACE, wpwa); 924 wp_wrapu(ess, apuch + i, APUREG_CURPTR, offset); 925 wp_wrapu(ess, apuch + i, APUREG_ENDPTR, offset + size); 926 wp_wrapu(ess, apuch + i, APUREG_LOOPLEN, size - 1); 927 wp_wrapu(ess, apuch + i, APUREG_EFFECTS_ENV, 0x00f0); 928 wp_wrapu(ess, apuch + i, APUREG_AMPLITUDE, 0xe800); 929 wp_wrapu(ess, apuch + i, APUREG_POSITION, 0x8f00 930 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 931 | (PAN_FRONT << APU_PAN_SHIFT)); 932 wp_wrapu(ess, apuch + i, APUREG_ROUTE, apuch + 2 + i); 933 934 DPRINTF(ESM_DEBUG_DMA, 935 ("choffs=0x%x, wpwa=0x%x, offset=0x%x words, size=0x%lx words\n", 936 choffset, wpwa, offset, (unsigned long int)size)); 937 938 /* Clear all mixer WP channel registers first. */ 939 for (reg = 0; reg < 15; reg++) 940 wp_wrapu(ess, apuch + 2 + i, reg, 0); 941 942 /* Program the WaveCache for the mixer WP channel. */ 943 chctl = (ess->rch.base + mixoffset - 0x10) & 944 WAVCACHE_CHCTL_ADDRTAG_MASK; 945 wc_wrchctl(ess, apuch + 2 + i, chctl); 946 947 /* Program the mixer WP channel. */ 948 wp_wrapu(ess, apuch + 2 + i, APUREG_FREQ_LOBYTE, APU_plus6dB 949 | ((mixdv & 0xff) << APU_FREQ_LOBYTE_SHIFT) | 0x08); 950 wp_wrapu(ess, apuch + 2 + i, APUREG_FREQ_HIWORD, mixdv >> 8); 951 offset = mixoffset >> 1; 952 wpwa = APU_USE_SYSMEM | ((offset >> 8) & APU_64KPAGE_MASK); 953 wp_wrapu(ess, apuch + 2 + i, APUREG_WAVESPACE, wpwa); 954 wp_wrapu(ess, apuch + 2 + i, APUREG_CURPTR, offset); 955 wp_wrapu(ess, apuch + 2 + i, APUREG_ENDPTR, 956 offset + mixsize); 957 wp_wrapu(ess, apuch + 2 + i, APUREG_LOOPLEN, mixsize); 958 wp_wrapu(ess, apuch + 2 + i, APUREG_EFFECTS_ENV, 0x00f0); 959 wp_wrapu(ess, apuch + 2 + i, APUREG_AMPLITUDE, 0xe800); 960 wp_wrapu(ess, apuch + 2 + i, APUREG_POSITION, 0x8f00 961 | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT) 962 | (PAN_FRONT << APU_PAN_SHIFT)); 963 wp_wrapu(ess, apuch + 2 + i, APUREG_ROUTE, 964 ROUTE_PARALLEL + i); 965 966 DPRINTF(ESM_DEBUG_DMA, 967 ("mixoffs=0x%x, wpwa=0x%x, offset=0x%x words, size=0x%lx words\n", 968 mixoffset, wpwa, offset, (unsigned long int)mixsize)); 969 970 /* Assume we're going to loop to do the right channel. */ 971 choffset += MAESTRO_RECBUF_L_SZ; 972 mixoffset += MAESTRO_MIXBUF_SZ >> 1; 973 } 974 975 wp_wrapu(ess, apuch, APUREG_APUTYPE, 976 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 977 APU_DMA_ENABLED | 0xf); 978 if (nch > 1) 979 wp_wrapu(ess, apuch + 1, APUREG_APUTYPE, 980 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 981 APU_DMA_ENABLED | 0xf); 982 wp_wrapu(ess, apuch + 2, APUREG_APUTYPE, 983 (APUTYPE_INPUTMIXER << APU_APUTYPE_SHIFT) | 984 APU_DMA_ENABLED | 0xf); 985 if (nch > 1) 986 wp_wrapu(ess, apuch + 3, APUREG_APUTYPE, 987 (APUTYPE_RATECONV << APU_APUTYPE_SHIFT) | 988 APU_DMA_ENABLED | 0xf); 989 990 return 0; 991 } 992 993 994 int 995 esm_halt_output(void *sc) 996 { 997 struct esm_softc *ess = sc; 998 struct esm_chinfo *ch = &ess->pch; 999 1000 DPRINTF(ESM_DEBUG_PARAM, ("esm_halt_output(%p)\n", sc)); 1001 1002 wp_wrapu(ess, (ch->num << 1), APUREG_APUTYPE, 1003 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1004 wp_wrapu(ess, (ch->num << 1) + 1, APUREG_APUTYPE, 1005 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1006 1007 ess->pactive = 0; 1008 if (!ess->ractive) 1009 wp_stoptimer(ess); 1010 1011 return 0; 1012 } 1013 1014 1015 int 1016 esm_halt_input(void *sc) 1017 { 1018 struct esm_softc *ess = sc; 1019 struct esm_chinfo *ch = &ess->rch; 1020 1021 DPRINTF(ESM_DEBUG_PARAM, ("esm_halt_input(%p)\n", sc)); 1022 1023 wp_wrapu(ess, (ch->num << 1), APUREG_APUTYPE, 1024 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1025 wp_wrapu(ess, (ch->num << 1) + 1, APUREG_APUTYPE, 1026 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1027 wp_wrapu(ess, (ch->num << 1) + 2, APUREG_APUTYPE, 1028 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1029 wp_wrapu(ess, (ch->num << 1) + 3, APUREG_APUTYPE, 1030 APUTYPE_INACTIVE << APU_APUTYPE_SHIFT); 1031 1032 ess->ractive = 0; 1033 if (!ess->pactive) 1034 wp_stoptimer(ess); 1035 1036 return 0; 1037 } 1038 1039 1040 static inline u_int 1041 calc_timer_freq(struct esm_chinfo *ch) 1042 { 1043 u_int freq; 1044 1045 freq = (ch->sample_rate + ch->apublk - 1) / ch->apublk; 1046 1047 DPRINTF(ESM_DEBUG_TIMER, 1048 ("calc_timer_freq(%p): rate = %u, blk = 0x%x (0x%x): freq = %u\n", 1049 ch, ch->sample_rate, ch->apublk, ch->blocksize, freq)); 1050 1051 return freq; 1052 } 1053 1054 static void 1055 set_timer(struct esm_softc *ess) 1056 { 1057 unsigned freq = 0, freq2; 1058 1059 if (ess->pactive) 1060 freq = calc_timer_freq(&ess->pch); 1061 1062 if (ess->ractive) { 1063 freq2 = calc_timer_freq(&ess->rch); 1064 if (freq2 > freq) 1065 freq = freq2; 1066 } 1067 1068 KASSERT(freq != 0); 1069 1070 for (; freq < MAESTRO_MINFREQ; freq <<= 1) 1071 ; 1072 1073 if (freq > 0) 1074 wp_settimer(ess, freq); 1075 } 1076 1077 1078 static void 1079 esmch_set_format(struct esm_chinfo *ch, struct audio_params *p) 1080 { 1081 u_int16_t wcreg_tpl = (ch->base - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK; 1082 u_int16_t aputype = APUTYPE_16BITLINEAR; 1083 1084 if (p->channels == 2) { 1085 wcreg_tpl |= WAVCACHE_CHCTL_STEREO; 1086 aputype++; 1087 } 1088 if (p->precision * p->factor == 8) { 1089 aputype += 2; 1090 switch (p->encoding) { 1091 case AUDIO_ENCODING_ULINEAR: 1092 case AUDIO_ENCODING_ULINEAR_BE: 1093 case AUDIO_ENCODING_ULINEAR_LE: 1094 wcreg_tpl |= WAVCACHE_CHCTL_U8; 1095 break; 1096 } 1097 } 1098 ch->wcreg_tpl = wcreg_tpl; 1099 ch->aputype = aputype; 1100 ch->sample_rate = p->sample_rate; 1101 1102 DPRINTF(ESM_DEBUG_PARAM, ("esmch_set_format: " 1103 "numch=%d, prec=%d*%d, tpl=0x%x, aputype=%d, rate=%ld\n", 1104 p->channels, p->precision, p->factor, wcreg_tpl, aputype, 1105 p->sample_rate)); 1106 } 1107 1108 /* 1109 * Since we can't record in true stereo, this function combines 1110 * the separately recorded left and right channels into the final 1111 * buffer for the upper layer. 1112 */ 1113 static void 1114 esmch_combine_input(struct esm_softc *ess, struct esm_chinfo *ch) 1115 { 1116 u_int32_t *dst32s; 1117 size_t offset, resid, count; 1118 const u_int32_t *left32s, *right32s; 1119 u_int32_t left32, right32; 1120 1121 /* The current offset into the upper layer buffer. */ 1122 offset = ch->offset; 1123 1124 /* The number of bytes left to combine. */ 1125 resid = ch->blocksize; 1126 1127 while (resid > 0) { 1128 1129 /* The 32-bit words for the left channel. */ 1130 left32s = (const u_int32_t *)(ess->sc_dma.addr + 1131 MAESTRO_RECBUF_L_OFF + offset / 2); 1132 1133 /* The 32-bit words for the right channel. */ 1134 right32s = (const u_int32_t *)(ess->sc_dma.addr + 1135 MAESTRO_RECBUF_R_OFF + offset / 2); 1136 1137 /* The pointer to the 32-bit words we will write. */ 1138 dst32s = (u_int32_t *)(ch->buffer + offset); 1139 1140 /* Get the number of bytes we will combine now. */ 1141 count = ch->bufsize - offset; 1142 if (count > resid) 1143 count = resid; 1144 resid -= count; 1145 offset += count; 1146 if (offset == ch->bufsize) 1147 offset = 0; 1148 1149 /* Combine, writing two 32-bit words at a time. */ 1150 KASSERT((count & (sizeof(uint32_t) * 2 - 1)) == 0); 1151 count /= (sizeof(u_int32_t) * 2); 1152 while (count > 0) { 1153 left32 = *(left32s++); 1154 right32 = *(right32s++); 1155 /* XXX this endian handling is half-baked at best */ 1156 #if BYTE_ORDER == LITTLE_ENDIAN 1157 *(dst32s++) = (left32 & 0xFFFF) | (right32 << 16); 1158 *(dst32s++) = (left32 >> 16) | (right32 & 0xFFFF0000); 1159 #else /* BYTE_ORDER == BIG_ENDIAN */ 1160 *(dst32s++) = (left32 & 0xFFFF0000) | (right32 >> 16); 1161 *(dst32s++) = (left32 << 16) | (right32 & 0xFFFF); 1162 #endif /* BYTE_ORDER == BIG_ENDIAN */ 1163 count--; 1164 } 1165 } 1166 1167 /* Update the offset. */ 1168 ch->offset = offset; 1169 } 1170 1171 /* 1172 * Audio interface glue functions 1173 */ 1174 1175 int 1176 esm_open(void *sc, int flags) 1177 { 1178 DPRINTF(ESM_DEBUG_PARAM, ("esm_open(%p, 0x%x)\n", sc, flags)); 1179 1180 return 0; 1181 } 1182 1183 1184 void 1185 esm_close(void *sc) 1186 { 1187 DPRINTF(ESM_DEBUG_PARAM, ("esm_close(%p)\n", sc)); 1188 } 1189 1190 1191 int 1192 esm_getdev (void *sc, struct audio_device *adp) 1193 { 1194 *adp = esm_device; 1195 return 0; 1196 } 1197 1198 1199 int 1200 esm_round_blocksize (void *sc, int blk) 1201 { 1202 DPRINTF(ESM_DEBUG_PARAM, 1203 ("esm_round_blocksize(%p, 0x%x)", sc, blk)); 1204 1205 blk &= ~0x3f; /* keep good alignment */ 1206 1207 DPRINTF(ESM_DEBUG_PARAM, (" = 0x%x\n", blk)); 1208 1209 return blk; 1210 } 1211 1212 1213 int 1214 esm_query_encoding(void *sc, struct audio_encoding *fp) 1215 { 1216 DPRINTF(ESM_DEBUG_PARAM, 1217 ("esm_query_encoding(%p, %d)\n", sc, fp->index)); 1218 1219 if (fp->index < 0 || fp->index >= MAESTRO_NENCODINGS) 1220 return EINVAL; 1221 1222 *fp = esm_encoding[fp->index]; 1223 return 0; 1224 } 1225 1226 1227 int 1228 esm_set_params(void *sc, int setmode, int usemode, 1229 struct audio_params *play, struct audio_params *rec) 1230 { 1231 struct esm_softc *ess = sc; 1232 struct audio_params *p; 1233 int mode; 1234 1235 DPRINTF(ESM_DEBUG_PARAM, 1236 ("esm_set_params(%p, 0x%x, 0x%x, %p, %p)\n", 1237 sc, setmode, usemode, play, rec)); 1238 1239 for (mode = AUMODE_RECORD; mode != -1; 1240 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 1241 if ((setmode & mode) == 0) 1242 continue; 1243 1244 p = mode == AUMODE_PLAY ? play : rec; 1245 1246 if (p->sample_rate < 4000 || p->sample_rate > 48000 || 1247 (p->precision != 8 && p->precision != 16) || 1248 (p->channels != 1 && p->channels != 2)) 1249 return EINVAL; 1250 1251 p->factor = 1; 1252 p->sw_code = 0; 1253 switch (p->encoding) { 1254 case AUDIO_ENCODING_SLINEAR_BE: 1255 if (p->precision == 16) 1256 p->sw_code = swap_bytes; 1257 else 1258 p->sw_code = change_sign8; 1259 break; 1260 case AUDIO_ENCODING_SLINEAR_LE: 1261 if (p->precision != 16) 1262 p->sw_code = change_sign8; 1263 break; 1264 case AUDIO_ENCODING_ULINEAR_BE: 1265 if (p->precision == 16) { 1266 if (mode == AUMODE_PLAY) 1267 p->sw_code = swap_bytes_change_sign16_le; 1268 else 1269 p->sw_code = change_sign16_swap_bytes_le; 1270 } 1271 break; 1272 case AUDIO_ENCODING_ULINEAR_LE: 1273 if (p->precision == 16) 1274 p->sw_code = change_sign16_le; 1275 break; 1276 case AUDIO_ENCODING_ULAW: 1277 if (mode == AUMODE_PLAY) { 1278 p->factor = 2; 1279 p->sw_code = mulaw_to_slinear16_le; 1280 } else 1281 p->sw_code = ulinear8_to_mulaw; 1282 break; 1283 case AUDIO_ENCODING_ALAW: 1284 if (mode == AUMODE_PLAY) { 1285 p->factor = 2; 1286 p->sw_code = alaw_to_slinear16_le; 1287 } else 1288 p->sw_code = ulinear8_to_alaw; 1289 break; 1290 default: 1291 return EINVAL; 1292 } 1293 } 1294 1295 if (setmode & AUMODE_PLAY) 1296 esmch_set_format(&ess->pch, play); 1297 1298 if (setmode & AUMODE_RECORD) 1299 esmch_set_format(&ess->rch, rec); 1300 1301 return 0; 1302 } 1303 1304 1305 int 1306 esm_set_port(void *sc, mixer_ctrl_t *cp) 1307 { 1308 struct esm_softc *ess = sc; 1309 1310 return (ess->codec_if->vtbl->mixer_set_port(ess->codec_if, cp)); 1311 } 1312 1313 1314 int 1315 esm_get_port(void *sc, mixer_ctrl_t *cp) 1316 { 1317 struct esm_softc *ess = sc; 1318 1319 return (ess->codec_if->vtbl->mixer_get_port(ess->codec_if, cp)); 1320 } 1321 1322 1323 int 1324 esm_query_devinfo(void *sc, mixer_devinfo_t *dip) 1325 { 1326 struct esm_softc *ess = sc; 1327 1328 return (ess->codec_if->vtbl->query_devinfo(ess->codec_if, dip)); 1329 } 1330 1331 1332 void * 1333 esm_malloc(void *sc, int direction, size_t size, struct malloc_type *pool, 1334 int flags) 1335 { 1336 struct esm_softc *ess = sc; 1337 int off; 1338 1339 DPRINTF(ESM_DEBUG_DMA, 1340 ("esm_malloc(%p, %d, 0x%lx, %p, 0x%x)", 1341 sc, direction, (unsigned long int)size, pool, flags)); 1342 1343 /* 1344 * Each buffer can only be allocated once. 1345 */ 1346 if (ess->rings_alloced & direction) { 1347 DPRINTF(ESM_DEBUG_DMA, (" = 0 (ENOMEM)\n")); 1348 return 0; 1349 } 1350 1351 /* 1352 * Mark this buffer as allocated and return its 1353 * kernel virtual address. 1354 */ 1355 ess->rings_alloced |= direction; 1356 off = (direction == AUMODE_PLAY ? 1357 MAESTRO_PLAYBUF_OFF : MAESTRO_RECBUF_OFF); 1358 DPRINTF(ESM_DEBUG_DMA, (" = %p (DMAADDR 0x%x)\n", 1359 ess->sc_dma.addr + off, 1360 (int)DMAADDR(&ess->sc_dma) + off)); 1361 return (ess->sc_dma.addr + off); 1362 } 1363 1364 1365 void 1366 esm_free(void *sc, void *ptr, struct malloc_type *pool) 1367 { 1368 struct esm_softc *ess = sc; 1369 1370 DPRINTF(ESM_DEBUG_DMA, 1371 ("esm_free(%p, %p, %p)\n", 1372 sc, ptr, pool)); 1373 1374 if ((caddr_t)ptr == ess->sc_dma.addr + MAESTRO_PLAYBUF_OFF) 1375 ess->rings_alloced &= ~AUMODE_PLAY; 1376 else if ((caddr_t)ptr == ess->sc_dma.addr + MAESTRO_RECBUF_OFF) 1377 ess->rings_alloced &= ~AUMODE_RECORD; 1378 } 1379 1380 1381 size_t 1382 esm_round_buffersize(void *sc, int direction, size_t size) 1383 { 1384 if (size > MAESTRO_PLAYBUF_SZ) 1385 size = MAESTRO_PLAYBUF_SZ; 1386 if (size > MAESTRO_RECBUF_SZ) 1387 size = MAESTRO_RECBUF_SZ; 1388 return size; 1389 } 1390 1391 1392 paddr_t 1393 esm_mappage(void *sc, void *mem, off_t off, int prot) 1394 { 1395 struct esm_softc *ess = sc; 1396 1397 DPRINTF(ESM_DEBUG_DMA, 1398 ("esm_mappage(%p, %p, 0x%lx, 0x%x)\n", 1399 sc, mem, (unsigned long)off, prot)); 1400 1401 if (off < 0) 1402 return (-1); 1403 1404 if ((caddr_t)mem == ess->sc_dma.addr + MAESTRO_PLAYBUF_OFF) 1405 off += MAESTRO_PLAYBUF_OFF; 1406 else if ((caddr_t)mem == ess->sc_dma.addr + MAESTRO_RECBUF_OFF) 1407 off += MAESTRO_RECBUF_OFF; 1408 else 1409 return -1; 1410 return bus_dmamem_mmap(ess->dmat, ess->sc_dma.segs, ess->sc_dma.nsegs, 1411 off, prot, BUS_DMA_WAITOK); 1412 } 1413 1414 1415 int 1416 esm_get_props(void *sc) 1417 { 1418 return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX; 1419 } 1420 1421 1422 /* ----------------------------- 1423 * Bus space. 1424 */ 1425 1426 int 1427 esm_intr(void *sc) 1428 { 1429 struct esm_softc *ess = sc; 1430 u_int16_t status; 1431 u_int16_t pos; 1432 int ret = 0; 1433 1434 status = bus_space_read_1(ess->st, ess->sh, PORT_HOSTINT_STAT); 1435 if (!status) 1436 return 0; 1437 1438 /* Acknowledge all. */ 1439 bus_space_write_2(ess->st, ess->sh, PORT_INT_STAT, 1); 1440 bus_space_write_1(ess->st, ess->sh, PORT_HOSTINT_STAT, 0); 1441 #if 0 /* XXX - HWVOL */ 1442 if (status & HOSTINT_STAT_HWVOL) { 1443 u_int delta; 1444 delta = bus_space_read_1(ess->st, ess->sh, PORT_HWVOL_MASTER) 1445 - 0x88; 1446 if (delta & 0x11) 1447 mixer_set(device_get_softc(ess->dev), 1448 SOUND_MIXER_VOLUME, 0); 1449 else { 1450 mixer_set(device_get_softc(ess->dev), 1451 SOUND_MIXER_VOLUME, 1452 mixer_get(device_get_softc(ess->dev), 1453 SOUND_MIXER_VOLUME) 1454 + ((delta >> 5) & 0x7) - 4 1455 + ((delta << 7) & 0x700) - 0x400); 1456 } 1457 bus_space_write_1(ess->st, ess->sh, PORT_HWVOL_MASTER, 0x88); 1458 ret++; 1459 } 1460 #endif /* XXX - HWVOL */ 1461 1462 if (ess->pactive) { 1463 pos = wp_rdapu(ess, ess->pch.num << 1, APUREG_CURPTR); 1464 1465 DPRINTF(ESM_DEBUG_IRQ, (" %4.4x/%4.4x ", pos, 1466 wp_rdapu(ess, (ess->pch.num<<1)+1, APUREG_CURPTR))); 1467 1468 pos -= ess->pch.apubase; 1469 if (pos >= ess->pch.nextirq && 1470 pos - ess->pch.nextirq < ess->pch.apubuf / 2) { 1471 ess->pch.nextirq += ess->pch.apublk; 1472 1473 if (ess->pch.nextirq >= ess->pch.apubuf) 1474 ess->pch.nextirq = 0; 1475 1476 if (ess->sc_pintr) { 1477 DPRINTF(ESM_DEBUG_IRQ, ("P\n")); 1478 ess->sc_pintr(ess->sc_parg); 1479 } 1480 1481 } 1482 ret++; 1483 } 1484 1485 if (ess->ractive) { 1486 pos = wp_rdapu(ess, ess->rch.num << 1, APUREG_CURPTR); 1487 1488 DPRINTF(ESM_DEBUG_IRQ, (" %4.4x/%4.4x ", pos, 1489 wp_rdapu(ess, (ess->rch.num<<1)+1, APUREG_CURPTR))); 1490 1491 pos -= ess->rch.apubase; 1492 if (pos >= ess->rch.nextirq && 1493 pos - ess->rch.nextirq < ess->rch.apubuf / 2) { 1494 ess->rch.nextirq += ess->rch.apublk; 1495 1496 if (ess->rch.nextirq >= ess->rch.apubuf) 1497 ess->rch.nextirq = 0; 1498 1499 if (ess->sc_rintr) { 1500 DPRINTF(ESM_DEBUG_IRQ, ("R\n")); 1501 switch(ess->rch.aputype) { 1502 case APUTYPE_16BITSTEREO: 1503 esmch_combine_input(ess, &ess->rch); 1504 break; 1505 } 1506 ess->sc_rintr(ess->sc_rarg); 1507 } 1508 1509 } 1510 ret++; 1511 } 1512 1513 return ret; 1514 } 1515 1516 1517 int 1518 esm_allocmem(struct esm_softc *sc, size_t size, size_t align, 1519 struct esm_dma *p) 1520 { 1521 int error; 1522 1523 p->size = size; 1524 error = bus_dmamem_alloc(sc->dmat, p->size, align, 0, 1525 p->segs, sizeof(p->segs)/sizeof(p->segs[0]), 1526 &p->nsegs, BUS_DMA_NOWAIT); 1527 if (error) 1528 return error; 1529 1530 error = bus_dmamem_map(sc->dmat, p->segs, p->nsegs, p->size, 1531 &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 1532 if (error) 1533 goto free; 1534 1535 error = bus_dmamap_create(sc->dmat, p->size, 1, p->size, 1536 0, BUS_DMA_NOWAIT, &p->map); 1537 if (error) 1538 goto unmap; 1539 1540 error = bus_dmamap_load(sc->dmat, p->map, p->addr, p->size, NULL, 1541 BUS_DMA_NOWAIT); 1542 if (error) 1543 goto destroy; 1544 1545 return 0; 1546 1547 destroy: 1548 bus_dmamap_destroy(sc->dmat, p->map); 1549 unmap: 1550 bus_dmamem_unmap(sc->dmat, p->addr, p->size); 1551 free: 1552 bus_dmamem_free(sc->dmat, p->segs, p->nsegs); 1553 1554 return error; 1555 } 1556 1557 1558 int 1559 esm_match(struct device *dev, struct cfdata *match, void *aux) 1560 { 1561 struct pci_attach_args *pa = (struct pci_attach_args *) aux; 1562 1563 switch (PCI_VENDOR(pa->pa_id)) { 1564 case PCI_VENDOR_ESSTECH: 1565 switch (PCI_PRODUCT(pa->pa_id)) { 1566 case PCI_PRODUCT_ESSTECH_MAESTRO1: 1567 case PCI_PRODUCT_ESSTECH_MAESTRO2: 1568 case PCI_PRODUCT_ESSTECH_MAESTRO2E: 1569 return 1; 1570 } 1571 1572 case PCI_VENDOR_ESSTECH2: 1573 switch (PCI_PRODUCT(pa->pa_id)) { 1574 case PCI_PRODUCT_ESSTECH2_MAESTRO1: 1575 return 1; 1576 } 1577 } 1578 return 0; 1579 } 1580 1581 void 1582 esm_attach(struct device *parent, struct device *self, void *aux) 1583 { 1584 struct esm_softc *ess = (struct esm_softc *)self; 1585 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 1586 pci_chipset_tag_t pc = pa->pa_pc; 1587 pcitag_t tag = pa->pa_tag; 1588 pci_intr_handle_t ih; 1589 pcireg_t csr, data; 1590 u_int16_t codec_data; 1591 u_int16_t pcmbar; 1592 const char *intrstr; 1593 int revision; 1594 char devinfo[256]; 1595 1596 aprint_naive(": Audio controller\n"); 1597 1598 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 1599 revision = PCI_REVISION(pa->pa_class); 1600 aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision); 1601 1602 /* Enable the device. */ 1603 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 1604 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, 1605 csr | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_IO_ENABLE); 1606 1607 /* Map I/O register */ 1608 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, 1609 &ess->st, &ess->sh, NULL, NULL)) { 1610 aprint_error("%s: can't map i/o space\n", ess->sc_dev.dv_xname); 1611 return; 1612 } 1613 1614 /* Initialize softc */ 1615 ess->pch.num = 0; 1616 ess->rch.num = 1; 1617 ess->dmat = pa->pa_dmat; 1618 ess->tag = tag; 1619 ess->pc = pc; 1620 ess->subid = pci_conf_read(pc, tag, PCI_SUBSYS_ID_REG); 1621 1622 DPRINTF(ESM_DEBUG_PCI, 1623 ("%s: sub-system vendor 0x%4.4x, product 0x%4.4x\n", 1624 ess->sc_dev.dv_xname, 1625 PCI_VENDOR(ess->subid), PCI_PRODUCT(ess->subid))); 1626 1627 /* Map and establish the interrupt. */ 1628 if (pci_intr_map(pa, &ih)) { 1629 aprint_error("%s: can't map interrupt\n", ess->sc_dev.dv_xname); 1630 return; 1631 } 1632 intrstr = pci_intr_string(pc, ih); 1633 ess->ih = pci_intr_establish(pc, ih, IPL_AUDIO, esm_intr, self); 1634 if (ess->ih == NULL) { 1635 aprint_error("%s: can't establish interrupt", 1636 ess->sc_dev.dv_xname); 1637 if (intrstr != NULL) 1638 aprint_normal(" at %s", intrstr); 1639 aprint_normal("\n"); 1640 return; 1641 } 1642 aprint_normal("%s: interrupting at %s\n", 1643 ess->sc_dev.dv_xname, intrstr); 1644 1645 /* 1646 * Setup PCI config registers 1647 */ 1648 1649 /* set to power state D0 */ 1650 esm_power(ess, PCI_PMCSR_STATE_D0); 1651 delay(100000); 1652 1653 /* Disable all legacy emulations. */ 1654 data = pci_conf_read(pc, tag, CONF_LEGACY); 1655 pci_conf_write(pc, tag, CONF_LEGACY, data | LEGACY_DISABLED); 1656 1657 /* Disconnect from CHI. (Makes Dell inspiron 7500 work?) 1658 * Enable posted write. 1659 * Prefer PCI timing rather than that of ISA. 1660 * Don't swap L/R. */ 1661 data = pci_conf_read(pc, tag, CONF_MAESTRO); 1662 data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING; 1663 data &= ~MAESTRO_SWAP_LR; 1664 pci_conf_write(pc, tag, CONF_MAESTRO, data); 1665 1666 /* initialize sound chip */ 1667 esm_init(ess); 1668 1669 esm_read_codec(ess, 0, &codec_data); 1670 if (codec_data == 0x80) { 1671 aprint_error("%s: PT101 codec detected!\n", 1672 ess->sc_dev.dv_xname); 1673 return; 1674 } 1675 1676 /* 1677 * Some cards and Notebooks appear to have left and right channels 1678 * reversed. Check if there is a corresponding quirk entry for 1679 * the subsystem vendor and product and if so, set the appropriate 1680 * codec flag. 1681 */ 1682 if (esm_get_quirks(ess->subid) & ESM_QUIRKF_SWAPPEDCH) { 1683 ess->codec_flags |= AC97_HOST_SWAPPED_CHANNELS; 1684 } 1685 ess->codec_flags |= AC97_HOST_DONT_READ; 1686 1687 /* initialize AC97 host interface */ 1688 ess->host_if.arg = self; 1689 ess->host_if.attach = esm_attach_codec; 1690 ess->host_if.read = esm_read_codec; 1691 ess->host_if.write = esm_write_codec; 1692 ess->host_if.reset = esm_reset_codec; 1693 ess->host_if.flags = esm_flags_codec; 1694 1695 if (ac97_attach(&ess->host_if) != 0) 1696 return; 1697 1698 /* allocate our DMA region */ 1699 if (esm_allocmem(ess, MAESTRO_DMA_SZ, MAESTRO_DMA_ALIGN, 1700 &ess->sc_dma)) { 1701 aprint_error("%s: couldn't allocate memory!\n", 1702 ess->sc_dev.dv_xname); 1703 return; 1704 } 1705 ess->rings_alloced = 0; 1706 1707 /* set DMA base address */ 1708 for (pcmbar = WAVCACHE_PCMBAR; pcmbar < WAVCACHE_PCMBAR + 4; pcmbar++) 1709 wc_wrreg(ess, pcmbar, 1710 DMAADDR(&ess->sc_dma) >> WAVCACHE_BASEADDR_SHIFT); 1711 1712 audio_attach_mi(&esm_hw_if, self, &ess->sc_dev); 1713 1714 ess->esm_suspend = PWR_RESUME; 1715 ess->esm_powerhook = powerhook_establish(esm_powerhook, ess); 1716 } 1717 1718 /* Power Hook */ 1719 void 1720 esm_powerhook(why, v) 1721 int why; 1722 void *v; 1723 { 1724 struct esm_softc *ess = (struct esm_softc *)v; 1725 1726 DPRINTF(ESM_DEBUG_PARAM, 1727 ("%s: ESS maestro 2E why=%d\n", ess->sc_dev.dv_xname, why)); 1728 switch (why) { 1729 case PWR_SUSPEND: 1730 case PWR_STANDBY: 1731 ess->esm_suspend = why; 1732 esm_suspend(ess); 1733 DPRINTF(ESM_DEBUG_RESUME, ("esm_suspend\n")); 1734 break; 1735 1736 case PWR_RESUME: 1737 ess->esm_suspend = why; 1738 esm_resume(ess); 1739 DPRINTF(ESM_DEBUG_RESUME, ("esm_resumed\n")); 1740 break; 1741 } 1742 } 1743 1744 int 1745 esm_suspend(struct esm_softc *ess) 1746 { 1747 int x; 1748 1749 x = splaudio(); 1750 wp_stoptimer(ess); 1751 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 1752 1753 esm_halt_output(ess); 1754 esm_halt_input(ess); 1755 splx(x); 1756 1757 /* Power down everything except clock. */ 1758 esm_write_codec(ess, AC97_REG_POWER, 0xdf00); 1759 delay(20); 1760 bus_space_write_4(ess->st, ess->sh, PORT_RINGBUS_CTRL, 0); 1761 delay(1); 1762 esm_power(ess, PCI_PMCSR_STATE_D3); 1763 1764 return 0; 1765 } 1766 1767 int 1768 esm_resume(struct esm_softc *ess) 1769 { 1770 int x; 1771 1772 esm_power(ess, PCI_PMCSR_STATE_D0); 1773 delay(100000); 1774 esm_init(ess); 1775 1776 (*ess->codec_if->vtbl->restore_ports)(ess->codec_if); 1777 #if 0 1778 if (mixer_reinit(dev)) { 1779 printf("%s: unable to reinitialize the mixer\n", 1780 ess->sc_dev.dv_xname); 1781 return ENXIO; 1782 } 1783 #endif 1784 1785 x = splaudio(); 1786 #if TODO 1787 if (ess->pactive) 1788 esm_start_output(ess); 1789 if (ess->ractive) 1790 esm_start_input(ess); 1791 #endif 1792 if (ess->pactive || ess->ractive) { 1793 set_timer(ess); 1794 wp_starttimer(ess); 1795 } 1796 splx(x); 1797 return 0; 1798 } 1799 1800 #if 0 1801 int 1802 esm_shutdown(struct esm_softc *ess) 1803 { 1804 int i; 1805 1806 wp_stoptimer(ess); 1807 bus_space_write_2(ess->st, ess->sh, PORT_HOSTINT_CTRL, 0); 1808 1809 esm_halt_output(ess); 1810 esm_halt_input(ess); 1811 1812 return 0; 1813 } 1814 #endif 1815