sb.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:16k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. #define TXBUF 1400
  2. #define RXBUF 8192
  3. #define SAMPRATE 8000U
  4. #include "global.h"
  5. #include <stdio.h>
  6. #include <dos.h>
  7. #include "mbuf.h"
  8. #include "dma.h"
  9. #include "sb.h"
  10. #include "npc.h"
  11. #include "socket.h"
  12. #include "cmdparse.h"
  13. #include "netuser.h"
  14. static int sb_read_data(int base);
  15. static int sb_reset(int base);
  16. static int sb_setup(int base,int irq,int dma8,int dma16);
  17. static int sb_write_byte(int base,int data);
  18. static int sb_write_word_le(int base,int data);
  19. static int sb_write_word_be(int base,int data);
  20. static int sb_read_data(int base);
  21. static int sb_read_mix(int base,int reg);
  22. static int sb_write_mix(int base,int reg,int data);
  23. static void dumpgains(int);
  24. static void dumpgain(int,struct gain *);
  25. static int sb_adc(long,int,int);
  26. static int sb_dac(long,int,int);
  27. static int sb_idle(void);
  28. int sb_calibrate(long);
  29. static void sb_outstart(struct mbuf **bpp);
  30. int sb_send(struct mbuf *bp);
  31. unsigned short pull16le(struct mbuf **bpp);
  32. INTERRUPT sb0vec(int dev);
  33. static INTERRUPT (*Sbhandle[])() = { sb0vec };
  34. INTERRUPT (*Savevec)(void);
  35. struct sbdriver {
  36. int irq,dma8,dma16;
  37. enum { IDLE, DAC, ADC } state;
  38. struct mbuf *sndq;
  39. struct mbuf *rcvq;
  40. uint8 *dmabuf; /* Base of DMA buffer */
  41. int32 physaddr; /* Physical address of DMA buffer */
  42. int dmasize; /* Size of DMA buffer */
  43. uint8 *ioptr; /* Write pointer into DMA buffer */
  44. int bufcnt; /* Count of bytes in DMA buffer */
  45. int base; /* Base register address */
  46. int pause; /* Paused due to data underflow */
  47. long samprate;
  48. int stereo;
  49. long stuffsamples;
  50. } Sb;
  51. int S = -1;
  52. int dosbatt(),dosbdet(),dogain(),dossend(),dosamprate(),dostereo();
  53. int dosbcal(),dosbidle(),dostcplisten(),dostatus();
  54. struct gain {
  55. char *name;
  56. int regl;
  57. int regr;
  58. double scale;
  59. double offset;
  60. };
  61. struct gain Gaintab[] = {
  62. "master", SB_MV, SB_MV+1, 4, -62,
  63. "dac", SB_DAC, SB_DAC+1, 4, -62,
  64. "midi", SB_MIDI,  SB_MIDI+1, 4, -62,
  65. "cd", SB_CD, SB_CD+1, 4, -62,
  66. "line", SB_LINE, SB_LINE+1, 4, -62,
  67. "mic", SB_MIKE, SB_MIKE, 4, -62,
  68. "pcspkr", SB_PCSPKR, SB_PCSPKR, 64/6., -18,
  69. "adc", SB_ADC, SB_ADC+1, 64/6., 0,
  70. "output", SB_OUTG, SB_OUTG+1, 64/6., 0,
  71. "treble", SB_TREB, SB_TREB+1, 8, -16,
  72. "bass", SB_BASS, SB_BASS+1, 8, -16,
  73. NULL,
  74. };
  75. static struct cmds Scmds[] = {
  76. "attach", dosbatt, 0, 6,
  77. "sound attach sb16 <base_addr> <irq> <8bitdma> <16bitdma>",
  78. "calibrate", dosbcal, 0, 1,
  79. "sound calibrate <samprate>",
  80. "detach", dosbdet, 0, 1,
  81. "sound detach",
  82. "gain", dogain, 0, 1,
  83. "sound gain [<parameter> [<setting>]]",
  84. "idle", dosbidle, 0, 0,
  85. "sound idle",
  86. "listen", dostcplisten, 0, 0, NULL,
  87. "samprate", dosamprate, 0, 0, NULL,
  88. "send", dossend, 4096, 2, "sound send <host> [<port>]",
  89. "status", dostatus, 0, 0, NULL,
  90. "stereo", dostereo, 0, 0, NULL,
  91. NULL,
  92. };
  93. dosound(argc,argv,p)
  94. int argc;
  95. char *argv[];
  96. void *p;
  97. {
  98. return subcmd(Scmds,argc,argv,p);
  99. }
  100. dostatus(argc,argv,p)
  101. int argc;
  102. char *argv[];
  103. void *p;
  104. {
  105. int i;
  106. printf("Samp rate: %lu Hz",Sb.samprate);
  107. if(Sb.stereo)
  108. printf(" Stereo;");
  109. else
  110. printf(" Mono;");
  111. switch(Sb.state){
  112. case IDLE:
  113. printf(" Idlen");
  114. break;
  115. case ADC:
  116. disable();
  117. i = len_q(Sb.rcvq);
  118. enable();
  119. printf(" A/D: %u buffersn",i);
  120. break;
  121. case DAC:
  122. disable();
  123. i = len_p(Sb.sndq);
  124. enable();
  125. printf(" D/A: %u bytes; inserted bytes %lu",i+Sb.bufcnt,Sb.stuffsamples);
  126. if(Sb.pause)
  127. printf(" Paused");
  128. printf("n");
  129. break;
  130. }
  131. return 0;
  132. }
  133. dosbidle(argc,argv,p)
  134. int argc;
  135. char *argv[];
  136. void *p;
  137. {
  138. /* This will indirectly cause any transfer to stop */
  139. sb_idle();
  140. return 0;
  141. }
  142. dosbatt(argc,argv,p)
  143. int argc;
  144. char *argv[];
  145. void *p;
  146. {
  147. int major,minor;
  148. if(strcmp(argv[1],"sb16") == 0){
  149. if(Sb.base != 0){
  150. printf("Only one sound card currently supportedn");
  151. return 1;
  152. }
  153. Sb.base = htoi(argv[2]);
  154. Sb.irq = atoi(argv[3]);
  155. Sb.dma8 = atoi(argv[4]);
  156. Sb.dma16 = atoi(argv[5]);
  157. if(sb_setup(Sb.base,Sb.irq,Sb.dma8,Sb.dma16) == -1){
  158. printf("setup failedn");
  159. return 0;
  160. }
  161. sb_write_byte(Sb.base,0xe1);
  162. major = sb_read_data(Sb.base);
  163. minor = sb_read_data(Sb.base);
  164. printf("SoundBlaster DSP version %d.%dn",major,minor);
  165. Sb.state = IDLE;
  166. } else {
  167. printf("Only sb16 currently supportedn");
  168. return -1;
  169. }
  170. return 0;
  171. }
  172. dosbdet(argc,argv,p)
  173. int argc;
  174. char *argv[];
  175. void *p;
  176. {
  177. sbshut();
  178. return 0;
  179. }
  180. void
  181. sbshut()
  182. {
  183. if(Sb.base == 0)
  184. return; /* No card attached */
  185. setirq(Sb.irq,Savevec);
  186. maskoff(Sb.irq);
  187. sb_reset(Sb.base);
  188. Sb.base = 0;
  189. shutdown(S,2); /* Blow it away */
  190. S = -1;
  191. }
  192. dosamprate(argc,argv,p)
  193. int argc;
  194. char *argv[];
  195. void *p;
  196. {
  197. return setlong(&Sb.samprate,"Sample rate:",argc,argv);
  198. }
  199. dostereo(argc,argv,p)
  200. int argc;
  201. char *argv[];
  202. void *p;
  203. {
  204. return setbool(&Sb.stereo,"Stereo",argc,argv);
  205. }
  206. dogain(argc,argv,p)
  207. int argc;
  208. char *argv[];
  209. void *p;
  210. {
  211. struct gain *gp;
  212. double x;
  213. if(argc == 1){
  214. /* Dump all settings */
  215. dumpgains(Sb.base);
  216. return 0;
  217. }
  218. for(gp = Gaintab;gp->name != NULL;gp++){
  219. if(strncmp(argv[1],gp->name,strlen(argv[1])) == 0)
  220. break;
  221. }
  222. if(gp->name == NULL){
  223. printf("Valid parameters:");
  224. for(gp = Gaintab;gp->name != NULL;gp++)
  225. printf(" %s",gp->name);
  226. printf("n");
  227. return 1;
  228. }
  229. if(argc == 2){
  230. dumpgain(Sb.base,gp);
  231. return 1;
  232. }
  233. x = (atof(argv[2]) - gp->offset) * gp->scale;
  234. x = max(0,x);
  235. x = min(x,255);
  236. sb_write_mix(Sb.base,gp->regl,(int) x);
  237. if(argc > 3){
  238. x = (atof(argv[3]) - gp->offset) * gp->scale;
  239. x = max(0,x);
  240. x = min(x,255);
  241. }
  242. sb_write_mix(Sb.base,gp->regr,(int) x);
  243. return 0;
  244. }
  245. void
  246. dumpgains(base)
  247. int base;
  248. {
  249. struct gain *gp;
  250. for(gp = Gaintab;gp->name != NULL;gp++)
  251. dumpgain(base,gp);
  252. }
  253. void
  254. dumpgain(base,gp)
  255. int base;
  256. struct gain *gp;
  257. {
  258. double l,r;
  259. l = sb_read_mix(base,gp->regl);
  260. r = sb_read_mix(base,gp->regr);
  261. printf("%s ",gp->name);
  262. if(l != r){
  263. printf("left %.0f right %.0f dBn",
  264.  l / gp->scale + gp->offset,
  265.  r / gp->scale + gp->offset);
  266. } else {
  267. printf("%.0f dBn",l / gp->scale + gp->offset);
  268. }
  269. }
  270. void
  271. sndrcv(s,p1,p2)
  272. int s;
  273. void *p1,*p2;
  274. {
  275. struct mbuf *bp;
  276. while(recv_mbuf(s,&bp,0,NULL,NULL) > 0)
  277. sb_send(bp);
  278. close(s);
  279. }
  280. dostcplisten(argc,argv,p)
  281. int argc;
  282. char *argv[];
  283. void *p;
  284. {
  285. if(sb_dac(Sb.samprate,Sb.stereo,RXBUF) == -1)
  286. return 1;
  287. return start_tcp(2010,"sound",sndrcv,2048);
  288. }
  289. dossend(argc,argv,p)
  290. int argc;
  291. char *argv[];
  292. void *p;
  293. {
  294. struct sockaddr_in sock;
  295. int s;
  296. int32 seq = 0;
  297. struct mbuf *bp;
  298. s = socket(AF_INET,SOCK_DGRAM,0);
  299. sock.sin_family = AF_INET;
  300. if(argc > 2)
  301. sock.sin_port = atoi(argv[2]);
  302. else
  303. sock.sin_port = 2010;
  304. sock.sin_addr.s_addr = resolve(argv[1]);
  305. if(connect(s,(struct sockaddr *)&sock,sizeof(sock)) == -1){
  306. printf("Connect failedn");
  307. close(s);
  308. return -1;
  309. }
  310. if(sb_adc(Sb.samprate,Sb.stereo,TXBUF) == -1){
  311. close(s);
  312. return 1;
  313. }
  314. for(;;){
  315. while(Sb.rcvq == NULL && Sb.state == ADC)
  316. kwait(&Sb.rcvq);
  317. if(Sb.state == IDLE)
  318. break;
  319. bp = dequeue(&Sb.rcvq);
  320. pushdown(&bp,NULL,4);
  321. put32(bp->data,seq);
  322. seq += len_p(bp) - 4;
  323. send_mbuf(s,&bp,0,NULL,NULL);
  324. }
  325. return 0;
  326. }
  327. int
  328. sb_setup(base,irq,dma8,dma16)
  329. int base;
  330. int irq;
  331. int dma8;
  332. int dma16;
  333. {
  334. int dma;
  335. if(sb_reset(base) == -1){
  336. printf("Soundblaster reset failedn");
  337. return -1;
  338. }
  339. /* Save original interrupt vector */
  340. Savevec = getirq(irq);
  341. /* Set new interrupt vector */
  342. if(setirq(irq,Sbhandle[0]) == -1){
  343. printf("IRQ %u out of rangen",irq);
  344. return -1;
  345. }
  346. switch(irq){
  347. case 2:
  348. case 9:
  349. sb_write_mix(base,0x80,1);
  350. break;
  351. case 5:
  352. sb_write_mix(base,0x80,2);
  353. break;
  354. case 7:
  355. sb_write_mix(base,0x80,4);
  356. break;
  357. case 10:
  358. sb_write_mix(base,0x80,8);
  359. break;
  360. default:
  361. printf("invalid irq %dn",irq);
  362. return -1;
  363. }
  364. maskon(irq);
  365. if(dma8 < 0 || dma8 > 3 || dma8 == 2){
  366. printf("dma8 invalidn");
  367. return -1;
  368. }
  369. if(dma16 < 5 || dma16 > 7){
  370. printf("dma16 invalidn");
  371. return -1;
  372. }
  373. dis_dmaxl(dma16);
  374. dis_dmaxl(dma8);
  375. dma = (1 << dma16) | (1<<dma8);
  376. sb_write_mix(base,0x81,dma);
  377. return 0;
  378. }
  379. /* Enter A/D mode */
  380. int
  381. sb_adc(rate,stereo,bufsiz)
  382. long rate; /* Sampling rate, Hz */
  383. int stereo; /* 1 = stereo, 0 = mono */
  384. int bufsiz; /* Size of mbufs to be generated (1/2 DMA buffer) */
  385. {
  386. if(Sb.base == 0){
  387. printf("No SB16 card attachedn");
  388. return -1;
  389. }
  390. if(Sb.state != IDLE){
  391. printf("SB16 not idlen");
  392. return -1;
  393. }
  394. /* Allocate DMA buffer */
  395. if((Sb.ioptr = Sb.dmabuf = dma_malloc(&Sb.physaddr,2*bufsiz)) == NULL){
  396. printf("Can't alloc dma buffern");
  397. return -1;
  398. }
  399. Sb.state = ADC;
  400. Sb.dmasize = 2*bufsiz;
  401. setup_dma(Sb.dma16,Sb.physaddr,Sb.dmasize,0x54);
  402. /* Set sampling rate */
  403. sb_write_byte(Sb.base,0x42);
  404. sb_write_word_be(Sb.base,rate);
  405. sb_write_byte(Sb.base,0xbe); /* 16-bit input, auto-init, fifo on */
  406. if(stereo)
  407. sb_write_byte(Sb.base,0x30); /* stereo, signed */
  408. else
  409. sb_write_byte(Sb.base,0x10); /* mono, signed */
  410. /* Write number of 16-bit words in half buffer, minus 1 */
  411. sb_write_word_le(Sb.base,Sb.dmasize/4-1);
  412. return 0;
  413. }
  414. /* Enter DAC mode */
  415. int
  416. sb_dac(rate,stereo,bufsiz)
  417. long rate; /* Sampling rate, Hz */
  418. int stereo; /* 1 = stereo, 0 = mono */
  419. int bufsiz; /* Size of buffer unit (1/2 DMA buffer) */
  420. {
  421. if(Sb.base == 0){
  422. printf("No SB16 card attachedn");
  423. return -1;
  424. }
  425. if(Sb.state != IDLE){
  426. printf("SB16 not idlen");
  427. return -1;
  428. }
  429. /* Allocate DMA buffer */
  430. if((Sb.ioptr = Sb.dmabuf = dma_malloc(&Sb.physaddr,2*bufsiz)) == NULL){
  431. printf("Can't alloc dma buffern");
  432. return -1;
  433. }
  434. Sb.state = DAC;
  435. Sb.dmasize = 2*bufsiz;
  436. Sb.stuffsamples = 0;
  437. Sb.bufcnt = 0;
  438. memset(Sb.dmabuf,0,Sb.dmasize);
  439. sb_write_byte(Sb.base,0xd1); /* spkr on */
  440. setup_dma(Sb.dma16,Sb.physaddr,Sb.dmasize,0x58);
  441. /* Set up sampling rate */
  442. sb_write_byte(Sb.base,0x41);
  443. sb_write_word_be(Sb.base,rate);
  444. sb_write_byte(Sb.base,0xb6); /* 16-bit output, auto-init, fifo on */
  445. if(stereo)
  446. sb_write_byte(Sb.base,0x30); /* stereo, signed */
  447. else
  448. sb_write_byte(Sb.base,0x10); /* mono, signed */
  449. /* Number of 16-bit words in a half-buffer, minus 1 */
  450. sb_write_word_le(Sb.base,Sb.dmasize/4-1);
  451. Sb.pause = 1;
  452. sb_write_byte(Sb.base,0xd5); /* Pause until we get data */
  453. return 0;
  454. }
  455. /* Return soundblaster to idle condition */
  456. int
  457. sb_idle()
  458. {
  459. switch(Sb.state){
  460. case IDLE:
  461. return 0; /* Already idle */
  462. case DAC: /* Wait for output queue to drain */
  463. case ADC:
  464. /* stop conversion */
  465. sb_write_byte(Sb.base,0xd9);
  466. break;
  467. }
  468. Sb.state = IDLE;
  469. kwait(NULL);
  470. /* Ought to wait for last interrupt here */
  471. free_q(&Sb.sndq);
  472. free_q(&Sb.rcvq);
  473. dma_disable(Sb.dma16);
  474. dmaunlock(Sb.physaddr,Sb.dmasize);
  475. free(Sb.dmabuf);
  476. Sb.dmabuf = NULL;
  477. Sb.physaddr = 0;
  478. return 0;
  479. }
  480. /* Reset Soundblaster card */
  481. static int
  482. sb_reset(base)
  483. int base;
  484. {
  485. unsigned int i;
  486. outportb(base+SB_RESET,1);
  487. for(i=100;i !=0;i--)
  488. ;
  489. outportb(base+SB_RESET,0);
  490. for(i=65535;i != 0;i--){
  491. if(sb_read_data(base) == 0xaa)
  492. break;
  493. }
  494. if(i == 0)
  495. return -1;
  496. return 0;
  497. }
  498. /* Wait for read data to become available, then read it. Return -1 on timeout */
  499. static int
  500. sb_read_data(base)
  501. int base;
  502. {
  503. unsigned int i;
  504. for(i=65535;i!=0;i--){
  505. if(inportb(base+SB_RB_STAT) & 0x80)
  506. break;
  507. }
  508. if(i == 0)
  509. return -1; /* Timeout */
  510. return inportb(base+SB_READ_DATA);
  511. }
  512. /* Write data byte to soundblaster when it's ready. return 0 normally, -1 on err */
  513. static int
  514. sb_write_byte(base,data)
  515. int base,data;
  516. {
  517. int i;
  518. for(i=65535;i!=0;i--){
  519. if((inportb(base+SB_WB_STAT) & 0x80) == 0)
  520. break;
  521. }
  522. if(i == 0)
  523. return -1;
  524. outportb(base+SB_WB,data);
  525. return 0;
  526. }
  527. /* Write 16-bit word in big-endian order */
  528. static int
  529. sb_write_word_be(base,data)
  530. int base;
  531. short data;
  532. {
  533. sb_write_byte(base,data >> 8);
  534. sb_write_byte(base,data);
  535. return 0;
  536. }
  537. /* Write 16-bit word in little-endian order */
  538. static int
  539. sb_write_word_le(base,data)
  540. int base;
  541. short data;
  542. {
  543. sb_write_byte(base,data);
  544. sb_write_byte(base,data >> 8);
  545. return 0;
  546. }
  547. /* Read the mixer */
  548. static int
  549. sb_read_mix(base,reg)
  550. int base,reg;
  551. {
  552. outportb(base+SB_MIX_INDEX,reg);
  553. return inportb(base+SB_MIX_DATA);
  554. }
  555. /* Write data to soundblaster when it's ready. return 0 normally, -1 on err */
  556. static int
  557. sb_write_mix(base,reg,data)
  558. int base,reg,data;
  559. {
  560. outportb(base+SB_MIX_INDEX,reg);
  561. outportb(base+SB_MIX_DATA,data);
  562. return 0;
  563. }
  564. dosbcal(argc,argv,p)
  565. int argc;
  566. char *argv[];
  567. void *p;
  568. {
  569. long rate;
  570. rate = atol(argv[1]);
  571. sb_calibrate(rate);
  572. return 0;
  573. }
  574. /* Find DC offsets of each channel */
  575. sb_calibrate(rate)
  576. long rate;
  577. {
  578. long leftavg,rightavg;
  579. uint8 omixl,omixr;
  580. long samples;
  581. /* Save previous mixer state,
  582.  * then turn everything off
  583.  */
  584. omixl = sb_read_mix(Sb.base,SB_INMIXL);
  585. omixr = sb_read_mix(Sb.base,SB_INMIXR);
  586. sb_write_mix(Sb.base,SB_INMIXL,0); /* All inputs off */
  587. sb_write_mix(Sb.base,SB_INMIXR,0);
  588. /* Collect a second of samples */
  589. sb_adc(rate,1,TXBUF);
  590. ppause(1000L);
  591. sb_idle();
  592. /* Restore previous mixer switches */
  593. sb_write_mix(Sb.base,SB_INMIXL,omixl);
  594. sb_write_mix(Sb.base,SB_INMIXR,omixr);
  595. /* Analyze the data */
  596. leftavg = rightavg = 0;
  597. samples = 0;
  598. while(Sb.rcvq != NULL){
  599. uint16 left,right;
  600. left = pull16le(&Sb.rcvq);
  601. right = pull16le(&Sb.rcvq);
  602. leftavg += left;
  603. rightavg += right;
  604. samples++;
  605. }
  606. leftavg /= samples;
  607. rightavg /= samples;
  608. printf("Left channel avg: %ld Right channel avg: %ldn",
  609.  leftavg,rightavg);
  610. return 0;
  611. }
  612. unsigned short
  613. pull16le(bpp)
  614. struct mbuf **bpp;
  615. {
  616. uint16 x;
  617. x = pull16(bpp);
  618. return (x >> 8) | (x << 8);
  619. }
  620. /* Copy as much of the buffer as will fit into the DMA buffer and start
  621.  * the DAC if it was paused
  622.  */
  623. void
  624. sb_outstart(bpp)
  625. struct mbuf **bpp;
  626. {
  627. int cnt;
  628. int istate;
  629. istate = dirps();
  630. /* Copy as much send queue data as we can into the DMA buffer */
  631. while(Sb.bufcnt < Sb.dmasize){
  632. cnt = min(Sb.dmasize-Sb.bufcnt,Sb.dmabuf+Sb.dmasize-Sb.ioptr);
  633. cnt = pullup(bpp,Sb.ioptr,cnt);
  634. if(cnt == 0)
  635. break;
  636. Sb.ioptr += cnt;
  637. if(Sb.ioptr >= Sb.dmabuf + Sb.dmasize)
  638. Sb.ioptr = Sb.dmabuf; /* Write pointer wraparound */
  639. Sb.bufcnt += cnt; /* Add to bytes in buffer */
  640. }
  641. if(!Sb.pause && Sb.bufcnt != 0 && Sb.bufcnt < Sb.dmasize/2){
  642. /* While running, pad out a partial half-buffer with silence */
  643. cnt = Sb.dmasize/2 - Sb.bufcnt;
  644. memset(Sb.ioptr,0,cnt);
  645. Sb.stuffsamples += cnt;
  646. Sb.ioptr += cnt;
  647. if(Sb.ioptr >= Sb.dmabuf + Sb.dmasize)
  648. Sb.ioptr = Sb.dmabuf; /* Write pointer wraparound */
  649. Sb.bufcnt += cnt;
  650. } else if(Sb.pause && Sb.bufcnt >= Sb.dmasize/2){
  651. /* If paused and there's now at least one full buffer, resume */
  652. Sb.pause = 0;
  653. sb_write_byte(Sb.base,0xd6); /* Resume output */
  654. }
  655. restore(istate);
  656. }
  657. /* Send a buffer to the DAC */
  658. int
  659. sb_send(bp)
  660. struct mbuf *bp;
  661. {
  662. if(Sb.state == DAC)
  663. sb_outstart(&bp);
  664. if(bp != NULL){
  665. /* Queue remainder */
  666. disable();
  667. append(&Sb.sndq,&bp);
  668. enable();
  669. }
  670. return 0;
  671. }
  672. /* Soundblaster interrupt handler */
  673. INTERRUPT (far *(sbint)(dev))()
  674. int dev;
  675. {
  676. int i;
  677. struct mbuf *bp;
  678. i = sb_read_mix(Sb.base,0x82);
  679. if(i & 1) /* 8-bit transfers not used, reset anyway */
  680. (void)inportb(Sb.base+0xe);
  681. if(i & 2){
  682. (void)inportb(Sb.base+0xf);
  683. switch(Sb.state){
  684. case IDLE:
  685. break;
  686. case DAC:
  687. Sb.bufcnt -= Sb.dmasize/2; /* Amount sent */
  688. sb_outstart(&Sb.sndq); /* Try to send more */
  689. if(Sb.bufcnt == 0){
  690. /* buffer empty, pause */
  691. Sb.pause = 1;
  692. sb_write_byte(Sb.base,0xd5);
  693. }
  694. break;
  695. case ADC:
  696. bp = alloc_mbuf(Sb.dmasize/2);
  697. memcpy(bp->data,Sb.ioptr,Sb.dmasize/2);
  698. bp->cnt = Sb.dmasize/2;
  699. Sb.ioptr += bp->cnt;
  700. if(Sb.ioptr >= Sb.dmabuf + Sb.dmasize)
  701. Sb.ioptr = Sb.dmabuf;
  702. enqueue(&Sb.rcvq,&bp);
  703. break;
  704. }
  705. ksignal(&Sb,0);
  706. }
  707. return NULL;
  708. }