via82c686.c revision 64881
1/* 2 * Copyright (c) 2000 David Jones <dej@ox.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/sound/pci/via82c686.c 64881 2000-08-20 22:18:56Z cg $ 27 */ 28 29#include <dev/sound/pcm/sound.h> 30#include <dev/sound/pcm/ac97.h> 31 32#include <pci/pcireg.h> 33#include <pci/pcivar.h> 34#include <sys/sysctl.h> 35 36#include <dev/sound/pci/via82c686.h> 37 38#define VIA_PCI_ID 0x30581106 39#define NSEGS 16 /* Number of segments in SGD table */ 40 41#define SEGS_PER_CHAN (NSEGS/2) 42 43#undef DEB 44#define DEB(x) 45 46struct via_info; 47 48struct via_chinfo { 49 struct via_info *parent; 50 pcm_channel *channel; 51 snd_dbuf *buffer; 52 int dir; 53}; 54 55struct via_info { 56 bus_space_tag_t st; 57 bus_space_handle_t sh; 58 bus_dma_tag_t parent_dmat; 59 bus_dma_tag_t sgd_dmat; 60 61 struct via_chinfo pch, rch; 62 struct via_dma_op *sgd_table; 63 u_int16_t codec_caps; 64}; 65 66static u_int32_t via_rd(struct via_info *via, int regno, int size); 67static void via_wr(struct via_info *, int regno, u_int32_t data, int size); 68 69int via_waitready_codec(struct via_info *via); 70int via_waitvalid_codec(struct via_info *via); 71u_int32_t via_read_codec(void *addr, int reg); 72void via_write_codec(void *addr, int reg, u_int32_t val); 73 74static void via_intr(void *); 75bus_dmamap_callback_t dma_cb; 76 77 78/* channel interface */ 79static void *viachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 80static int viachan_setdir(void *data, int dir); 81static int viachan_setformat(void *data, u_int32_t format); 82static int viachan_setspeed(void *data, u_int32_t speed); 83static int viachan_setblocksize(void *data, u_int32_t blocksize); 84static int viachan_trigger(void *data, int go); 85static int viachan_getptr(void *data); 86static pcmchan_caps *viachan_getcaps(void *data); 87 88static u_int32_t via_playfmt[] = { 89 AFMT_U8, 90 AFMT_STEREO | AFMT_U8, 91 AFMT_S16_LE, 92 AFMT_STEREO | AFMT_S16_LE, 93 0 94}; 95static pcmchan_caps via_playcaps = {4000, 48000, via_playfmt, 0}; 96 97static u_int32_t via_recfmt[] = { 98 AFMT_U8, 99 AFMT_STEREO | AFMT_U8, 100 AFMT_S16_LE, 101 AFMT_STEREO | AFMT_S16_LE, 102 0 103}; 104static pcmchan_caps via_reccaps = {4000, 48000, via_recfmt, 0}; 105 106static pcm_channel via_chantemplate = { 107 viachan_init, 108 viachan_setdir, 109 viachan_setformat, 110 viachan_setspeed, 111 viachan_setblocksize, 112 viachan_trigger, 113 viachan_getptr, 114 viachan_getcaps, 115}; 116 117 118/* 119 * Probe and attach the card 120 */ 121static int 122via_probe(device_t dev) 123{ 124 if (pci_get_devid(dev) == VIA_PCI_ID) { 125 device_set_desc(dev, "VIA VT82C686A AC'97 Audio"); 126 return 0; 127 } 128 return ENXIO; 129} 130 131 132void dma_cb(void *p, bus_dma_segment_t *bds, int a, int b) 133{ 134} 135 136 137static int 138via_attach(device_t dev) 139{ 140 snddev_info *d; 141 struct via_info *via = 0; 142 struct ac97_info *codec; 143 char status[SND_STATUSLEN]; 144 145 u_int32_t data; 146 struct resource *reg = 0; 147 int regid; 148 struct resource *irq = 0; 149 void *ih = 0; 150 int irqid; 151 152 u_int16_t v; 153 bus_dmamap_t sgd_dma_map; 154 155 d = device_get_softc(dev); 156 if ((via = malloc(sizeof *via, M_DEVBUF, M_NOWAIT)) == NULL) { 157 device_printf(dev, "cannot allocate softc\n"); 158 return ENXIO; 159 } 160 bzero(via, sizeof *via); 161 162 /* Get resources */ 163 data = pci_read_config(dev, PCIR_COMMAND, 2); 164 data |= (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN); 165 pci_write_config(dev, PCIR_COMMAND, data, 2); 166 data = pci_read_config(dev, PCIR_COMMAND, 2); 167 168 pci_write_config(dev, VIA_PCICONF_MISC, 169 VIA_PCICONF_ACLINKENAB | VIA_PCICONF_ACSGD | 170 VIA_PCICONF_ACNOTRST | VIA_PCICONF_ACVSR, 1); 171 172 regid = PCIR_MAPS; 173 reg = bus_alloc_resource(dev, SYS_RES_IOPORT, ®id, 174 0, ~0, 1, RF_ACTIVE); 175 if (!reg) { 176 device_printf(dev, "via: Cannot allocate bus resource."); 177 goto bad; 178 } 179 via->st = rman_get_bustag(reg); 180 via->sh = rman_get_bushandle(reg); 181 182 irqid = 0; 183 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, 184 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 185 if (!irq 186 || bus_setup_intr(dev, irq, INTR_TYPE_TTY, via_intr, via, &ih)){ 187 device_printf(dev, "unable to map interrupt\n"); 188 goto bad; 189 } 190 191 via_wr(via, VIA_PLAY_MODE, 192 VIA_RPMODE_AUTOSTART | 193 VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); 194 via_wr(via, VIA_RECORD_MODE, 195 VIA_RPMODE_AUTOSTART | 196 VIA_RPMODE_INTR_FLAG | VIA_RPMODE_INTR_EOL, 1); 197 198 codec = ac97_create(dev, via, NULL, 199 via_read_codec, via_write_codec); 200 if (!codec) goto bad; 201 202 mixer_init(d, &ac97_mixer, codec); 203 204 /* 205 * The mixer init resets the codec. So enabling VRA must be done 206 * afterwards. 207 */ 208 v = via_read_codec(via, AC97_REG_EXT_AUDIO_ID); 209 v &= (AC97_ENAB_VRA | AC97_ENAB_MICVRA); 210 via_write_codec(via, AC97_REG_EXT_AUDIO_STAT, v); 211 via->codec_caps = v; 212 { 213 v = via_read_codec(via, AC97_REG_EXT_AUDIO_STAT); 214 DEB(printf("init: codec stat: %d\n", v)); 215 } 216 217 if (!(v & AC97_CODEC_DOES_VRA)) { 218 /* no VRA => can do only 48 kbps */ 219 via_playcaps.minspeed = 48000; 220 via_reccaps.minspeed = 48000; 221 } 222 223 /* DMA tag for buffers */ 224 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 225 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 226 /*highaddr*/BUS_SPACE_MAXADDR, 227 /*filter*/NULL, /*filterarg*/NULL, 228 /*maxsize*/VIA_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff, 229 /*flags*/0, &via->parent_dmat) != 0) { 230 device_printf(dev, "unable to create dma tag\n"); 231 goto bad; 232 } 233 234 /* 235 * DMA tag for SGD table. The 686 uses scatter/gather DMA and 236 * requires a list in memory of work to do. We need only 16 bytes 237 * for this list, and it is wasteful to allocate 16K. 238 */ 239 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, 240 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 241 /*highaddr*/BUS_SPACE_MAXADDR, 242 /*filter*/NULL, /*filterarg*/NULL, 243 /*maxsize*/NSEGS * sizeof(struct via_dma_op), 244 /*nsegments*/1, /*maxsegz*/0x3ffff, 245 /*flags*/0, &via->sgd_dmat) != 0) { 246 device_printf(dev, "unable to create dma tag\n"); 247 goto bad; 248 } 249 250 if (bus_dmamem_alloc(via->sgd_dmat, (void **)&via->sgd_table, 251 BUS_DMA_NOWAIT, &sgd_dma_map) == -1) goto bad; 252 if (bus_dmamap_load(via->sgd_dmat, sgd_dma_map, via->sgd_table, 253 NSEGS * sizeof(struct via_dma_op), dma_cb, 0, 0)) goto bad; 254 255 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", 256 rman_get_start(reg), rman_get_start(irq)); 257 258 /* Register */ 259 if (pcm_register(dev, via, 1, 1)) goto bad; 260 pcm_addchan(dev, PCMDIR_PLAY, &via_chantemplate, via); 261 pcm_addchan(dev, PCMDIR_REC, &via_chantemplate, via); 262 pcm_setstatus(dev, status); 263 return 0; 264bad: 265 if (via) free(via, M_DEVBUF); 266 bus_release_resource(dev, SYS_RES_IOPORT, regid, reg); 267 if (ih) bus_teardown_intr(dev, irq, ih); 268 if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); 269 return ENXIO; 270} 271 272 273static device_method_t via_methods[] = { 274 DEVMETHOD(device_probe, via_probe), 275 DEVMETHOD(device_attach, via_attach), 276 { 0, 0} 277}; 278 279static driver_t via_driver = { 280 "pcm", 281 via_methods, 282 sizeof(snddev_info), 283}; 284 285static devclass_t pcm_devclass; 286 287DRIVER_MODULE(via, pci, via_driver, pcm_devclass, 0, 0); 288MODULE_DEPEND(via, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER); 289MODULE_VERSION(via, 1); 290 291 292static u_int32_t 293via_rd(struct via_info *via, int regno, int size) 294{ 295 296 switch (size) { 297 case 1: 298 return bus_space_read_1(via->st, via->sh, regno); 299 case 2: 300 return bus_space_read_2(via->st, via->sh, regno); 301 case 4: 302 return bus_space_read_4(via->st, via->sh, regno); 303 default: 304 return 0xFFFFFFFF; 305 } 306} 307 308 309static void 310via_wr(struct via_info *via, int regno, u_int32_t data, int size) 311{ 312 313 switch (size) { 314 case 1: 315 bus_space_write_1(via->st, via->sh, regno, data); 316 break; 317 case 2: 318 bus_space_write_2(via->st, via->sh, regno, data); 319 break; 320 case 4: 321 bus_space_write_4(via->st, via->sh, regno, data); 322 break; 323 } 324} 325 326 327/* Codec interface */ 328int 329via_waitready_codec(struct via_info *via) 330{ 331 int i; 332 333 /* poll until codec not busy */ 334 for (i = 0; (i < TIMEOUT) && 335 (via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_BUSY); i++) 336 DELAY(1); 337 if (i >= TIMEOUT) { 338 printf("via: codec busy\n"); 339 return 1; 340 } 341 342 return 0; 343} 344 345 346int 347via_waitvalid_codec(struct via_info *via) 348{ 349 int i; 350 351 /* poll until codec valid */ 352 for (i = 0; (i < TIMEOUT) && 353 !(via_rd(via, VIA_CODEC_CTL, 4) & VIA_CODEC_PRIVALID); i++) 354 DELAY(1); 355 if (i >= TIMEOUT) { 356 printf("via: codec invalid\n"); 357 return 1; 358 } 359 360 return 0; 361} 362 363 364void 365via_write_codec(void *addr, int reg, u_int32_t val) 366{ 367 struct via_info *via = addr; 368 369 if (via_waitready_codec(via)) return; 370 371 via_wr(via, VIA_CODEC_CTL, 372 VIA_CODEC_PRIVALID | VIA_CODEC_INDEX(reg) | val, 4); 373} 374 375 376u_int32_t 377via_read_codec(void *addr, int reg) 378{ 379 struct via_info *via = addr; 380 381 if (via_waitready_codec(via)) 382 return 1; 383 384 via_wr(via, VIA_CODEC_CTL, 385 VIA_CODEC_PRIVALID | VIA_CODEC_READ | VIA_CODEC_INDEX(reg),4); 386 387 if (via_waitready_codec(via)) 388 return 1; 389 390 if (via_waitvalid_codec(via)) 391 return 1; 392 393 return via_rd(via, VIA_CODEC_CTL, 2); 394} 395 396 397/* channel interface */ 398static void * 399viachan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 400{ 401 struct via_info *via = devinfo; 402 struct via_chinfo *ch = (dir == PCMDIR_PLAY) ? &via->pch : &via->rch; 403 404 ch->parent = via; 405 ch->channel = c; 406 ch->buffer = b; 407 b->bufsize = VIA_BUFFSIZE; 408 409 if (chn_allocbuf(ch->buffer, via->parent_dmat) == -1) return NULL; 410 return ch; 411} 412 413static int 414viachan_setdir(void *data, int dir) 415{ 416 struct via_chinfo *ch = data; 417 struct via_info *via = ch->parent; 418 struct via_dma_op *ado; 419 int i, chunk_size; 420 int phys_addr, flag; 421 422 ch->dir = dir; 423 /* 424 * Build the scatter/gather DMA (SGD) table. 425 * There are four slots in the table: two for play, two for record. 426 * This creates two half-buffers, one of which is playing; the other 427 * is feeding. 428 */ 429 ado = via->sgd_table; 430 chunk_size = ch->buffer->bufsize / SEGS_PER_CHAN; 431 432 if (dir == PCMDIR_REC) { 433 ado += SEGS_PER_CHAN; 434 } 435 436DEB(printf("SGD table located at va %p\n", ado)); 437 phys_addr = vtophys(ch->buffer->buf); 438 for (i = 0; i < SEGS_PER_CHAN; i++) { 439 ado->ptr = phys_addr; 440 flag = (i == SEGS_PER_CHAN-1) ? 441 VIA_DMAOP_EOL : VIA_DMAOP_FLAG; 442 ado->flags = flag | chunk_size; 443DEB(printf("ado->ptr/flags = %x/%x\n", phys_addr, flag)); 444 phys_addr += chunk_size; 445 ado++; 446 } 447 return 0; 448} 449 450static int 451viachan_setformat(void *data, u_int32_t format) 452{ 453 struct via_chinfo *ch = data; 454 struct via_info *via = ch->parent; 455 int mode, mode_set; 456 457 mode_set = 0; 458 if (format & AFMT_STEREO) 459 mode_set |= VIA_RPMODE_STEREO; 460 if (format & AFMT_S16_LE) 461 mode_set |= VIA_RPMODE_16BIT; 462 463 /* Set up for output format */ 464 if (ch->dir == PCMDIR_PLAY) { 465DEB(printf("set play format: %x\n", format)); 466 mode = via_rd(via, VIA_PLAY_MODE, 1); 467 mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO); 468 mode |= mode_set; 469 via_wr(via, VIA_PLAY_MODE, mode, 1); 470 } 471 else { 472DEB(printf("set record format: %x\n", format)); 473 mode = via_rd(via, VIA_RECORD_MODE, 1); 474 mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO); 475 mode |= mode_set; 476 via_wr(via, VIA_RECORD_MODE, mode, 1); 477 } 478 479 return 0; 480} 481 482static int 483viachan_setspeed(void *data, u_int32_t speed) 484{ 485 struct via_chinfo *ch = data; 486 struct via_info *via = ch->parent; 487 488 /* 489 * Basic AC'97 defines a 48 kHz sample rate only. For other rates, 490 * upsampling is required. 491 * 492 * The VT82C686A does not perform upsampling, and neither do we. 493 * If the codec supports variable-rate audio (i.e. does the upsampling 494 * itself), then negotiate the rate with the codec. Otherwise, 495 * return 48 kHz cuz that's all you got. 496 */ 497 if (ch->dir == PCMDIR_PLAY) { 498DEB(printf("requested play speed: %d\n", speed)); 499 if (via->codec_caps & AC97_CODEC_DOES_VRA) { 500 via_write_codec(via, AC97_REG_EXT_DAC_RATE, speed); 501 speed = via_read_codec(via, AC97_REG_EXT_DAC_RATE); 502 } 503 else { 504DEB(printf("VRA not supported!\n")); 505 speed = 48000; 506 } 507DEB(printf("obtained play speed: %d\n", speed)); 508 } 509 else { 510DEB(printf("requested record speed: %d\n", speed)); 511 if (via->codec_caps & AC97_CODEC_DOES_VRA) { 512 via_write_codec(via, AC97_REG_EXT_ADC_RATE, speed); 513 speed = via_read_codec(via, AC97_REG_EXT_ADC_RATE); 514 } 515 else { 516DEB(printf("VRA not supported!\n")); 517 speed = 48000; 518 } 519DEB(printf("obtained record speed: %d\n", speed)); 520 } 521 return speed; 522} 523 524static int 525viachan_setblocksize(void *data, u_int32_t blocksize) 526{ 527 struct via_chinfo *ch = data; 528 529 return ch->buffer->bufsize / 2; 530} 531 532static int 533viachan_trigger(void *data, int go) 534{ 535 struct via_chinfo *ch = data; 536 struct via_info *via = ch->parent; 537 struct via_dma_op *ado; 538 539 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD) return 0; 540 if (ch->dir == PCMDIR_PLAY) { 541 if (go == PCMTRIG_START) { 542 ado = &via->sgd_table[0]; 543DEB(printf("ado located at va=%p pa=%x\n", ado, vtophys(ado))); 544 via_wr(via, VIA_PLAY_DMAOPS_BASE, vtophys(ado),4); 545 via_wr(via, VIA_PLAY_CONTROL, 546 VIA_RPCTRL_START, 1); 547 } 548 else { 549 /* Stop DMA */ 550 via_wr(via, VIA_PLAY_CONTROL, 551 VIA_RPCTRL_TERMINATE, 1); 552 } 553 } else { 554 if (go == PCMTRIG_START) { 555 ado = &via->sgd_table[SEGS_PER_CHAN]; 556DEB(printf("ado located at va=%p pa=%x\n", ado, vtophys(ado))); 557 via_wr(via, VIA_RECORD_DMAOPS_BASE, 558 vtophys(ado),4); 559 via_wr(via, VIA_RECORD_CONTROL, 560 VIA_RPCTRL_START, 1); 561 } 562 else { 563 /* Stop DMA */ 564 via_wr(via, VIA_RECORD_CONTROL, 565 VIA_RPCTRL_TERMINATE, 1); 566 } 567 } 568 569DEB(printf("viachan_trigger: go=%d\n", go)); 570 return 0; 571} 572 573static int 574viachan_getptr(void *data) 575{ 576 struct via_chinfo *ch = data; 577 struct via_info *via = ch->parent; 578 struct via_dma_op *ado; 579 int ptr, base, len, seg; 580 int base1; 581 582 if (ch->dir == PCMDIR_PLAY) { 583 ado = &via->sgd_table[0]; 584 base1 = via_rd(via, VIA_PLAY_DMAOPS_BASE, 4); 585 len = via_rd(via, VIA_PLAY_DMAOPS_COUNT, 4); 586 base = via_rd(via, VIA_PLAY_DMAOPS_BASE, 4); 587 if (base != base1) { /* Avoid race hazzard */ 588 len = via_rd(via, VIA_PLAY_DMAOPS_COUNT, 4); 589 } 590DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base)); 591 592 /* Base points to SGD segment to do, one past current */ 593 594 /* Determine how many segments have been done */ 595 seg = (base - vtophys(ado)) / sizeof(struct via_dma_op); 596 if (seg == 0) seg = SEGS_PER_CHAN; 597 598 /* Now work out offset: seg less count */ 599 ptr = seg * ch->buffer->bufsize / SEGS_PER_CHAN - len; 600DEB(printf("return ptr=%d\n", ptr)); 601 return ptr; 602 } 603 else { 604 base1 = via_rd(via, VIA_RECORD_DMAOPS_BASE, 4); 605 ado = &via->sgd_table[SEGS_PER_CHAN]; 606 len = via_rd(via, VIA_RECORD_DMAOPS_COUNT, 4); 607 base = via_rd(via, VIA_RECORD_DMAOPS_BASE, 4); 608 if (base != base1) { /* Avoid race hazzard */ 609 len = via_rd(via, VIA_RECORD_DMAOPS_COUNT, 4); 610 } 611DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base)); 612 613 /* Base points to next block to do, one past current */ 614 615 /* Determine how many segments have been done */ 616 seg = (base - vtophys(ado)) / sizeof(struct via_dma_op); 617 if (seg == 0) seg = SEGS_PER_CHAN; 618 619 /* Now work out offset: seg less count */ 620 ptr = seg * ch->buffer->bufsize / SEGS_PER_CHAN - len; 621 622 /* DMA appears to operate on memory 'lines' of 32 bytes */ 623 /* so don't return any part line - it isn't in RAM yet */ 624 ptr = ptr & ~0x1f; 625DEB(printf("return ptr=%d\n", ptr)); 626 return ptr; 627 } 628 return 0; 629} 630 631static pcmchan_caps * 632viachan_getcaps(void *data) 633{ 634 struct via_chinfo *ch = data; 635 return (ch->dir == PCMDIR_PLAY) ? &via_playcaps : &via_reccaps; 636} 637 638static void 639via_intr(void *p) 640{ 641 struct via_info *via = p; 642 int st; 643 644DEB(printf("viachan_intr\n")); 645 /* Read channel */ 646 st = via_rd(via, VIA_PLAY_STAT, 1); 647 if (st & VIA_RPSTAT_INTR) { 648 via_wr(via, VIA_PLAY_STAT, VIA_RPSTAT_INTR, 1); 649 chn_intr(via->pch.channel); 650 } 651 652 /* Write channel */ 653 st = via_rd(via, VIA_RECORD_STAT, 1); 654 if (st & VIA_RPSTAT_INTR) { 655 via_wr(via, VIA_RECORD_STAT, VIA_RPSTAT_INTR, 1); 656 chn_intr(via->rch.channel); 657 } 658} 659 660 661