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

TCP/IP协议栈

开发平台:

Visual C++

  1. /* OS- and machine-dependent stuff for the 8250 asynch chip on a IBM-PC
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * 16550A support plus some statistics added mah@hpuviea.at 15/7/89
  5.  *
  6.  * CTS hardware flow control from dkstevens@ucdavis,
  7.  * additional stats from delaroca@oac.ucla.edu added by karn 4/17/90
  8.  * Feb '91      RLSD line control reorganized by Bill_Simpson@um.cc.umich.edu
  9.  * Sep '91      All control signals reorganized by Bill Simpson
  10.  * Apr '92 Control signals redone again by Phil Karn
  11.  */
  12. #include <stdio.h>
  13. #include <dos.h>
  14. #include <errno.h>
  15. #include "global.h"
  16. #include "mbuf.h"
  17. #include "proc.h"
  18. #include "iface.h"
  19. #include "n8250.h"
  20. #include "asy.h"
  21. #include "devparam.h"
  22. #include "nospc.h"
  23. #include "dialer.h"
  24. static int asyrxint(struct asy *asyp);
  25. static void asytxint(struct asy *asyp);
  26. static void asymsint(struct asy *asyp);
  27. static void pasy(struct asy *asyp);
  28. static INTERRUPT (far *(asycom)(struct asy *))(void);
  29. struct asy Asy[ASY_MAX];
  30. struct fport Fport[FPORT_MAX];
  31. static INTERRUPT (*Fphand[FPORT_MAX])() = {
  32. fp0vec,
  33. };
  34. /* ASY interrupt handlers */
  35. static INTERRUPT (*Handle[ASY_MAX])() = {
  36. asy0vec,asy1vec,asy2vec,asy3vec,asy4vec,asy5vec
  37. };
  38. /* Initialize asynch port "dev" */
  39. int
  40. asy_init(dev,ifp,base,irq,bufsize,trigchar,speed,cts,rlsd,chain)
  41. int dev;
  42. struct iface *ifp;
  43. int base;
  44. int irq;
  45. uint16 bufsize;
  46. int trigchar;
  47. long speed;
  48. int cts; /* Use CTS flow control */
  49. int rlsd; /* Use Received Line Signal Detect (aka CD) */
  50. int chain; /* Chain interrupts */
  51. {
  52. register struct fifo *fp;
  53. register struct asy *ap;
  54. int i_state;
  55. ap = &Asy[dev];
  56. ap->iface = ifp;
  57. ap->addr = base;
  58. ap->vec = irq;
  59. ap->chain = chain;
  60. /* Set up receiver FIFO */
  61. fp = &ap->fifo;
  62. fp->buf = mallocw(bufsize);
  63. fp->bufsize = bufsize;
  64. fp->wp = fp->rp = fp->buf;
  65. fp->cnt = 0;
  66. fp->hiwat = 0;
  67. fp->overrun = 0;
  68. base = ap->addr;
  69. ap->trigchar = trigchar;
  70. /* Purge the receive data buffer */
  71. (void)inportb(base+RBR);
  72. i_state = dirps();
  73. /* Save original interrupt vector, mask state, control bits */
  74. if(ap->vec != -1){
  75. ap->save.vec = getirq(ap->vec);
  76. ap->save.mask = getmask(ap->vec);
  77. }
  78. ap->save.lcr = inportb(base+LCR);
  79. ap->save.ier = inportb(base+IER);
  80. ap->save.mcr = inportb(base+MCR);
  81. ap->msr = ap->save.msr = inportb(base+MSR);
  82. ap->save.iir = inportb(base+IIR);
  83. /* save speed bytes */
  84. setbit(base+LCR,LCR_DLAB);
  85. ap->save.divl = inportb(base+DLL);
  86. ap->save.divh = inportb(base+DLM);
  87. clrbit(base+LCR,LCR_DLAB);
  88. /* save modem control flags */
  89. ap->cts = cts;
  90. ap->rlsd = rlsd;
  91. /* Set interrupt vector to SIO handler */
  92. if(ap->vec != -1)
  93. setirq(ap->vec,Handle[dev]);
  94. /* Set line control register: 8 bits, no parity */
  95. outportb(base+LCR,LCR_8BITS);
  96. /* determine if 16550A, turn on FIFO mode and clear RX and TX FIFOs */
  97. outportb(base+FCR,FIFO_ENABLE);
  98. /* According to National ap note AN-493, the FIFO in the 16550 chip
  99.  * is broken and must not be used. To determine if this is a 16550A
  100.  * (which has a good FIFO implementation) check that both bits 7
  101.  * and 6 of the IIR are 1 after setting the fifo enable bit. If
  102.  * not, don't try to use the FIFO.
  103.  */
  104. if ((inportb(base+IIR) & IIR_FIFO_ENABLED) == IIR_FIFO_ENABLED) {
  105. ap->is_16550a = TRUE;
  106. outportb(base+FCR,FIFO_SETUP);
  107. } else {
  108. /* Chip is not a 16550A. In case it's a 16550 (which has a
  109.  * broken FIFO), turn off the FIFO bit.
  110.  */
  111. outportb(base+FCR,0);
  112. ap->is_16550a = FALSE;
  113. }
  114. /* Turn on receive interrupts and optionally modem interrupts;
  115.  * leave transmit interrupts off until we actually send data.
  116.  */
  117. if(ap->rlsd || ap->cts)
  118. outportb(base+IER,IER_MS|IER_DAV);
  119. else
  120. outportb(base+IER,IER_DAV);
  121. /* Turn on 8250 master interrupt enable (connected to OUT2) */
  122. setbit(base+MCR,MCR_OUT2);
  123. /* Enable interrupt */
  124. if(ap->vec != -1)
  125. maskon(ap->vec);
  126. restore(i_state);
  127. asy_speed(dev,speed);
  128. return 0;
  129. }
  130. int
  131. asy_stop(ifp)
  132. struct iface *ifp;
  133. {
  134. register unsigned base;
  135. register struct asy *ap;
  136. struct asydialer *dialer;
  137. int i_state;
  138. ap = &Asy[ifp->dev];
  139. if(ap->iface == NULL)
  140. return -1; /* Not allocated */
  141. ap->iface = NULL;
  142. base = ap->addr;
  143. if(ifp->dstate != NULL){
  144. dialer = (struct asydialer *)ifp->dstate;
  145. stop_timer(&dialer->idle); /* Stop the idle timer, if running */
  146. free(dialer);
  147. ifp->dstate = NULL;
  148. }
  149. (void)inportb(base+RBR); /* Purge the receive data buffer */
  150. if(ap->is_16550a){
  151. /* Purge hardware FIFOs and disable if we weren't already
  152.  * in FIFO mode when we entered. Apparently some
  153.  * other comm programs can't handle 16550s in
  154.  * FIFO mode; they expect 16450 compatibility mode.
  155.  */
  156. outportb(base+FCR,FIFO_SETUP);
  157. if((ap->save.iir & IIR_FIFO_ENABLED) != IIR_FIFO_ENABLED)
  158. outportb(base+FCR,0);
  159. }
  160. /* Restore original interrupt vector and 8259 mask state */
  161. i_state = dirps();
  162. if(ap->vec != -1){
  163. setirq(ap->vec,ap->save.vec);
  164. if(ap->save.mask)
  165. maskon(ap->vec);
  166. else
  167. maskoff(ap->vec);
  168. }
  169. /* Restore speed regs */
  170. setbit(base+LCR,LCR_DLAB);
  171. outportb(base+DLL,ap->save.divl); /* Low byte */
  172. outportb(base+DLM,ap->save.divh); /* Hi byte */
  173. clrbit(base+LCR,LCR_DLAB);
  174. /* Restore control regs */
  175. outportb(base+LCR,ap->save.lcr);
  176. outportb(base+IER,ap->save.ier);
  177. outportb(base+MCR,ap->save.mcr);
  178. restore(i_state);
  179. free(ap->fifo.buf);
  180. return 0;
  181. }
  182. /* Set asynch line speed */
  183. int
  184. asy_speed(dev,bps)
  185. int dev;
  186. long bps;
  187. {
  188. register unsigned base;
  189. register long divisor;
  190. struct asy *asyp;
  191. int i_state;
  192. if(bps <= 0 || dev >= ASY_MAX)
  193. return -1;
  194. asyp = &Asy[dev];
  195. if(asyp->iface == NULL)
  196. return -1;
  197. if(bps == 0)
  198. return -1;
  199. asyp->speed = bps;
  200. base = asyp->addr;
  201. divisor = BAUDCLK / bps;
  202. i_state = dirps();
  203. /* Purge the receive data buffer */
  204. (void)inportb(base+RBR);
  205. if (asyp->is_16550a) /* clear tx+rx fifos */
  206. outportb(base+FCR,FIFO_SETUP);
  207. /* Turn on divisor latch access bit */
  208. setbit(base+LCR,LCR_DLAB);
  209. /* Load the two bytes of the register */
  210. outportb(base+DLL,divisor); /* Low byte */
  211. outportb(base+DLM,divisor >> 8); /* Hi byte */
  212. /* Turn off divisor latch access bit */
  213. clrbit(base+LCR,LCR_DLAB);
  214. restore(i_state);
  215. return 0;
  216. }
  217. /* Asynchronous line I/O control */
  218. int32
  219. asy_ioctl(ifp,cmd,set,val)
  220. struct iface *ifp;
  221. int cmd;
  222. int set;
  223. int32 val;
  224. {
  225. struct asy *ap = &Asy[ifp->dev];
  226. uint16 base = ap->addr;
  227. switch(cmd){
  228. case PARAM_SPEED:
  229. if(set)
  230. asy_speed(ifp->dev,val);
  231. return ap->speed;
  232. case PARAM_DTR:
  233. if(set) {
  234. writebit(base+MCR,MCR_DTR,(int)val);
  235. }
  236. return (inportb(base+MCR) & MCR_DTR) ? TRUE : FALSE;
  237. case PARAM_RTS:
  238. if(set) {
  239. writebit(base+MCR,MCR_RTS,(int)val);
  240. }
  241. return (inportb(base+MCR) & MCR_RTS) ? TRUE : FALSE;
  242. case PARAM_DOWN:
  243. clrbit(base+MCR,MCR_RTS);
  244. clrbit(base+MCR,MCR_DTR);
  245. return FALSE;
  246. case PARAM_UP:
  247. setbit(base+MCR,MCR_RTS);
  248. setbit(base+MCR,MCR_DTR);
  249. return TRUE;
  250. }
  251. return -1;
  252. }
  253. /* Open an asynch port for direct I/O, temporarily suspending any
  254.  * packet-mode operations. Returns device number for asy_write and get_asy
  255.  */
  256. int
  257. asy_open(name)
  258. char *name;
  259. {
  260. struct iface *ifp;
  261. int dev;
  262. if((ifp = if_lookup(name)) == NULL){
  263. errno = ENODEV;
  264. return -1;
  265. }
  266. if((dev = ifp->dev) >= ASY_MAX || Asy[dev].iface != ifp){
  267. errno = EINVAL;
  268. return -1;
  269. }
  270. /* Suspend the packet drivers */
  271. suspend(ifp->rxproc);
  272. suspend(ifp->txproc);
  273. /* bring the line up (just in case) */
  274. if(ifp->ioctl != NULL)
  275. (*ifp->ioctl)(ifp,PARAM_UP,TRUE,0L);
  276. return dev;
  277. }
  278. int
  279. asy_close(dev)
  280. int dev;
  281. {
  282. struct iface *ifp;
  283. if(dev < 0 || dev >= ASY_MAX){
  284. errno = EINVAL;
  285. return -1;
  286. }
  287. /* Resume the packet drivers */
  288. if((ifp = Asy[dev].iface) == NULL){
  289. errno = EINVAL;
  290. return -1;
  291. }
  292. resume(ifp->rxproc);
  293. resume(ifp->txproc);
  294. return 0;
  295. }
  296. /* Send a buffer on the serial transmitter and wait for completion */
  297. int
  298. asy_write(dev,buf,cnt)
  299. int dev;
  300. void *buf;
  301. unsigned short cnt;
  302. {
  303. register struct dma *dp;
  304. unsigned base;
  305. struct asy *asyp;
  306. int tmp;
  307. int i_state;
  308. struct iface *ifp;
  309. if(dev < 0 || dev >= ASY_MAX)
  310. return -1;
  311. asyp = &Asy[dev];
  312. if((ifp = asyp->iface) == NULL)
  313. return -1;
  314. base = asyp->addr;
  315. dp = &asyp->dma;
  316. if(dp->busy)
  317. return -1; /* Already busy */
  318. dp->data = buf;
  319. dp->cnt = cnt;
  320. dp->busy = 1;
  321. /* If CTS flow control is disabled or CTS is true,
  322.  * enable transmit interrupts here so we'll take an immediate
  323.  * interrupt to get things going. Otherwise let the
  324.  * modem control interrupt enable transmit interrupts
  325.  * when CTS comes up. If we do turn on TxE,
  326.  * "kick start" the transmitter interrupt routine, in case just
  327.  * setting the interrupt enable bit doesn't cause an interrupt
  328.  */
  329. if(!asyp->cts || (asyp->msr & MSR_CTS)){
  330. setbit(base+IER,IER_TxE);
  331. asytxint(asyp);
  332. }
  333. /* Wait for completion */
  334. for(;;){
  335. i_state = dirps();
  336. tmp = dp->busy;
  337. restore(i_state);
  338. if(tmp == 0)
  339. break;
  340. kwait(&asyp->dma);
  341. }
  342. ifp->lastsent = secclock();
  343. return cnt;
  344. }
  345. /* Read data from asynch line
  346.  * Blocks until at least 1 byte of data is available.
  347.  * returns number of bytes read, up to 'cnt' max
  348.  */
  349. int
  350. asy_read(dev,buf,cnt)
  351. int dev;
  352. void *buf;
  353. unsigned short cnt;
  354. {
  355. struct fifo *fp;
  356. int i_state,tmp;
  357. uint8 c,*obp;
  358. if(cnt == 0)
  359. return 0;
  360. if(dev < 0 || dev >= ASY_MAX){
  361. errno = EINVAL;
  362. return -1;
  363. }
  364. fp = &Asy[dev].fifo;
  365. obp = (uint8 *)buf;
  366. for(;;){
  367. /* Atomic read of and subtract from fp->cnt */
  368. i_state = dirps();
  369. tmp = fp->cnt;
  370. if(tmp != 0){
  371. if(cnt > tmp)
  372. cnt = tmp; /* Limit to data on hand */
  373. fp->cnt -= cnt;
  374. restore(i_state);
  375. break;
  376. }
  377. restore(i_state);
  378. if((errno = kwait(fp)) != 0)
  379. return -1;
  380. }
  381. tmp = cnt;
  382. while(tmp-- != 0){
  383. /* This can be optimized later if necessary */
  384. c = *fp->rp++;
  385. if(fp->rp >= &fp->buf[fp->bufsize])
  386. fp->rp = fp->buf;
  387. *obp++ = c;
  388. }
  389. return cnt;
  390. }
  391. /* Blocking read from asynch line
  392.  * Returns character or -1 if aborting
  393.  */
  394. int
  395. get_asy(dev)
  396. int dev;
  397. {
  398. uint8 c;
  399. int tmp;
  400. if((tmp = asy_read(dev,&c,1)) == 1)
  401. return c;
  402. else
  403. return tmp;
  404. }
  405. /* Interrupt handler for 8250 asynch chip (called from asyvec.asm) */
  406. INTERRUPT (far *(asyint)(dev))()
  407. int dev;
  408. {
  409. return asycom(&Asy[dev]);
  410. }
  411. /* Interrupt handler for AST 4-port board (called from fourport.asm) */
  412. INTERRUPT (far *(fpint)(dev))()
  413. int dev;
  414. {
  415. int iv;
  416. struct fport *fport;
  417. int i;
  418. fport = &Fport[dev];
  419. /* Read special interrupt demux register to see which port is active */
  420. while(((iv = inportb(fport->iv)) & 0xf) != 0xf){
  421. for(i=0;i<4;i++){
  422. if((iv & (1 << i)) == 0 && fport->asy[i] != NULL)
  423. asycom(fport->asy[i]);
  424. }
  425. }
  426. return NULL;
  427. }
  428. /* Common interrupt handler code for 8250/16550 port */
  429. static INTERRUPT (far *(asycom)(asyp))(void)
  430. struct asy *asyp;
  431. {
  432. unsigned base;
  433. char iir;
  434. base = asyp->addr;
  435. while(((iir = inportb(base+IIR)) & IIR_IP) == 0){
  436. switch(iir & IIR_ID_MASK){
  437. case IIR_RDA: /* Receiver interrupt */
  438. asyrxint(asyp);
  439. break;
  440. case IIR_THRE: /* Transmit interrupt */
  441. asytxint(asyp);
  442. break;
  443. case IIR_MSTAT: /* Modem status change */
  444. asymsint(asyp);
  445. asyp->msint_count++;
  446. break;
  447. }
  448. /* should happen at end of a single packet */
  449. if(iir & IIR_FIFO_TIMEOUT)
  450. asyp->fifotimeouts++;
  451. }
  452. return asyp->chain ? asyp->save.vec : NULL;
  453. }
  454. /* Process 8250 receiver interrupts */
  455. static int
  456. asyrxint(asyp)
  457. struct asy *asyp;
  458. {
  459. register struct fifo *fp;
  460. unsigned base;
  461. uint8 c,lsr;
  462. int cnt = 0;
  463. int trigseen = FALSE;
  464. asyp->rxints++;
  465. base = asyp->addr;
  466. fp = &asyp->fifo;
  467. for(;;){
  468. lsr = inportb(base+LSR);
  469. if(lsr & LSR_OE)
  470. asyp->overrun++;
  471. if(lsr & LSR_DR){
  472. asyp->rxchar++;
  473. c = inportb(base+RBR);
  474. if(asyp->trigchar == -1 || asyp->trigchar == c)
  475. trigseen = TRUE;
  476. /* If buffer is full, we have no choice but
  477.  * to drop the character
  478.  */
  479. if(fp->cnt != fp->bufsize){
  480. *fp->wp++ = c;
  481. if(fp->wp >= &fp->buf[fp->bufsize])
  482. /* Wrap around */
  483. fp->wp = fp->buf;
  484. fp->cnt++;
  485. if(fp->cnt > fp->hiwat)
  486. fp->hiwat = fp->cnt;
  487. cnt++;
  488. } else
  489. fp->overrun++;
  490. } else
  491. break;
  492. }
  493. if(cnt > asyp->rxhiwat)
  494. asyp->rxhiwat = cnt;
  495. if(trigseen)
  496. ksignal(fp,1);
  497. return cnt;
  498. }
  499. /* Handle 8250 transmitter interrupts */
  500. static void
  501. asytxint(asyp)
  502. struct asy *asyp;
  503. {
  504. register struct dma *dp;
  505. register unsigned base;
  506. register int count;
  507. base = asyp->addr;
  508. dp = &asyp->dma;
  509. asyp->txints++;
  510. if(!dp->busy || (asyp->cts && !(asyp->msr & MSR_CTS))){
  511. /* These events "shouldn't happen". Either the
  512.  * transmitter is idle, in which case the transmit
  513.  * interrupts should have been disabled, or flow control
  514.  * is enabled but CTS is low, and interrupts should also
  515.  * have been disabled.
  516.  */
  517. clrbit(base+IER,IER_TxE);
  518. return; /* Nothing to send */
  519. }
  520. if(!(inportb(base+LSR) & LSR_THRE))
  521. return; /* Not really ready */
  522. /* If it's a 16550A, load up to 16 chars into the tx hw fifo
  523.  * at once. With an 8250, it can be one char at most.
  524.  */
  525. if(asyp->is_16550a){
  526. count = min(dp->cnt,OUTPUT_FIFO_SIZE);
  527. /* 16550A: LSR_THRE will drop after the first char loaded
  528.  * so we can't look at this bit to determine if the hw fifo is
  529.  * full. There seems to be no way to determine if the tx fifo
  530.  * is full (any clues?). So we should never get here while the
  531.  * fifo isn't empty yet.
  532.  */
  533. asyp->txchar += count;
  534. dp->cnt -= count;
  535. #ifdef notdef /* This is apparently too fast for some chips */
  536. dp->data = outbuf(base+THR,dp->data,count);
  537. #else
  538. while(count-- != 0)
  539. outportb(base+THR,*dp->data++);
  540. #endif
  541. } else { /* 8250 */
  542. do {
  543. asyp->txchar++;
  544. outportb(base+THR,*dp->data++);
  545. } while(--dp->cnt != 0 && (inportb(base+LSR) & LSR_THRE));
  546. }
  547. if(dp->cnt == 0){
  548. dp->busy = 0;
  549. /* Disable further transmit interrupts */
  550. clrbit(base+IER,IER_TxE);
  551. ksignal(&asyp->dma,1);
  552. }
  553. }
  554. /* Handle 8250 modem status change interrupt */
  555. static void
  556. asymsint(asyp)
  557. struct asy *asyp;
  558. {
  559. unsigned base = asyp->addr;
  560. asyp->msr = inportb(base+MSR);
  561. if(asyp->cts && (asyp->msr & MSR_DCTS)){
  562. /* CTS has changed and we care */
  563. if(asyp->msr & MSR_CTS){
  564. /* CTS went up */
  565. if(asyp->dma.busy){
  566. /* enable transmit interrupts and kick */
  567. setbit(base+IER,IER_TxE);
  568. asytxint(asyp);
  569. }
  570. } else {
  571. /* CTS now dropped, disable Transmit interrupts */
  572. clrbit(base+IER,IER_TxE);
  573. }
  574. }
  575. if(asyp->rlsd && (asyp->msr & MSR_DRLSD)){
  576. /* RLSD just changed and we care, signal it */
  577. ksignal( &(asyp->rlsd), 1 );
  578. /* Keep count */
  579. asyp->cdchanges++;
  580. }
  581. ksignal(&asyp->msr,0);
  582. }
  583. /* Wait for a signal that the RLSD modem status has changed */
  584. int
  585. get_rlsd_asy(dev, new_rlsd)
  586. int dev;
  587. int new_rlsd;
  588. {
  589. struct asy *ap = &Asy[dev];
  590. if(ap->rlsd == 0)
  591. return -1;
  592. for(;;){
  593. if(new_rlsd && (ap->msr & MSR_RLSD))
  594. return 1;
  595. if(!new_rlsd && !(ap->msr & MSR_RLSD))
  596. return 0;
  597. /* Wait for state change to requested value */
  598. ppause(2L);
  599. kwait( &(ap->rlsd) );
  600. }
  601. }
  602. /* Poll the asynch input queues; called on every clock tick.
  603.  * This helps limit the interrupt ring buffer occupancy when long
  604.  * packets are being received.
  605.  */
  606. void
  607. asytimer()
  608. {
  609. register struct asy *asyp;
  610. register struct fifo *fp;
  611. register int i;
  612. int i_state;
  613. for(i=0;i<ASY_MAX;i++){
  614. asyp = &Asy[i];
  615. fp = &asyp->fifo;
  616. if(fp->cnt != 0)
  617. ksignal(fp,1);
  618. if(asyp->dma.busy
  619.  && (inportb(asyp->addr+LSR) & LSR_THRE)
  620.  && (!asyp->cts || (asyp->msr & MSR_CTS))){
  621. asyp->txto++;
  622. i_state = dirps();
  623. asytxint(asyp);
  624. restore(i_state);
  625. }
  626. }
  627. }
  628. int
  629. doasystat(argc,argv,p)
  630. int argc;
  631. char *argv[];
  632. void *p;
  633. {
  634. register struct asy *asyp;
  635. struct iface *ifp;
  636. int i;
  637. if(argc < 2){
  638. for(asyp = Asy;asyp < &Asy[ASY_MAX];asyp++){
  639. if(asyp->iface != NULL)
  640. pasy(asyp);
  641. }
  642. return 0;
  643. }
  644. for(i=1;i<argc;i++){
  645. if((ifp = if_lookup(argv[i])) == NULL){
  646. printf("Interface %s unknownn",argv[i]);
  647. continue;
  648. }
  649. for(asyp = Asy;asyp < &Asy[ASY_MAX];asyp++){
  650. if(asyp->iface == ifp){
  651. pasy(asyp);
  652. break;
  653. }
  654. }
  655. if(asyp == &Asy[ASY_MAX])
  656. printf("Interface %s not asyn",argv[i]);
  657. }
  658. return 0;
  659. }
  660. static void
  661. pasy(asyp)
  662. struct asy *asyp;
  663. {
  664. int mcr;
  665. printf("%s:",asyp->iface->name);
  666. if(asyp->is_16550a)
  667. printf(" [NS16550A]");
  668. if(asyp->trigchar != -1)
  669. printf(" [trigger 0x%02x]",asyp->trigchar);
  670. if(asyp->cts)
  671. printf(" [cts flow control]");
  672. if(asyp->rlsd)
  673. printf(" [rlsd line control]");
  674. printf(" %lu bpsn",asyp->speed);
  675. mcr = inportb(asyp->addr+MCR);
  676. printf(" MC: int %lu DTR %s  RTS %s  CTS %s  DSR %s  RI %s  CD %sn",
  677.  asyp->msint_count,
  678.  (mcr & MCR_DTR) ? "On" : "Off",
  679.  (mcr & MCR_RTS) ? "On" : "Off",
  680.  (asyp->msr & MSR_CTS) ? "On" : "Off",
  681.  (asyp->msr & MSR_DSR) ? "On" : "Off",
  682.  (asyp->msr & MSR_RI) ? "On" : "Off",
  683.  (asyp->msr & MSR_RLSD) ? "On" : "Off");
  684. printf(" RX: int %lu chars %lu hw over %lu hw hi %lu",
  685.  asyp->rxints,asyp->rxchar,asyp->overrun,asyp->rxhiwat);
  686. asyp->rxhiwat = 0;
  687. if(asyp->is_16550a)
  688. printf(" fifo TO %lu",asyp->fifotimeouts);
  689. printf(" sw over %lu sw hi %un",
  690.  asyp->fifo.overrun,asyp->fifo.hiwat);
  691. asyp->fifo.hiwat = 0;
  692. printf(" TX: int %lu chars %lu THRE TO %lu%sn",
  693.  asyp->txints,asyp->txchar,asyp->txto,
  694.  asyp->dma.busy ? " BUSY" : "");
  695. }
  696. /* Send a message on the specified serial line */
  697. int
  698. asy_send(dev,bpp)
  699. int dev;
  700. struct mbuf **bpp;
  701. {
  702. if(dev < 0 || dev >= ASY_MAX){
  703. free_p(bpp);
  704. return -1;
  705. }
  706. while(*bpp != NULL){
  707. /* Send the buffer */
  708. asy_write(dev,(*bpp)->data,(*bpp)->cnt);
  709. /* Now do next buffer on chain */
  710. *bpp = free_mbuf(bpp);
  711. }
  712. return 0;
  713. }
  714. /* Attach an AST 4-port serial interface (or clone) to the system
  715.  * argv[0]: hardware type, must be "4port"
  716.  * argv[1]: I/O address, e.g., "0x2a0"
  717.  * argv[2]: vector, e.g., "5",
  718.  */
  719. int
  720. fp_attach(argc,argv,p)
  721. int argc;
  722. char *argv[];
  723. void *p;
  724. {
  725. int i;
  726. struct fport *fp;
  727. for(i=0;i<FPORT_MAX;i++){
  728. if(Fport[i].base == 0)
  729. break;
  730. }
  731. if(i == FPORT_MAX){
  732. printf("Too many 4port devicesn");
  733. return 1;
  734. }
  735. fp = &Fport[i];
  736. fp->base = htoi(argv[1]);
  737. fp->irq = atoi(argv[2]);
  738. fp->iv = fp->base + 0x1f;
  739. setirq(fp->irq,Fphand[i]);
  740. maskon(fp->irq);
  741. outportb(fp->iv,0x80); /* Enable global interrupts */
  742. return 0;
  743. }
  744. void
  745. fp_stop()
  746. {
  747. int i;
  748. struct fport *fp;
  749. for(i=0;i<FPORT_MAX;i++){
  750. if(Fport[i].base == 0)
  751. continue;
  752. fp = &Fport[i];
  753. outportb(fp->iv,0); /* Disable global interrupts */
  754. maskoff(fp->irq);
  755. }
  756. }