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

TCP/IP协议栈

开发平台:

Visual C++

  1. /*
  2.  * Interface driver for the VE3IFB 8530 card (PI card)
  3.  * Copyright 1990 by Dave Perry, VE3IFB
  4.  * Minor delinting - KA9Q 2/2/91
  5.  *
  6.  * Portions of this driver were derived from the Eagle card
  7.  * driver by Art Goldman, WA3CVG. It has been very extensively
  8.  * modified from his work, due to the addition of DMA support
  9.  * and due to differences in the hardware.  The PI card is NOT
  10.  * an Eagle card clone. It is an original design by Dave Perry,
  11.  * VE3IFB.  Art's copyright notice follows:
  12.  *
  13.  *  Written by Art Goldman, WA3CVG - (c) Copyright 1987 All Rights Reserved
  14.  *  Permission for non-commercial use is hereby granted provided this notice
  15.  *  is retained.  For info call: (301) 997-3838.
  16.  *
  17.  */
  18. #include <time.h>
  19. #include <stdio.h>
  20. #include <dos.h>
  21. #include <bios.h>
  22. #include "global.h"
  23. #include "mbuf.h"
  24. #include "iface.h"
  25. #include "pktdrvr.h"
  26. #include "netuser.h"
  27. #include "pi.h"
  28. #include "z8530.h"
  29. #include "ax25.h"
  30. #include "trace.h"
  31. #include "nospc.h"
  32. #include "session.h"
  33. #include "lapb.h"
  34. #include "proc.h"
  35. #include "ip.h"
  36. #include "devparam.h"
  37. #ifndef FP_OFF
  38. #define FP_OFF(fp) ((unsigned)(fp))
  39. #endif
  40. #ifndef FP_SEG
  41. #define FP_SEG(fp) ((unsigned)((unsigned long)(fp) >> 16))
  42. #endif
  43. void b_rxint(struct pichan *);
  44. void b_txint(struct pichan *);
  45. void b_exint(struct pichan *);
  46. void a_rxint(struct pichan *);
  47. void a_txint(struct pichan *);
  48. void a_exint(struct pichan *);
  49. static void xwrite_scc(struct pichan *hp,uint16 ctl,uint16 reg,
  50. uint16 val );
  51. static char xread_scc(struct pichan *hp, uint16 ctl, char reg);
  52. static int32 pi_ctl(struct iface *iface,int cmd,int set,int32 val);
  53. static int pi_raw(struct iface *iface,struct mbuf **bpp);
  54. static int pi_stop(struct iface *iface);
  55. static void rts(struct pichan *hp, uint16 x);
  56. void setup_rx_dma(struct pichan *hp);
  57. void setup_tx_dma(struct pichan *hp);
  58. static void set_acc_delay(void);
  59. static void tdelay(register struct pichan *hp,unsigned int time);
  60. static int scc_init(register struct pichan *hp);
  61. static struct PITAB Pi[PIMAX]; /* Device table - one entry per card */
  62. static INTERRUPT (*pihandle[])() = { /* handler interrupt vector table */
  63. pi0vec,
  64. pi1vec,
  65. pi2vec
  66. };
  67. static uint16 Page_regs[] = {
  68. 0x87,0x83,0x81,0x82,0,0x8b,0x89,0x8a
  69. };
  70. static struct pichan Pichan[2*PIMAX]; /* channel table - 2 entries per card */
  71. static uint16 pinbr;
  72. extern uint16 acc_delay; /* Delay for the 8530 chip access recovery time */
  73. /* This calculates the constant to be used in the delay loops
  74.  *  which satify the SCC's access recovery time.  It needs to be timed and
  75.  *  calculated because a fixed value would not work in a 4.77mhz XT
  76.  *  to a 40mhz 486 (and beyond).
  77.  */
  78. static void
  79. set_acc_delay()
  80. {
  81. long starttime, endtime;
  82. int n;
  83. int ticks;
  84. starttime = bioscnt();
  85. for(n = 0; n < 10; n++)
  86. mloop();
  87. endtime = bioscnt();
  88. ticks = (int) (endtime - starttime);
  89. if(ticks == 0)
  90. ticks = 1;
  91. acc_delay = 61/ticks;
  92. if(acc_delay == 0)
  93. acc_delay = 1;
  94. fflush(stdout);
  95. }
  96. /* Write 8530 register */
  97. static void
  98. xwrite_scc(hp,ctl,reg,val)
  99. register struct pichan *hp;
  100. register uint16 ctl;
  101. uint16 reg,val;
  102. {
  103. wrtscc(hp->cardbase,ctl,reg,val);
  104. }
  105. /* Read 8530 register */
  106. static char
  107. xread_scc(hp,ctl,reg)
  108. register struct pichan *hp;
  109. register uint16 ctl;
  110. char reg;
  111. {
  112. return(rdscc(hp->cardbase,ctl,reg));
  113. }
  114. /* Setup 8253 chip for time delay */
  115. static void
  116. tdelay(hp,time)
  117. register struct pichan *hp;
  118. unsigned int time;  /* Time to delay in milliseconds */
  119. {
  120. int n,port;
  121. unsigned int t1;
  122. unsigned char sc;
  123. if(hp->base & 2){ /* If A channel */
  124. sc = SC1;
  125. t1 = time;
  126. port = hp->cardbase+TMR1;
  127. } else {
  128. sc = SC2;
  129. t1 = 10 * time; /* 10s of milliseconds for the B channel */
  130. port = hp->cardbase+TMR2;
  131. }
  132. /* Setup timer sc */
  133. outportb(hp->cardbase+TMRCMD, sc|LSB_MSB|MODE0);
  134. /* satisfy access time restriction */
  135. for(n=0; n<5;n++)
  136. ;
  137. /* times 2 to make millisecs */
  138. outportb(port, (t1 << 1) & 0xFF);
  139. /* satisfy access time restriction */
  140. for(n=0; n<5;n++)
  141. ;
  142. outportb(port, (t1 >> 7) & 0xFF);
  143. /* Enable correct int for timeout */
  144. xwrite_scc(hp,hp->base+CTL,R15,CTSIE);
  145. xwrite_scc(hp,hp->base+CTL,R1,EXT_INT_ENAB);
  146. xwrite_scc(hp,hp->base+CTL,R0,RES_EXT_INT);
  147. }
  148. /* Master interrupt handler.  One interrupt at a time is handled.
  149.  * here. Service routines are called from here.
  150.  */
  151. INTERRUPT (far *(piint)(dev))()
  152. int dev;
  153. {
  154. register char st;
  155. register uint16 pcbase;
  156. struct pichan *hp;
  157. struct PITAB *pip;
  158. pip = &Pi[dev];
  159. pip->ints++;
  160. pcbase = pip->addr;
  161. /* Read interrupt status register (only valid from channel A)
  162.  * Process all pending interrupts in while loop
  163.  */
  164. hp = &Pichan[2 * dev]; /* Assume channel A */
  165. while((st = xread_scc(hp,pcbase+CHANA+CTL,R3)) != 0){
  166. if(st & CHARxIP){
  167. /* Channel A Rcv Interrupt Pending */
  168. hp = &Pichan[2 * dev];
  169. a_rxint(hp);
  170. } else if(st & CHATxIP){
  171. /* Channel A Transmit Int Pending */
  172. hp = &Pichan[2 * dev];
  173. a_txint(hp);
  174. } else if(st & CHAEXT){
  175. /* Channel A External Status Int */
  176. hp = &Pichan[2 * dev];
  177. a_exint(hp);
  178. } else if(st & CHBRxIP){
  179. /* Channel B Rcv Interrupt Pending */
  180. hp = &Pichan[(2 * dev)+1];
  181. b_rxint(hp);
  182. } else if(st & CHBTxIP){
  183. /* Channel B Transmit Int Pending */
  184. hp = &Pichan[(2 * dev)+1];
  185. b_txint(hp);
  186. } else if(st & CHBEXT){
  187. /* Channel B External Status Int */
  188. hp = &Pichan[(2 * dev)+1];
  189. b_exint(hp);
  190. }
  191. /* Reset highest interrupt under service */
  192. xwrite_scc(hp,hp->base+CTL,R0,RES_H_IUS);
  193. } /* End of while loop on int processing */
  194. return pip->chain ? pip->oldvec : NULL;
  195. }
  196. static void
  197. a_exint(hp)
  198. register struct pichan *hp;
  199. {
  200. register uint16 cmd;
  201. char st;
  202. int32 t,ca;
  203. struct mbuf *bp;
  204. int i_state;
  205. i_state = dirps();
  206. st = xread_scc(hp,hp->base+CTL,R0);     /* Fetch status */
  207. /* reset external status latch */
  208. xwrite_scc(hp,CTL+hp->base,R0,RES_EXT_INT);
  209. cmd = hp->base+CTL;
  210. hp->exints++;
  211. if((hp->rstate >= ACTIVE) && (st & BRK_ABRT)){
  212. setup_rx_dma(hp);
  213. hp->rstate = ACTIVE;
  214. }
  215. switch(hp->tstate){
  216. case ACTIVE:
  217. hp->tstate = FLAGOUT;
  218. tdelay(hp,hp->squeldelay);
  219. break;
  220. case FLAGOUT:
  221. if((bp = dequeue(&hp->sndq)) == NULL){
  222. /* Nothing to send - return to receive mode */
  223. hp->tstate = IDLE;
  224. rts(hp,OFF);
  225. restore(i_state);
  226. return;
  227. }
  228. /* Get all chars */
  229. hp->txcnt = pullup(&bp,hp->sndbuf,hp->bufsiz);
  230. free_p(&bp); /* Truncate overly long packets */
  231. /* NOTE - fall through if more to send */
  232. case ST_TXDELAY:
  233. /* Disable DMA chan */
  234. outportb(DMA_MASK, DMA_DISABLE|hp->dmachan);
  235. /* Set up for TX dma */
  236. xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|EXT_INT_ENAB);
  237. /* Setup DMA controller for tx */
  238. setup_tx_dma(hp);
  239. /* select transmit interrupts to enable */
  240. /* Allow DMA on chan */
  241. outportb(DMA_MASK,DMA_ENABLE|hp->dmachan);
  242. /* reset CRC, Txint pend*/
  243. xwrite_scc(hp,cmd,R0,RES_Tx_CRC|RES_Tx_P);
  244. /* allow Underrun int only */
  245. xwrite_scc(hp,cmd,R15,TxUIE);
  246. /* Enable TX DMA */
  247. xwrite_scc(hp,cmd,R1,WT_RDY_ENAB|WT_FN_RDYFN|EXT_INT_ENAB);
  248. /* Send CRC on underrun */
  249. xwrite_scc(hp,cmd,R0,RES_EOM_L);
  250. /* packet going out now */
  251. hp->tstate = ACTIVE;
  252. break;
  253. case DEFER:
  254. /* we have deferred prev xmit attempt
  255.  * See Intel Microcommunications Handbook, p2-308
  256.  */
  257. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  258. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  259. if((xread_scc(hp,cmd,R0) & DCD) != 0){
  260. hp->tstate = DEFER;
  261. tdelay(hp,100);
  262. /* Defer until dcd transition or 100mS timeout */
  263. xwrite_scc(hp,CTL+hp->base,R15,CTSIE|DCDIE);
  264. restore(i_state);
  265. return;
  266. }
  267. /* Defer logic. Wait until deftime is in the past (so we
  268.  * defer to any overheard CTS messages) AND the p-persistence
  269.  * dice roll succeeds. The computation of ca allows for clock
  270.  * rollover (which happens every 49+ days).
  271.  */
  272. t = msclock();
  273. ca = hp->deftime - t;
  274. if(ca > 0){
  275. hp->tstate = DEFER;
  276. tdelay(hp,ca);
  277. restore(i_state);
  278. return;
  279. }
  280. hp->deftime = t; /* Keep from getting too old */
  281. if((rand() & 0xff) > hp->persist){
  282. hp->tstate = DEFER;
  283. tdelay(hp,hp->slotime);
  284. restore(i_state);
  285. return;
  286. }
  287. /* Assert RTS early minimize collision window */
  288. xwrite_scc(hp,cmd,R5,TxCRC_ENAB|RTS|Tx8);
  289. rts(hp,ON); /* Transmitter on */
  290. hp->tstate = ST_TXDELAY;
  291. tdelay(hp,hp->txdelay);
  292. restore(i_state);
  293. return;
  294. } /* switch(hp->tstate) */
  295. restore(i_state);
  296. } /* a_exint() */
  297. /* Receive interrupt handler for the A channel 
  298.  */
  299. static void
  300. a_rxint(hp)
  301. register struct pichan *hp;
  302. {
  303. register uint16 cmd;
  304. register uint16 bytecount;
  305. char rse;
  306. struct mbuf *bp;
  307. int i_state;
  308. hp->rxints++;
  309. cmd = hp->base+CTL;
  310. i_state = dirps();
  311. rse = xread_scc(hp,cmd,R1); /* Get special condition bits from R1 */
  312. if(rse & Rx_OVR){
  313. /* If receiver overrun */
  314. hp->rovers++;
  315. hp->rstate = RXERROR;
  316. }
  317. if(rse & END_FR){
  318. /* If end of frame */
  319. /* figure length of frame from 8237 */
  320. outportb(DMA_RESETFF,0); /* reset firstlast ff */
  321. bytecount = inportb(DMABASE+2*hp->dmachan+1);
  322. bytecount += inportb(DMABASE+2*hp->dmachan+1) << 8;
  323. bytecount = hp->bufsiz - 1 - bytecount;
  324. if((rse & CRC_ERR)||(hp->rstate > ACTIVE)||(bytecount < 10)){
  325. if((bytecount >= 10) && (rse & CRC_ERR))
  326. hp->crcerr++; /* Ignore noise */
  327. /* Reset buffer pointers */
  328. hp->rstate = ACTIVE;
  329. setup_rx_dma(hp);
  330. } else {
  331. /* Here we have a valid frame. Copy to buffer,
  332.  * minus 2 CRC bytes
  333.  */
  334. bytecount -= 2;
  335. if((bp = alloc_mbuf(bytecount+sizeof(struct iface *)))
  336.  != NULL){
  337. bp->data += sizeof(struct iface *);
  338. bp->cnt = bytecount;
  339. memcpy(bp->data,hp->rcvbuf,bytecount);
  340. net_route(hp->iface,&bp);
  341. hp->rxcnt = 0;
  342. hp->rxframes++;
  343. }
  344. /* packet queued - get buffer for next frame */
  345. setup_rx_dma(hp);
  346. } /* end good frame queued */
  347. } /* end EOF check */
  348. xwrite_scc(hp,hp->base+CTL,R0,ERR_RES); /* error reset */
  349. restore(i_state);
  350. }
  351. void
  352. a_txint(hp)
  353. register struct pichan *hp;
  354. {
  355. register uint16 cmd;
  356. int32 t,ca;
  357. struct mbuf *bp;
  358. int i_state;
  359. cmd = CTL+hp->base;
  360. i_state = dirps();
  361. switch(hp->tstate){
  362. case IDLE:
  363. /* Transmitter idle. Find a frame for transmission */
  364. if((bp = dequeue(&hp->sndq)) == NULL){
  365. rts(hp,OFF);
  366. restore(i_state);
  367. return;
  368. }
  369. /* If a buffer to send, we drop thru here */
  370. hp->txcnt = pullup(&bp,hp->sndbuf,hp->bufsiz);
  371. free_p(&bp); /* Truncate overly long packet */
  372. hp->tcp = hp->sndbuf;
  373. case DEFER:
  374. /* we may have deferred prev xmit attempt */
  375. /* Check DCD - debounce it
  376.  * See Intel Microcommunications Handbook, p2-308
  377.  */
  378. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  379. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  380. if((xread_scc(hp,cmd,R0) & DCD) != 0){
  381. hp->tstate = DEFER;
  382. tdelay(hp,100);
  383. /* defer until DCD transition or timeout */
  384. xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
  385. restore(i_state);
  386. return;
  387. }
  388. /* Defer logic. Wait until deftime is in the past (so we
  389.  * defer to any overheard CTS messages) AND the p-persistence
  390.  * dice roll succeeds. The computation of ca allows for clock
  391.  * rollover (which happens every 49+ days).
  392.  */
  393. t = msclock();
  394. ca = hp->deftime - t;
  395. if(ca > 0){
  396. hp->tstate = DEFER;
  397. tdelay(hp,ca);
  398. restore(i_state);
  399. return;
  400. }
  401. hp->deftime = t; /* Keep from getting too old */
  402. if((rand() & 0xff) > hp->persist){
  403. hp->tstate = DEFER;
  404. tdelay(hp,hp->slotime);
  405. restore(i_state);
  406. return;
  407. }
  408. /* Assert RTS early minimize collision window */
  409. xwrite_scc(hp,cmd,R5,TxCRC_ENAB|RTS|Tx8);
  410. rts(hp,ON); /* Transmitter on */
  411. hp->tstate = ST_TXDELAY;
  412. tdelay(hp,hp->txdelay);
  413. restore(i_state);
  414. return;
  415. default:
  416. break;
  417. } /* end switch(hp->state) */
  418. restore(i_state);
  419. } /*a_txint */
  420. static void
  421. b_rxint(hp)
  422. register struct pichan *hp;
  423. {
  424. register uint16 cmd;
  425. char rse;
  426. struct mbuf *bp;
  427. int i_state;
  428. hp->rxints++;
  429. cmd = CTL+hp->base;
  430. i_state = dirps();
  431. if((xread_scc(hp,cmd,R0)) & Rx_CH_AV){
  432. /* there is a char to be stored
  433.  * read special condition bits before reading the data char
  434.  */
  435. rse = xread_scc(hp,cmd,R1); /* get status byte from R1 */
  436. if(rse & Rx_OVR){
  437. /* Rx overrun - toss buffer */
  438. /* reset buffer pointers */
  439. hp->rcp = hp->rcvbuf;
  440. hp->rxcnt = 0;
  441. hp->rstate = RXERROR; /* set error flag */
  442. hp->rovers++;
  443. } else if(hp->rxcnt >= hp->bufsiz){
  444. /* Too large -- toss entire frame */
  445. /* reset buffer pointers */
  446. hp->rcp = hp->rcvbuf;
  447. hp->rxcnt = 0;
  448. hp->rstate = TOOBIG; /* when set, chars are not stored */
  449. }
  450. /* ok, we can store the received character now */
  451. if(hp->rstate == ACTIVE){ /* If no errors... */
  452. *hp->rcp++ = xread_scc(hp,cmd,R8); /* char to rcv buff */
  453. hp->rxcnt++;    /* bump count */
  454. } else {
  455. /* got to empty FIFO */
  456. (void) xread_scc(hp,cmd,R8);
  457. xwrite_scc(hp,cmd,R0,ERR_RES); /* reset err latch */
  458. hp->rstate = ACTIVE;
  459. }
  460. }
  461. if(rse & END_FR){
  462. /* END OF FRAME -- Make sure Rx was active */
  463. if(hp->rxcnt > 0){
  464. if((rse & CRC_ERR)||(hp->rstate > ACTIVE)||(hp->rxcnt < 10)){
  465. if((hp->rxcnt >= 10) && (rse & CRC_ERR))
  466. hp->crcerr++; /* Ignore noise */
  467. hp->rcp = hp->rcvbuf;
  468. hp->rxcnt = 0;
  469. } else {
  470. /* Here we have a valid frame */
  471. hp->rxcnt -= 2;  /* Toss 2 crc bytes */
  472. if((bp = alloc_mbuf(hp->rxcnt+sizeof(struct iface *)))
  473.  != NULL){
  474. bp->data += sizeof(struct iface *);
  475. bp->cnt = hp->rxcnt;
  476. memcpy(bp->data,hp->rcvbuf,hp->rxcnt);
  477. net_route(hp->iface,&bp);
  478. hp->rxframes++;
  479. }
  480. /* packet queued - get ready for next frame */
  481. hp->rcp = hp->rcvbuf;
  482. hp->rxcnt = 0;
  483. } /* end good frame queued */
  484. }  /* end check for active receive upon EOF */
  485. hp->rstate = ACTIVE; /* and clear error status */
  486. } /* end EOF check */
  487. restore(i_state);
  488. }
  489. static void
  490. b_txint(hp)
  491. register struct pichan *hp;
  492. {
  493. register uint16 cmd;
  494. char c;
  495. struct mbuf *bp;
  496. int i_state;
  497. cmd = CTL+hp->base;
  498. i_state = dirps();
  499. if(hp->tstate != DEFER && hp->tstate)
  500. hp->txints++;
  501. switch(hp->tstate){
  502. case CRCOUT:
  503. hp->tstate = FLAGOUT;
  504. tdelay(hp,hp->squeldelay);
  505. restore(i_state);
  506. return;
  507. case IDLE:
  508. /* Transmitter idle. Find a frame for transmission */
  509. if((bp = dequeue(&hp->sndq)) == NULL){
  510. /* Nothing to send - return to receive mode
  511.  * Tx OFF now - flag should have gone
  512.  */
  513. rts(hp,OFF);
  514. restore(i_state);
  515. return;
  516. }
  517. hp->txcnt = pullup(&bp,hp->sndbuf,hp->bufsiz);
  518. free_p(&bp); /* Truncate overly long packets */
  519. /* If a buffer to send, we drop thru here */
  520. case DEFER:     /* we may have deferred prev xmit attempt */
  521. /* Check DCD - debounce it */
  522. /* See Intel Microcommunications Handbook, p2-308 */
  523. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  524. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  525. if((xread_scc(hp,cmd,R0) & DCD) != 0){
  526. hp->tstate = DEFER;
  527. tdelay(hp,100);
  528. /* defer until DCD transition or timeout */
  529. xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
  530. restore(i_state);
  531. return;
  532. }
  533. /* p - persist calculation */
  534. if(inportb(hp->cardbase+TMR0) > hp->persist){
  535. inportb(hp->cardbase+TMR0); /* Discard MSB */
  536. hp->tstate = DEFER;
  537. tdelay(hp,hp->slotime);
  538. restore(i_state);
  539. return;
  540. }
  541. inportb(hp->cardbase+TMR0); /* Discard MSB */
  542. rts(hp,ON);   /* Transmitter on */
  543. hp->tstate = ST_TXDELAY;
  544. tdelay(hp,hp->txdelay);
  545. restore(i_state);
  546. return;
  547. case ACTIVE:
  548. /* Here we are actively sending a frame */
  549. if(hp->txcnt-- != 0){
  550. c = *hp->tcp++;
  551. /* next char is gone */
  552. xwrite_scc(hp,cmd,R8,c);
  553. /* stuffing a char satisfies Interrupt condition */
  554. } else {
  555. /* No more to send */
  556. if((xread_scc(hp,cmd,R0) & 0x40)){
  557. /* Did we underrun? */
  558. /* unexpected underrun */
  559. hp->tunders++;
  560. xwrite_scc(hp,cmd,R0,SEND_ABORT);
  561. hp->tstate = FLAGOUT;
  562. tdelay(hp,hp->squeldelay);
  563. restore(i_state);
  564. return;
  565. }
  566. hp->tstate = UNDERRUN; /* Now we expect to underrun */
  567. /* Send flags on underrun */
  568. if(hp->speed){ /* If externally clocked */
  569. xwrite_scc(hp,cmd,R10,CRCPS|NRZI);
  570. } else {
  571. xwrite_scc(hp,cmd,R10,CRCPS);
  572. }
  573. xwrite_scc(hp,cmd,R0,RES_Tx_P); /* reset Tx Int Pend */
  574. }
  575. restore(i_state);
  576. return;     /* back to wait for interrupt */
  577. } /* end switch */
  578. restore(i_state);
  579. }
  580. /* Pi SIO External/Status interrupts (for the B channel)
  581.  * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
  582.  * Receiver automatically goes to Hunt on an abort.
  583.  *
  584.  * If the Tx Underrun interrupt hits, change state and
  585.  * issue a reset command for it, and return.
  586.  */
  587. static void
  588. b_exint(hp)
  589. register struct pichan *hp;
  590. {
  591. char st;
  592. register uint16 cmd;
  593. char c;
  594. struct mbuf *bp;
  595. int i_state;
  596. cmd = CTL+hp->base;
  597. hp->exints++;
  598. i_state = dirps();
  599. st = xread_scc(hp,cmd,R0);     /* Fetch status */
  600. /* reset external status latch */
  601. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  602. switch(hp->tstate){
  603. case ACTIVE: /* Unexpected underrun */
  604. xwrite_scc(hp,cmd,R0,SEND_ABORT);
  605. hp->tstate = FLAGOUT;
  606. hp->tunders++;
  607. tdelay(hp,hp->squeldelay);
  608. restore(i_state);
  609. return;
  610. case UNDERRUN:
  611. hp->tstate = CRCOUT;
  612. restore(i_state);
  613. return;
  614. case FLAGOUT: 
  615. /* Find a frame for transmission */
  616. if((bp = dequeue(&hp->sndq)) == NULL){
  617. /* Nothing to send - return to receive mode
  618.  * Tx OFF now - flag should have gone
  619.  */
  620. rts(hp,OFF);
  621. hp->tstate = IDLE;
  622. restore(i_state);
  623. return;
  624. }
  625. hp->txcnt = pullup(&bp,hp->sndbuf,hp->bufsiz);
  626.                 free_p(&bp); /* Truncate overly long packets */
  627. hp->tcp = hp->sndbuf;
  628. /* Get next char to send */
  629. c = *hp->tcp++;
  630. hp->txcnt--;
  631. xwrite_scc(hp,cmd,R0,RES_Tx_CRC);/* reset for next frame */
  632. /* Send abort on underrun */
  633. if(hp->speed){ /* If externally clocked */
  634. xwrite_scc(hp,cmd,R10,CRCPS|NRZI|ABUNDER);
  635. } else {
  636. xwrite_scc(hp,cmd,R10,CRCPS|ABUNDER);
  637. }
  638. xwrite_scc(hp,cmd,R8,c); /* First char out now */
  639. xwrite_scc(hp,cmd,R0,RES_EOM_L);/* Reset end of message latch */
  640. /* select transmit interrupts to enable */
  641. xwrite_scc(hp,cmd,R15,TxUIE); /* allow Underrun int only */
  642. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  643. xwrite_scc(hp,cmd,R1,TxINT_ENAB|EXT_INT_ENAB);  /* Tx/Extern ints on */
  644. hp->tstate = ACTIVE; /* char going out now */
  645. restore(i_state);
  646. return;
  647. case DEFER:
  648. /* Check DCD - debounce it
  649.  * See Intel Microcommunications Handbook, p2-308
  650.  */
  651. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  652. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  653. if((xread_scc(hp,cmd,R0) & DCD) != 0){
  654. hp->tstate = DEFER;
  655. tdelay(hp,100);
  656. /* defer until DCD transition or timeout */
  657. xwrite_scc(hp,cmd,R15,CTSIE|DCDIE);
  658. restore(i_state);
  659. return;
  660. }
  661. /* p - persist calculation */
  662. if(inportb(hp->cardbase+TMR0) > hp->persist){
  663. inportb(hp->cardbase+TMR0); /* Discard MSB */
  664. hp->tstate = DEFER;
  665. tdelay(hp,hp->slotime);
  666. restore(i_state);
  667. return;
  668. }
  669. inportb(hp->cardbase+TMR0); /* Discard MSB */
  670. rts(hp,ON);   /* Transmitter on */
  671. hp->tstate = ST_TXDELAY;
  672. tdelay(hp,hp->txdelay);
  673. restore(i_state);
  674. return;
  675. case ST_TXDELAY:
  676. /* Get next char to send */
  677. c = *hp->tcp++;
  678. hp->txcnt--;
  679. xwrite_scc(hp,cmd,R0,RES_Tx_CRC);/* reset for next frame */
  680. /* Send abort on underrun */
  681. if(hp->speed){ /* If externally clocked */
  682. xwrite_scc(hp,cmd,R10,CRCPS|NRZI|ABUNDER);
  683. } else {
  684. xwrite_scc(hp,cmd,R10,CRCPS|ABUNDER);
  685. }
  686. xwrite_scc(hp,cmd,R8,c); /* First char out now */
  687. xwrite_scc(hp,cmd,R0,RES_EOM_L);/* Reset end of message latch */
  688. /* select transmit interrupts to enable */
  689. xwrite_scc(hp,cmd,R15,TxUIE); /* allow Underrun int only */
  690. xwrite_scc(hp,cmd,R0,RES_EXT_INT);
  691. /* Tx/Extern ints on */
  692. xwrite_scc(hp,cmd,R1,TxINT_ENAB|EXT_INT_ENAB);
  693. hp->tstate = ACTIVE; /* char going out now */
  694. restore(i_state);
  695. return;
  696. }
  697. /* Receive Mode only
  698.  * This triggers when hunt mode is entered, & since an ABORT
  699.  * automatically enters hunt mode, we use that to clean up
  700.  * any waiting garbage
  701.  */
  702. if((hp->rstate == ACTIVE) && (st & BRK_ABRT)){
  703. (void) xread_scc(hp,cmd,R8);
  704. (void) xread_scc(hp,cmd,R8);
  705. (void) xread_scc(hp,cmd,R8);
  706. hp->rcp = hp->rcvbuf;
  707. hp->rxcnt = 0;       /* rewind on DCD transition */
  708. }
  709. restore(i_state);
  710. }
  711. /* SET Transmit or Receive Mode
  712.  * Set RTS (request-to-send) to modem on Transmit
  713.  */
  714. static void
  715. rts(hp,x)
  716. register struct pichan *hp;
  717. uint16 x;
  718. {
  719. uint16 tc;
  720. long br;
  721. uint16 cmd;
  722. cmd = CTL+hp->base;
  723. /* Reprogram BRG and turn on transmitter to send flags */
  724. if(x == ON){ /* Turn Tx ON and Receive OFF */
  725. /* Exints off first to avoid abort int */
  726. xwrite_scc(hp,cmd,R15,0);
  727. xwrite_scc(hp,cmd,R3,Rx8); /* Rx off */
  728. hp->rstate = IDLE;
  729. if(cmd & 2){ /* if channel a */
  730. /* Set up for TX dma */
  731. xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|EXT_INT_ENAB);
  732. } else {
  733. xwrite_scc(hp,cmd,R1,0); /* No interrupts */
  734. }
  735. if(hp->speed){ /* if internally clocked */
  736. br = hp->speed; /* get desired speed */
  737. tc = (XTAL/br)-2; /* calc 1X BRG divisor */
  738. xwrite_scc(hp,cmd,R12,tc&0xFF);     /* lower byte */
  739. xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF);/* upper byte */
  740. }
  741. xwrite_scc(hp,cmd,R5,TxCRC_ENAB|RTS|TxENAB|Tx8|DTR);
  742. /* Transmitter now on */
  743. } else { /* Tx OFF and Rx ON */
  744. hp->tstate = IDLE;
  745. xwrite_scc(hp,cmd,R5,Tx8|DTR);  /*  TX off */
  746. if(hp->speed){ /* if internally clocked */
  747. /* Reprogram BRG for 32x clock for receive DPLL */
  748. /* BRG off, keep Pclk source */
  749. xwrite_scc(hp,cmd,R14,BRSRC);
  750. br = hp->speed; /* get desired speed */
  751. /* calc 32X BRG divisor */
  752. tc = ((XTAL/32)/br)-2;
  753. xwrite_scc(hp,cmd,R12,tc&0xFF); /* lower byte */
  754. xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF);/* upper byte */
  755. /* SEARCH mode, BRG source */
  756. xwrite_scc(hp,cmd,R14,BRSRC|SEARCH);
  757. /* Enable the BRG */
  758. xwrite_scc(hp,cmd,R14,BRSRC|BRENABL);
  759. }
  760. /* Now, turn on the receiver and hunt for a flag */
  761. xwrite_scc(hp,cmd,R3,RxENABLE|RxCRC_ENAB|Rx8);
  762. hp->rstate = ACTIVE; /* Normal state */
  763. if(cmd & 2){/* if channel a */
  764. setup_rx_dma(hp);
  765. } else {
  766. /* reset error bits */
  767. /* xwrite_scc(hp,cmd,R0,ERR_RES); */
  768. /* reset buffer pointers */
  769. hp->rcp = hp->rcvbuf;
  770. hp->rxcnt = 0;
  771. xwrite_scc(hp,cmd,R1,(INT_ALL_Rx|EXT_INT_ENAB));
  772. }
  773. xwrite_scc(hp,cmd,R15,BRKIE); /* allow ABORT int */
  774. /* Hold tx off long enough for other station to reply */
  775. hp->deftime = msclock() + hp->txdelay + 500;
  776. }
  777. }
  778. void
  779. setup_rx_dma(hp)
  780. register struct pichan *hp;
  781. {
  782. int cmd;
  783. int dmaport;
  784. int i_state;
  785. cmd = hp->base+CTL;
  786. dmaport = DMABASE+2*hp->dmachan;
  787. i_state = dirps();
  788. if(!hp->rcvbuf){
  789. /* No rx buffer available */
  790. restore(i_state);
  791. return;
  792. }
  793. /* Get ready for RX DMA */
  794. xwrite_scc(hp,cmd,R1,WT_FN_RDYFN|WT_RDY_RT|INT_ERR_Rx|EXT_INT_ENAB);
  795. outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA chan */
  796. /* Set DMA mode register to single transfers, incrementing address,
  797.  * auto init, writes
  798.  */
  799. outportb(DMA_MODE,DMA_RX_MODE|hp->dmachan);
  800. outportb(Page_regs[hp->dmachan],hp->rcvphys >> 16);/* Store in  64K DMA page */
  801. outportb(DMA_RESETFF,0);  /* reset byte pointer flipflop */
  802. /* Output buffer start (dest) address */
  803. outportb(dmaport,hp->rcvphys);
  804. outportb(dmaport,hp->rcvphys >> 8);
  805. /* output DMA maximum byte count */
  806. dmaport++;
  807. outportb(dmaport,hp->bufsiz - 1);
  808. outportb(dmaport, (hp->bufsiz - 1) >> 8);
  809. /* Unmask channel 1 (start DMA) */
  810. outportb(DMA_MASK, DMA_ENABLE|hp->dmachan); /* Enable DMA chan */
  811. /* If a packet is already coming in, this line is supposed
  812.  * to mess up the crc to avoid receiving a partial packet
  813.  */
  814. xwrite_scc(hp,cmd,R0,RES_Rx_CRC);
  815. /* Enable RX dma */
  816. xwrite_scc(hp,cmd,R1,WT_RDY_ENAB|WT_FN_RDYFN|WT_RDY_RT|INT_ERR_Rx|EXT_INT_ENAB);
  817. restore(i_state);
  818. }
  819. void
  820. setup_tx_dma(hp)
  821. struct pichan *hp;
  822. {
  823. int dmaport;
  824. uint16 length;
  825. int i_state;
  826. length = hp->txcnt - 1;
  827. dmaport = DMABASE + 2*hp->dmachan;
  828. i_state = dirps();
  829. outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA chan */
  830. /* Set DMA mode register to single transfers, incrementing address,
  831.  * no auto init, reads
  832.    */
  833. outportb(DMA_MODE,DMA_TX_MODE|hp->dmachan);
  834. outportb(Page_regs[hp->dmachan],hp->sndphys >> 16); /* Store in 64K DMA page */
  835. outportb(DMA_RESETFF,0); /* reset byte pointer flipflop */
  836. outportb(dmaport,hp->sndphys); /* Output buffer start (source) address */
  837. outportb(dmaport,hp->sndphys >> 8);
  838. /* output byte count */
  839. dmaport++;
  840. outportb(dmaport,length);
  841. outportb(dmaport, length >> 8);
  842. restore(i_state);
  843. }
  844. /* Initialize pi controller parameters */
  845. static int
  846. scc_init(hp)
  847. register struct pichan *hp;
  848. {
  849. uint16 tc;
  850. long br;
  851. register uint16 cmd;
  852. int i_state;
  853. /* Initialize 8530 channel for SDLC operation */
  854. cmd = CTL+hp->base;
  855. #ifdef notdef
  856. printf("Pi: Initializing Channel %c - Base = %xn",cmd&2?'A':'B',cmd&~CTL);
  857. #endif
  858. i_state = dirps();
  859. switch(cmd & 2){
  860. case 2:
  861. xwrite_scc(hp,cmd,R9,CHRA); /* Reset channel A */
  862. xwrite_scc(hp,cmd,R2,0xff); /* Initialize interrupt vector */
  863. break;
  864. case 0:
  865. xwrite_scc(hp,cmd,R9,CHRB); /* Reset channel B */
  866. break;
  867. }
  868. /* Deselect all Rx and Tx interrupts */
  869. xwrite_scc(hp,cmd,R1,0);
  870. /* Turn off external interrupts (like CTS/CD) */
  871. xwrite_scc(hp,cmd,R15,0);
  872. /* X1 clock, SDLC mode */
  873. xwrite_scc(hp,cmd,R4,SDLC|X1CLK);
  874. /* Now some misc Tx/Rx parameters */
  875. /* CRC PRESET 1, NRZI Mode */
  876. if(hp->speed){
  877. xwrite_scc(hp,cmd,R10,CRCPS|NRZI);
  878. /* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
  879. xwrite_scc(hp,cmd,R11,TCBR|RCDPLL|TRxCDP|TRxCOI);
  880. } else {
  881. xwrite_scc(hp,cmd,R10,CRCPS);
  882. /* Tx Clk from Trxcl. Rcv Clk from Rtxcl, TRxC pin is input */
  883. xwrite_scc(hp,cmd,R11,TCTRxCP);
  884. }
  885. /* Null out SDLC start address */
  886. xwrite_scc(hp,cmd,R6,0);
  887. /* SDLC flag */
  888. xwrite_scc(hp,cmd,R7,FLAG);
  889. /* Set up the Transmitter but don't enable it
  890.  *  DTR, 8 bit TX chars only - TX NOT ENABLED
  891.  */
  892. xwrite_scc(hp,cmd,R5,Tx8|DTR);
  893. /* Receiver - intial setup only - more later */
  894. xwrite_scc(hp,cmd,R3,Rx8);         /* 8 bits/char */
  895. /* Setting up BRG now - turn it off first */
  896. xwrite_scc(hp,cmd,R14,BRSRC);      /* BRG off, but keep Pclk source */
  897. /* set the 32x time constant for the BRG in Receive mode */
  898. if(hp->speed){
  899. br = hp->speed;  /* get desired speed */
  900. tc = ((XTAL/32)/br)-2; /* calc 32X BRG divisor */
  901. } else {
  902. tc = 14;
  903. }
  904. xwrite_scc(hp,cmd,R12,tc&0xFF);      /* lower byte */
  905. xwrite_scc(hp,cmd,R13,(tc>>8)&0xFF); /* upper byte */
  906. /* Following subroutine sets up and ENABLES the receiver */
  907. rts(hp,OFF);    /* TX OFF and RX ON */
  908. if(hp->speed){
  909. /* DPLL frm BRG, BRG src PCLK */
  910. xwrite_scc(hp,cmd,R14,BRSRC|SSBR);
  911. } else {
  912. /* DPLL frm rtxc,BRG src PCLK */
  913. xwrite_scc(hp,cmd,R14,BRSRC|SSRTxC);
  914. }
  915. xwrite_scc(hp,cmd,R14,BRSRC|SEARCH); /* SEARCH mode, keep BRG source */
  916. xwrite_scc(hp,cmd,R14,BRSRC|BRENABL);/* Enable the BRG */
  917. if(!(cmd & 2)) /* if channel b */
  918. xwrite_scc(hp,cmd,R1,(INT_ALL_Rx|EXT_INT_ENAB));
  919. xwrite_scc(hp,cmd,R15,BRKIE);     /* ABORT int */
  920. /* Now, turn on the receiver and hunt for a flag */
  921. xwrite_scc(hp,cmd,R3,RxENABLE|RxCRC_ENAB|Rx8);
  922. restore(i_state);
  923. return 0;
  924. }
  925. /* Attach a PI interface to the system
  926.  * argv[0]: hardware type, must be "pi"
  927.  * argv[1]: I/O address, e.g., "0x300"
  928.  * argv[2]: vector, e.g., "2"
  929.  * argv[3]: dma channel (1..3)
  930.  * argv[4]: mode, must be:
  931.  *     "ax25" (AX.25 UI frame format)
  932.  * argv[5]: interface label, e.g., "pi0"
  933.  * argv[6]: receiver packet buffer size in bytes
  934.  * argv[7]: maximum transmission unit, bytes
  935.  * argv[8]: channel A interface speed, e.g, "1200", 0 = ext. clock
  936.  * argv[9]: channel B interface speed
  937.  * argv[10]: First IP address, optional (defaults to Ip_addr);
  938.  * argv[11]: Second IP address, optional (defaults to Ip_addr);
  939.  */
  940. int
  941. pi_attach(argc,argv)
  942. int argc;
  943. char *argv[];
  944. {
  945. register struct iface *if_pca,*if_pcb;
  946. struct pichan *hp;
  947. int dev;
  948. int n;
  949. char *cp;
  950. if(acc_delay == 0){ /* Only do this once */
  951. /* Adapt recovery time delay to processor speed */
  952. set_acc_delay();
  953. }
  954. /* Quick check to make sure args are good and mycall is set */
  955. if(setencap(NULL,argv[4]) == -1){
  956. printf("PI: Mode %s unknown for interface %sn",
  957. argv[4],argv[5]);
  958. return -1;
  959. }
  960. if(if_lookup(argv[5]) != NULL){
  961. printf("PI: Interface %s already existsn",argv[5]);
  962. return -1;
  963. }
  964. if(Mycall[0] == ''){
  965. printf("PI: Set mycall firstn");
  966. return -1;
  967. }
  968. /* Note: each card must have a unique address, IRQ and DMA */
  969. if(pinbr >= PIMAX){
  970. printf("PI: Maximum of %d PI cards supportedn",PIMAX);
  971. return -1;
  972. }
  973. dev = pinbr++;
  974. /* Initialize hardware-level control structure */
  975. Pi[dev].addr = htoi(argv[1]);
  976. Pi[dev].vec = atoi(argv[2]);
  977. if(strchr(argv[2],'c') != NULL)
  978. Pi[dev].chain = 1;
  979. else
  980. Pi[dev].chain = 0;
  981. /* Set up counter chip */
  982. /* 500 uS square wave */
  983. outportb(Pi[dev].addr+TMRCMD, SC0|LSB_MSB|MODE3);
  984. for(n=0; n<5;n++) /* satisfy access time restriction */
  985. ;
  986. outportb(Pi[dev].addr+TMR0, 922 & 0xFF); 
  987. for(n=0; n<5;n++) /* satisfy access time restriction */
  988. ;
  989. outportb(Pi[dev].addr+TMR0, 922 >> 8);
  990. for(n=0; n<5;n++) /* satisfy access time restriction */
  991. ;
  992. /* Save original interrupt vector */
  993. Pi[dev].oldvec = getirq(Pi[dev].vec);
  994. /* Set new interrupt vector */
  995. if(setirq(Pi[dev].vec,pihandle[dev]) == -1){
  996. printf("PI: IRQ %u out of rangen",Pi[dev].vec);
  997. pinbr--;
  998. return -1;
  999. }
  1000. if((atoi(argv[3]) < 1) || (atoi(argv[3]) > 3)){
  1001. printf("PI: DMA %d out of rangen",atoi(argv[3]));
  1002. pinbr--;
  1003. return -1;
  1004. }
  1005. /* set params in pichan table for CHANNEL B */
  1006. hp = &Pichan[2*dev+1]; /* pi1 is offset 1 */
  1007. hp->dmachan = 0; /* Channel B does not have dma */
  1008. hp->cardbase = Pi[dev].addr;
  1009. hp->stata = Pi[dev].addr + CHANA + CTL; /* permanent status */
  1010. hp->statb = Pi[dev].addr + CHANB + CTL; /* addrs for CHANA/B*/
  1011. hp->speed = (uint16)atoi(argv[9]);
  1012. hp->base = Pi[dev].addr + CHANB;
  1013. hp->bufsiz = atoi(argv[6]);
  1014. hp->tstate = IDLE;
  1015. /* default channel access Params */
  1016. hp->txdelay = 30; /* 300 Ms */
  1017. hp->persist = 128; /* 50% persistence */
  1018. hp->slotime = 30; /* 300 Ms */
  1019. hp->squeldelay = 3; /* 30 Ms */
  1020. xwrite_scc(hp,CTL+hp->stata,R9,FHWRES);  /* Hardware reset */
  1021. /* one time only */
  1022. /* Disable interrupts with Master interrupt ctrl reg */
  1023. xwrite_scc(hp,CTL+hp->stata,R9,0);
  1024. scc_init(hp);
  1025. /* Pre-allocate a receive DMA buffer */
  1026. hp->rcvbuf = dma_malloc(&hp->rcvphys,hp->bufsiz);
  1027. if(hp->rcvbuf == NULL){
  1028. /* No memory, abort receiver */
  1029. printf("PI: No memory available for receive buffern");
  1030. /* Restore original interrupt vector */
  1031. setirq(Pi[dev].vec,Pi[dev].oldvec);
  1032. pinbr--;
  1033. return -1;
  1034. }
  1035. /* Pre-allocate a transmit DMA buffer */
  1036. hp->sndbuf = dma_malloc(&hp->sndphys,hp->bufsiz);
  1037. if(hp->sndbuf == NULL){
  1038. /* No memory, abort */
  1039. printf("PI: No memory available for transmit buffern");
  1040. /* Restore original interrupt vector */
  1041. setirq(Pi[dev].vec,Pi[dev].oldvec);
  1042. pinbr--;
  1043. free(hp->rcvbuf);
  1044. return -1;
  1045. }
  1046. hp->sndq = NULL;
  1047. /* set params in pichan table for CHANNEL A */
  1048. hp = &Pichan[2*dev]; /* pi0a is offset 0 */
  1049. hp->dmachan = (unsigned char)atoi(argv[3]);
  1050. /* Verify dma channel */
  1051. if(hp->dmachan >= 8){
  1052. printf("PI: DMA channel %d out of rangen",hp->dmachan);
  1053. free(hp->rcvbuf);
  1054. free(hp->sndbuf);
  1055. /* Restore original interrupt vector */
  1056. setirq(Pi[dev].vec,Pi[dev].oldvec);
  1057. pinbr--;
  1058. return -1;
  1059. }
  1060. hp->cardbase = Pi[dev].addr;
  1061. hp->speed = (uint16)atoi(argv[8]);
  1062. hp->base = Pi[dev].addr + CHANA;
  1063. hp->bufsiz = atoi(argv[6]);
  1064. hp->tstate = IDLE;
  1065. /* default channel access Params */
  1066. hp->txdelay = 15; /* 15 mS */
  1067. hp->persist = 128; /* 50% persistence */
  1068. hp->slotime = 15; /* 15 mS */
  1069. hp->squeldelay = 1; /* 1 mS */
  1070. /* Pre-allocate a receive buffer */
  1071. hp->rcvbuf = dma_malloc(&hp->rcvphys,hp->bufsiz);
  1072. if(hp->rcvbuf == NULL){
  1073. /* No memory, abort receiver */
  1074. printf("PI: No memory available for receive buffersn");
  1075. /* Restore original interrupt vector */
  1076. setirq(Pi[dev].vec,Pi[dev].oldvec);
  1077. pinbr--;
  1078. return -1;
  1079. }
  1080. hp->sndq = NULL;
  1081. /* Get a buffer for tx which does not cross a dma boundary */
  1082. hp->sndbuf = dma_malloc(&hp->sndphys,hp->bufsiz);
  1083. if(hp->sndbuf == NULL){
  1084. printf("PI: No memory available for transmit buffer");
  1085. /* Restore original interrupt vector */
  1086. setirq(Pi[dev].vec,Pi[dev].oldvec);
  1087. pinbr--;
  1088. free(hp->rcvbuf);
  1089. return -1;
  1090. }
  1091. /* Create interface structures and fill in details */
  1092. if_pca = (struct iface *)callocw(1,sizeof(struct iface));
  1093. if_pcb = (struct iface *)callocw(1,sizeof(struct iface));
  1094. if_pca->addr = if_pcb->addr = Ip_addr;
  1095. if(argc > 10)
  1096. if_pca->addr = resolve(argv[10]);
  1097. if(argc > 11)
  1098. if_pcb->addr = resolve(argv[11]);
  1099. if(if_pca->addr == 0 || if_pcb->addr == 0)
  1100. printf("PI: No IP address!n");
  1101. /* Append "a" to interface associated with A channel */
  1102. if_pca->name = malloc((unsigned)strlen(argv[5])+2);
  1103. strcpy(if_pca->name,argv[5]);
  1104. strcat(if_pca->name,"a");
  1105. /* Append "b" to interface associated with B channel */
  1106. if_pcb->name = malloc((unsigned)strlen(argv[5])+2);
  1107. strcpy(if_pcb->name,argv[5]);
  1108. strcat(if_pcb->name,"b");
  1109. if_pcb->mtu = if_pca->mtu = atoi(argv[7]);
  1110. if_pcb->ioctl = if_pca->ioctl = pi_ctl;
  1111. if_pca->dev = 2*dev; /* pi0a */
  1112. if_pcb->dev = 2*dev + 1; /* pi0b */
  1113. if_pcb->stop = if_pca->stop = pi_stop;
  1114. if_pcb->raw = if_pca->raw = pi_raw;
  1115. /* Must succeed, was checked at top */
  1116. setencap(if_pca,argv[4]);
  1117. setencap(if_pcb,argv[4]);
  1118. if(if_pcb->hwaddr == NULL)
  1119. if_pcb->hwaddr = mallocw(AXALEN);
  1120. memcpy(if_pcb->hwaddr,Mycall,AXALEN);
  1121. if(if_pca->hwaddr == NULL)
  1122. if_pca->hwaddr = mallocw(AXALEN);
  1123. memcpy(if_pca->hwaddr,Mycall,AXALEN);
  1124.         Pichan[2*dev].iface = if_pca;
  1125.         Pichan[2*dev+1].iface = if_pcb;
  1126. /* Link em in to the interface chain */
  1127. if_pca->next = if_pcb;
  1128. if_pcb->next = Ifaces;
  1129. Ifaces = if_pca;
  1130. scc_init(hp);
  1131. /* master interrupt enable */
  1132. xwrite_scc(hp,CTL+hp->base,R9,MIE|NV);
  1133. /* Enable interrupt */
  1134. maskon(Pi[dev].vec);
  1135. cp = if_name(if_pca," tx");
  1136. if_pca->txproc = newproc(cp,512,if_tx,0,if_pca,NULL,0);
  1137. free(cp);
  1138. cp = if_name(if_pcb," tx");
  1139. if_pcb->txproc = newproc(cp,512,if_tx,0,if_pcb,NULL,0);
  1140. free(cp);
  1141. return 0;
  1142. }
  1143. /* Shut down interface */
  1144. int
  1145. pi_stop(iface)
  1146. struct iface *iface;
  1147. {
  1148. uint16 dev;
  1149. struct pichan *hp;
  1150. dev = iface->dev;
  1151. if(dev & 1) /* Because there are 2 devices per card */
  1152. return 0;
  1153. dev >>= 1; /* Convert back into pi number */
  1154. hp = &Pichan[2*dev]; /* pi0a is offset 0 */
  1155. outportb(DMA_MASK, DMA_DISABLE|hp->dmachan); /* Disable DMA channel */
  1156. /* Turn off interrupts */
  1157. maskoff(Pi[dev].vec);
  1158. /* Restore original interrupt vector */
  1159. setirq(Pi[dev].vec,Pi[dev].oldvec);
  1160. /* Force hardware reset */
  1161. xwrite_scc(&Pichan[2*dev],CTL+Pi[dev].addr + CHANA,R9,FHWRES);
  1162. return 0;
  1163. }
  1164. /* Send raw packet on pi card */
  1165. int
  1166. pi_raw(
  1167. struct iface *iface,
  1168. struct mbuf **bpp
  1169. ){
  1170. char kickflag;
  1171. struct pichan *hp;
  1172. int i_state;
  1173. dump(iface,IF_TRACE_OUT,*bpp);
  1174. iface->rawsndcnt++;
  1175. iface->lastsent = secclock();
  1176. hp = &Pichan[iface->dev];
  1177. kickflag = (hp->sndq == NULL) & (hp->sndbuf == NULL);
  1178. enqueue(&hp->sndq,bpp);
  1179. hp->enqueued++;
  1180. if(kickflag){
  1181. /* simulate interrupt to xmit */
  1182. switch(hp->base & 2){
  1183. case 2:
  1184. a_txint(hp); /* process interrupt */
  1185. break;
  1186. case 0:
  1187. i_state = dirps();
  1188. if(hp->tstate == IDLE)
  1189. b_txint(hp);
  1190. restore(i_state);
  1191. break;
  1192. }
  1193. }
  1194. return 0;
  1195. }
  1196. /* display PI Channel stats */
  1197. int
  1198. dopistat()
  1199. {
  1200. struct pichan *hp;
  1201. int i;
  1202. printf("PI Board Statistics:nn");
  1203. printf("Base Addr  Rxints  Txints  Exints  TxFrms  RxFrms  Crcerr  RxOvrs  TxUndr n");
  1204. printf("---------  ------  ------  ------  ------  ------  ------  ------  ------ n");
  1205. for(i=0; i<pinbr*2; i++){
  1206. hp = &Pichan[i];
  1207. printf("0x%03x    % 8lu% 8lu% 8lu% 8u% 8u% 8u% 8u% 8unRcv State=%s ",
  1208.  hp->base, hp->rxints, hp->txints, hp->exints, hp->enqueued,
  1209.  hp->rxframes, hp->crcerr, hp->rovers, hp->tunders,
  1210.  hp->rstate==0 ?
  1211.   "IDLE" : hp->rstate==1 ?
  1212.    "ACTIVE" : hp->rstate==2 ?
  1213.     "RXERROR" : hp->rstate==3 ?
  1214.      "RXABORT":"TOOBIG"
  1215. );
  1216. printf("Tstate = %sn",
  1217.  hp->tstate == 0 ?
  1218.   "IDLE" : hp->tstate == 1 ?
  1219.    "ACTIVE" : hp->tstate == 2 ?
  1220.     "UNDERRUN" : hp->tstate == 3 ?
  1221.      "FLAGOUT" : hp->tstate == 4 ?
  1222.       "DEFER" : hp->tstate == 5 ?
  1223.        "TXDELAY" : "CRCOUT"
  1224. );
  1225. }
  1226. return 0;
  1227. }
  1228. /* Subroutine to set kiss params in channel tables */
  1229. int32
  1230. pi_ctl(iface,cmd,set,val)
  1231. struct iface *iface;
  1232. int cmd;
  1233. int set;
  1234. int32 val;
  1235. {
  1236. struct pichan *hp;
  1237. int32 t,ca;
  1238. hp = &Pichan[iface->dev]; /* point to channel table */
  1239. switch(cmd){
  1240. case PARAM_TXDELAY:
  1241. if(set)
  1242. hp->txdelay = val;
  1243. return hp->txdelay;
  1244. case PARAM_PERSIST:
  1245. if(set)
  1246. hp->persist = val;
  1247. return hp->persist;
  1248. case PARAM_SLOTTIME:
  1249. if(set)
  1250. hp->slotime = val;
  1251. return hp->slotime;
  1252. case PARAM_TXTAIL:
  1253. if(set)
  1254. hp->squeldelay = val;
  1255. return hp->squeldelay;
  1256. case PARAM_MUTE:
  1257. if(set){
  1258. if(val == -1){
  1259. /* Special case for duration of a CTS */
  1260. val = hp->txdelay + 500;
  1261. }
  1262. hp->deftime = msclock() + val;
  1263. }
  1264. t = msclock();
  1265. ca = hp->deftime - t;
  1266. if(ca < 0){
  1267. hp->deftime = t;
  1268. ca = 0;
  1269. }
  1270. return ca;
  1271. }
  1272. return -1;
  1273. }