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

TCP/IP协议栈

开发平台:

Visual C++

  1. /*
  2.  * Interface driver for the EAGLE board for KA9Q's TCP/IP on an IBM-PC ONLY!
  3.  *
  4.  *  Written by Art Goldman, WA3CVG - (c) Copyright 1987 All Rights Reserved
  5.  *  Permission for non-commercial use is hereby granted provided this notice
  6.  *  is retained.  For info call: (301) 997-3838.
  7.  *
  8.  *  10 Jan 88 ng6q - Corrected IDLE comparison in doegstat.
  9.  *   6 Apr 88 ng6q - Changed eg_raw to prevent calling egtxint with a
  10.  *   packet in sndbuf.  Initialized sndq and rcvq in
  11.  *   eg_attach.  Added carrier detect check before
  12.  *   slot time delay in egtxint.  Should make major
  13.  *   changes to egtxint to avoid delay loops while
  14.  *   masked for receive interrupts.
  15.  */
  16. #include <stdio.h>
  17. #include <dos.h>
  18. #include "global.h"
  19. #include "mbuf.h"
  20. #include "iface.h"
  21. #include "pktdrvr.h"
  22. #include "netuser.h"
  23. #include "eagle.h"
  24. #include "z8530.h"
  25. #include "ax25.h"
  26. #include "trace.h"
  27. #include "nospc.h"
  28. #include "devparam.h"
  29. #include <time.h>
  30. static int32 eg_ctl(struct iface *iface,int cmd,int set,int32 val);
  31. static int eg_raw(struct iface *iface,struct mbuf **bpp);
  32. static int eg_stop(struct iface *iface);
  33. static void egchanparam(struct egchan *hp);
  34. static void egexint(struct egchan *hp);
  35. static void egrxint(struct egchan *hp);
  36. static void egtxint(struct egchan *hp);
  37. static void rts(struct egchan *hp,uint16 x);
  38. static void waitmsec(int n);
  39. static struct EGTAB Eagle[EGMAX]; /* Device table - one entry per card */
  40. static INTERRUPT (*eghandle[])() = { /* handler interrupt vector table */
  41. eg0vec,
  42. };
  43. static struct egchan Egchan[2*EGMAX]; /* channel table - 2 entries per card */
  44. static uint16 Egnbr;
  45. /* Master interrupt handler.  One interrupt at a time is handled.
  46.  * here. Service routines are called from here.
  47.  */
  48. INTERRUPT (far *(egint)(dev))()
  49. int dev;
  50. {
  51. register char st;
  52. register uint16 pcbase;
  53. struct egchan *hp;
  54. struct EGTAB *ep;
  55. ep = &Eagle[dev];
  56. ep->ints++;
  57. pcbase = ep->addr;
  58. /* Read interrupt status register from channel A */
  59. while((st = read_scc(pcbase+CHANA+CTL,R3)) != 0) {
  60. /* Use IFs to process ALL interrupts pending
  61.  * because we need to check all interrupt conditions
  62.  */
  63. if (st & CHARxIP) {
  64. /* Channel A Rcv Interrupt Pending */
  65. hp = &Egchan[2 * dev];
  66. egrxint(hp);
  67. } else if (st & CHATxIP) {
  68. /* Channel A Transmit Int Pending */
  69. hp = &Egchan[2 * dev];
  70. egtxint(hp);
  71. } else if (st & CHAEXT) {
  72. /* Channel A External Status Int */
  73. hp = &Egchan[2 * dev];
  74. egexint(hp);
  75. } else if (st & CHBRxIP) {
  76. /* Channel B Rcv Interrupt Pending */
  77. hp = &Egchan[(2 * dev)+1];
  78. egrxint(hp);
  79. } else if (st & CHBTxIP) {
  80. /* Channel B Transmit Int Pending */
  81. hp = &Egchan[(2 * dev)+1];
  82. egtxint(hp);
  83. } else if (st & CHBEXT) {
  84. /* Channel B External Status Int */
  85. hp = &Egchan[(2 * dev)+1];
  86. egexint(hp);
  87. }
  88. /* Reset highest interrupt under service */
  89. write_scc(hp->base+CTL,R0,RES_H_IUS);
  90. } /* End of while loop on int processing */
  91. return ep->chain ? ep->oldvec : NULL;
  92. }
  93. /* Eagle SIO External/Status interrupts
  94.  * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
  95.  * Receiver automatically goes to Hunt on an abort.
  96.  *
  97.  * If the Tx Underrun interrupt hits, change state and
  98.  * issue a reset command for it, and return.
  99.  */
  100. static void
  101. egexint(hp)
  102. register struct egchan *hp;
  103. {
  104. char st;
  105. int i_state;
  106. i_state = dirps();
  107. hp->exints++;
  108. st = read_scc(hp->base+CTL,R0);     /* Fetch status */
  109. /* Check for Tx UNDERRUN/EOM - only in Transmit Mode */
  110. if((hp->rstate==0) && (st & TxEOM)) {
  111. /* if in UNDERRUN, go to FLAGOUT state
  112.  * see explanation under egtxint()
  113.  * CRC & FLAG now going out, so
  114.  * wait for Tx BUffer Empty int
  115.  */
  116. /* If we are not in underrun, this is an unexpected
  117.  * underrun.  EOM bit should be set, so the SCC will
  118.  * now send an abort
  119.  */
  120. if(hp->tstate == UNDERRUN)
  121.     hp->tstate = FLAGOUT;
  122. /* Tx Buff EMPTY interrupt occurs after CRC is sent */
  123. }
  124. /* Receive Mode only
  125.  * This triggers when hunt mode is entered, & since an ABORT
  126.  * automatically enters hunt mode, we use that to clean up
  127.  * any waiting garbage
  128.  */
  129. if((hp->rstate == ACTIVE) && (st & BRK_ABRT)) {
  130. hp->rcp = hp->rcvbuf->data;
  131. hp->rcvbuf->cnt = 0;       /* rewind on DCD transition */
  132. hp->aborts++;       /* nbr aborts * 2 */
  133. }
  134. /* reset external status latch */
  135. write_scc(CTL+hp->base,R0,RES_EXT_INT);
  136. restore(i_state);
  137. }
  138. /* EG receive interrupt handler. The first receive buffer is pre-allocated
  139.  * in the init routine.  Thereafter, it is filled here, queued out, and a
  140.  * new one acquired.  CRC, OVERRUN and TOOBIG errors merely 'rewind' the
  141.  * pointers and reuse the same buffer.
  142.  */
  143. static void
  144. egrxint(hp)
  145. register struct egchan *hp;
  146. {
  147. register uint16 base;
  148. char rse;
  149. int i_state;
  150. i_state = dirps();
  151. hp->rxints++;
  152. base = hp->base;
  153. if ((read_scc(base+CTL,R0)) & Rx_CH_AV) {
  154. /* there is a char to be stored
  155.  * read special condition bits before reading the data char
  156.  */
  157. rse = read_scc(hp->base+CTL,R1); /* get status byte from R1 */
  158. if(rse & Rx_OVR) {
  159. /* Rx overrun - toss buffer */
  160. hp->rcp = hp->rcvbuf->data; /* reset buffer pointers */
  161. hp->rcvbuf->cnt = 0;
  162. hp->rstate = RXERROR; /* set error flag */
  163. hp->rovers++; /* count overruns */
  164. } else if(hp->rcvbuf->cnt >= hp->bufsiz) {
  165. /* Too large -- toss buffer */
  166. hp->toobig++;
  167. hp->rcp = hp->rcvbuf->data; /* reset buffer pointers */
  168. hp->rcvbuf->cnt = 0;
  169. hp->rstate = TOOBIG; /* when set, chars are not stored */
  170. }
  171. /* ok, we can store the received character now */
  172. if(hp->rstate == ACTIVE) { /* If no errors... */
  173. *hp->rcp++ = inportb(base+DATA);    /* char to rcv buff */
  174. hp->rcvbuf->cnt++;     /* bump count */
  175. } else {
  176. /* got to empty FIFO */
  177. (void) inportb(base+DATA);
  178. write_scc(hp->base+CTL,R0,ERR_RES); /* reset err latch */
  179. hp->rstate = ACTIVE;
  180. }
  181. }
  182. /* char has been stored
  183.  * read special condition bits
  184.  */
  185. rse = read_scc(hp->base+CTL,R1);     /* get status byte from R1 */
  186. /* The End of Frame bit is ALWAYS associated with a character,
  187.  * usually, it is the last CRC char.  Only when EOF is true can
  188.  * we look at the CRC byte to see if we have a valid frame
  189.  */
  190. if(rse & END_FR) {
  191. hp->rxframes++;
  192. /* END OF FRAME -- Make sure Rx was active */
  193. if(hp->rcvbuf->cnt > 0) { /* any data to store */
  194. /* looks like a frame was received
  195.  * now is the only time we can check for CRC error
  196.  */
  197. if((rse & CRC_ERR) || (hp->rstate > ACTIVE) || (hp->rcvbuf->cnt < 10)) {
  198. /* error occurred; toss frame */
  199. if(rse & CRC_ERR)
  200. hp->crcerr++; /* count CRC errs */
  201. if(hp->rstate == RXERROR)
  202. hp->rovers++;
  203. /* don't throw away buffer -
  204.  * merely reset the pointers
  205.  */
  206. hp->rcp = hp->rcvbuf->data;
  207. hp->rcvbuf->cnt = 0;
  208. } else {
  209. /* Here we have a valid frame */
  210. hp->rcvbuf->cnt -= 2;        /* Toss 2 crc bytes */
  211. net_route(hp->iface,&hp->rcvbuf);
  212. /* packet queued - get buffer for next frame */
  213. hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  214. hp->rcp = hp->rcvbuf->data;
  215. hp->rcvbuf->cnt = 0;
  216. if(hp->rcvbuf == NULL) {
  217. /* No memory, abort receiver */
  218. restore(i_state);
  219. printf("DISASTER! Out of Memory for Receive!n");
  220. write_scc(CTL+base,R3,Rx8);
  221. return;
  222. }
  223. } /* end good frame queued */
  224. }  /* end check for active receive upon EOF */
  225. hp->rstate = ACTIVE; /* and clear error status */
  226. } /* end EOF check */
  227. restore(i_state);
  228. }
  229. /* egchan transmit interrupt service routine
  230.  *
  231.  * The state variable tstate, along with some static pointers,
  232.  * represents the state of the transmit "process".
  233.  */
  234. static void
  235. egtxint(hp)
  236. register struct egchan *hp;
  237. {
  238. register uint16 base;
  239. int c;
  240. int i_state;
  241. i_state = dirps();
  242. if(hp->tstate != DEFER && hp->tstate)
  243. hp->txints++;
  244. base = hp->base;
  245. switch(hp->tstate) {
  246. case FLAGOUT:
  247. /* Here after CRC sent and Tx interrupt fires.
  248.  * To give the SCC a chance to get the FLAG
  249.  * out, we delay 100 Ms
  250.  */
  251. hp->tstate = IDLE; /* fall thru to IDLE */
  252. waitmsec(10); /* 100 msec wait for flag Tx */
  253. /* Note, it may be possible to stuff out a
  254.  * meaningless character, wait for the interrupt
  255.  * then go to idle.  A delay is absolutely necessary
  256.  * here else the packet gets truncated prematurely
  257.  * when no other packet is waiting to be sent.
  258.  * IDLE state indicates either we are starting a brand new packet
  259.  * as a result of its being queued for transmission (egtxint called
  260.  * from eg_raw), or after a frame has been transmitted (as a
  261.  * result of a Tx buffer empty interrupt after the CRC/FLAG
  262.  */
  263. case IDLE:
  264. /* Transmitter idle. Find a frame for transmission */
  265. if((hp->sndbuf = dequeue(&hp->sndq)) == NULL) {
  266. /* Nothing to send - return to receive mode
  267.  * Tx OFF now - flag should have gone
  268.  */
  269. rts(hp,OFF);
  270. restore(i_state);
  271. return;
  272. }
  273. /* If a buffer to send, we drop thru here */
  274. case DEFER:     /* we may have deferred prev xmit attempt */
  275. /* PPERSIST CALCULATION: we use the lower byte of the
  276.  * 8253 timer 0 count, as a random number (0-255).
  277.  * If the persist value is higher, wait one slot time
  278.  */
  279. if(hp->persist >= peekb(0x40,0x6c))
  280. waitmsec(hp->slotime);
  281. /* Check DCD so we don't step on a frame being received */
  282. /* DCD is ACTIVE LOW on the SCC DCD pin, but the bit in R0 */
  283. /* is SET when DCD is ACTIVE!! */
  284. if((read_scc(base+CTL,R0) & DCD) > 0) { /* Carrier Detected? */
  285. hp->tstate = DEFER; /* defer xmit */
  286. /* don't release dequeued buffer...*/
  287. restore(i_state);
  288. return;
  289. }
  290. rts(hp,ON);   /* Transmitter on */
  291. /* ints not enabled yet */
  292. /* Get next char to send */
  293. c = PULLCHAR(&hp->sndbuf);     /* one char at a time */
  294. write_scc(CTL+base,R0,RES_Tx_CRC); /* reset for next frame */
  295. outportb(base+DATA,c);     /* First char out now */
  296. /* select transmit interrupts to enable */
  297. write_scc(CTL+base,R15,TxUIE);     /* allow Underrun int only */
  298. write_scc(CTL+base,R1,TxINT_ENAB|EXT_INT_ENAB);  /* Tx/Extern ints on */
  299. write_scc(CTL+base,R9,MIE|NV);     /* master enable */
  300. /* enable interrupt latch on board */
  301. outportb(hp->dmactrl,INTENABLE);
  302. hp->tstate = ACTIVE; /* char going out now */
  303. restore(i_state);
  304. return;
  305. case ACTIVE:
  306. /* Here we are actively sending a frame */
  307. if((c = PULLCHAR(&hp->sndbuf)) != -1){
  308. outportb(hp->base+DATA,c); /* next char is gone */
  309. /* stuffing a char satisfies Interrupt condition */
  310. } else {
  311. /* No more to send - just stop till underrun int */
  312. hp->tstate = UNDERRUN;
  313. free_p(&hp->sndbuf);
  314. /* now we reset the EOM latch & enable underrun int */
  315. write_scc(CTL+base,R0,RES_EOM_L); /* send CRC at underrun */
  316. write_scc(CTL+hp->base,R0,RES_Tx_P); /* reset Tx Int Pend */
  317. }
  318. restore(i_state);
  319. return;     /* back to wait for interrupt */
  320. case UNDERRUN:
  321. /*
  322.  * This state is handled by an UNDERRUN interrupt, which
  323.  * is an External Status interrupt.  At UNDERRUN, the
  324.  * UNDERRUN/EOM latch in R0 will be 0, so the SCC will send
  325.  * CRC and ending flag.  After the CRC clears the Tx buffer,
  326.  * a TX BUFF EMPTY interrupt will fire.  At that time, we
  327.  * should be in FLAGOUT state, ready to send another frame
  328.  * if one is there to send.
  329.  */
  330. break;
  331. } /* end switch */
  332. restore(i_state);
  333. }
  334. /* SET Transmit or Receive Mode
  335.  * Set RTS (request-to-send) to modem on Transmit
  336.  */
  337. static void
  338. rts(hp,x)
  339. register struct egchan *hp;
  340. uint16 x;
  341. {
  342. uint16 tc;
  343. long br;
  344. /* Reprogram BRG and turn on transmitter to send flags */
  345. if(x == ON) { /* Turn Tx ON and Receive OFF */
  346. write_scc(CTL+hp->base,R3,Rx8); /* Rx off */
  347. waitmsec(50); /* 500 msec delay before on */
  348. hp->rstate = IDLE;
  349. write_scc(CTL+hp->base,R9,0); /* Interrupts off */
  350. br = hp->speed;  /* get desired speed */
  351. tc = (XTAL/br)-2; /* calc 1X BRG divisor */
  352. write_scc(CTL+hp->base,R12,tc&0xFF);      /* lower byte */
  353. write_scc(CTL+hp->base,R13,(tc>>8)&0xFF); /* upper bite */
  354. write_scc(CTL+hp->base,R5,TxCRC_ENAB|RTS|TxENAB|Tx8|DTR);
  355. /* Transmitter now on */
  356. write_scc(CTL+hp->base,R0,RES_Tx_CRC);/* CRC reset */
  357. waitmsec(hp->txdelay);   /* Delay after Tx on */
  358. } else { /* Tx OFF and Rx ON */
  359. hp->tstate = IDLE;
  360. write_scc(CTL+hp->base,R5,Tx8|DTR);  /* TX off now */
  361. write_scc(CTL+hp->base,R0,ERR_RES);  /* reset error bits */
  362. write_scc(CTL+hp->base,R1,(INT_ALL_Rx|EXT_INT_ENAB));
  363. write_scc(CTL+hp->base,R15,BRKIE); /* allow ABORT int */
  364. /* delay for squelch tail before enable of Rx */
  365. waitmsec(hp->squeldelay); /* keep it up  */
  366. /* Reprogram BRG for 32x clock for receive DPLL */
  367. write_scc(CTL+hp->base,R14,BRSRC);      /* BRG off, but keep Pclk source */
  368. br = hp->speed;  /* get desired speed */
  369. tc = ((XTAL/32)/br)-2; /* calc 32X BRG divisor */
  370. write_scc(CTL+hp->base,R12,tc&0xFF); /* lower byte */
  371. write_scc(CTL+hp->base,R13,(tc>>8)&0xFF); /* upper bite */
  372. write_scc(CTL+hp->base,R14,BRSRC|SEARCH); /* SEARCH mode, keep BRG source */
  373. write_scc(CTL+hp->base,R14,BRSRC|BRENABL); /* Enable the BRG */
  374. /* Now, turn on the receiver and hunt for a flag */
  375. write_scc(CTL+hp->base,R3,RxENABLE|RxCRC_ENAB|Rx8);
  376. hp->rstate = ACTIVE; /* Normal state */
  377. }
  378. }
  379. /* Initialize eg controller parameters */
  380. static void
  381. egchanparam(hp)
  382. register struct egchan *hp;
  383. {
  384. uint16 tc;
  385. long br;
  386. register uint16 base;
  387. int i_state;
  388. /* Initialize 8530 channel for SDLC operation */
  389. base = hp->base;
  390. #ifdef notdef
  391. printf("Initializing Channel %c - Base = %xn",base&2?'A':'B',base);
  392. #endif
  393. i_state = dirps();
  394. switch(base & 2){
  395. case 2:
  396. write_scc(CTL+base,R9,CHRA); /* Reset channel A */
  397. break;
  398. case 0:
  399. write_scc(CTL+base,R9,CHRB); /* Reset channel B */
  400. break;
  401. }
  402. /* Deselect all Rx and Tx interrupts */
  403. write_scc(CTL+base,R1,0);
  404. /* Turn off external interrupts (like CTS/CD) */
  405. write_scc(CTL+base,R15,0);
  406. /* X1 clock, SDLC mode */
  407. write_scc(CTL+base,R4,SDLC|X1CLK);        /* SDLC mode and X1 clock */
  408. /* Now some misc Tx/Rx parameters */
  409. /* CRC PRESET 1, NRZI Mode */
  410. write_scc(CTL+base,R10,CRCPS|NRZI);
  411. /* Set up BRG and DPLL multiplexers */
  412. /* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */
  413. write_scc(CTL+base,R11,TCBR|RCDPLL|TRxCDP|TRxCOI);
  414. /* Null out SDLC start address */
  415. write_scc(CTL+base,R6,0);
  416. /* SDLC flag */
  417. write_scc(CTL+base,R7,FLAG);
  418. /* Set up the Transmitter but don't enable it */
  419. /*  DTR, 8 bit TX chars only - TX NOT ENABLED */
  420. write_scc(CTL+base,R5,Tx8|DTR);
  421. /* Receiver - intial setup only - more later */
  422. write_scc(CTL+base,R3,Rx8);         /* 8 bits/char */
  423. /* Setting up BRG now - turn it off first */
  424. write_scc(CTL+hp->base,R14,BRSRC);      /* BRG off, but keep Pclk source */
  425. /* set the 32x time constant for the BRG in Receive mode */
  426. br = hp->speed;  /* get desired speed */
  427. tc = ((XTAL/32)/br)-2; /* calc 32X BRG divisor */
  428. write_scc(CTL+hp->base,R12,tc&0xFF);      /* lower byte */
  429. write_scc(CTL+hp->base,R13,(tc>>8)&0xFF); /* upper bite */
  430. /* Time to set up clock control register for RECEIVE mode
  431.  * Eagle has xtal osc going to pclk at 3.6864 Mhz
  432.  * The BRG is sourced from that, and set to 32x clock
  433.  * The DPLL is sourced from the BRG, and feeds the TRxC pin
  434.  * Transmit clock & Receive clock come from DPLL
  435.  */
  436. /* Following subroutine sets up and ENABLES the receiver */
  437. rts(hp,OFF);    /* TX OFF and RX ON */
  438. write_scc(CTL+hp->base,R14,BRSRC|SSBR);    /* DPLL from BRG, BRG source is PCLK */
  439. write_scc(CTL+hp->base,R14,BRSRC|SEARCH);    /* SEARCH mode, keep BRG source */
  440. write_scc(CTL+hp->base,R14,BRSRC|BRENABL); /* Enable the BRG */
  441. /* enable the receive interrupts */
  442. write_scc(CTL+hp->base,R1,(INT_ALL_Rx|EXT_INT_ENAB));
  443. write_scc(CTL+hp->base,R15,BRKIE);     /* ABORT int */
  444. write_scc(CTL+hp->base,R9,MIE|NV); /* master enable */
  445. /* enable interrupt latch on board */
  446. outportb(hp->dmactrl,INTENABLE);
  447. /* Now, turn on the receiver and hunt for a flag */
  448. write_scc(CTL+hp->base,R3,RxENABLE|RxCRC_ENAB|Rx8);
  449. restore(i_state);
  450. }
  451. /* Attach a EAGLE interface to the system
  452.  * argv[0]: hardware type, must be "eagle"
  453.  * argv[1]: I/O address, e.g., "0x300"
  454.  * argv[2]: vector, e.g., "2"
  455.  * argv[3]: mode, must be:
  456.  *     "ax25" (AX.25 UI frame format)
  457.  * argv[4]: interface label, e.g., "eg0"
  458.  * argv[5]: receiver packet buffer size in bytes
  459.  * argv[6]: maximum transmission unit, bytes
  460.  * argv[7]: interface speed, e.g, "1200"
  461.  * argv[8]: First IP address, optional (defaults to Ip_addr);
  462.  * argv[9]: Second IP address, optional (defaults to Ip_addr);
  463.  */
  464. int
  465. eg_attach(argc,argv,p)
  466. int argc;
  467. char *argv[];
  468. void *p;
  469. {
  470. register struct iface *if_pca,*if_pcb;
  471. struct egchan *hp;
  472. int dev;
  473. char *cp;
  474. /* Quick check to make sure args are good and mycall is set */
  475. if(strcmp(argv[3],"ax25") != 0){
  476. printf("Mode %s unknown for interface %sn",
  477. argv[3],argv[4]);
  478. return -1;
  479. }
  480. if(if_lookup(argv[4]) != NULL){
  481. printf("Interface %s already existsn",argv[4]);
  482. return -1;
  483. }
  484. if(Mycall[0] == ''){
  485. printf("set mycall firstn");
  486. return -1;
  487. }
  488. /* Note: More than one card can be supported if you give up a COM:
  489.  * port, thus freeing up an IRQ line and port address
  490.  */
  491. if(Egnbr >= EGMAX) {
  492. printf("Only 1 EAGLE controller supported right now!n");
  493. return -1;
  494. }
  495. if(setencap(NULL,argv[3]) == -1){
  496. printf("Unknown encapsulation %sn",argv[3]);
  497. return -1;
  498. }
  499. dev = Egnbr++;
  500. /* Initialize hardware-level control structure */
  501. Eagle[dev].addr = htoi(argv[1]);
  502. Eagle[dev].vec = atoi(argv[2]);
  503. if(strchr(argv[2],'c') != NULL)
  504. Eagle[dev].chain = 1;
  505. else
  506. Eagle[dev].chain = 0;
  507. /* Save original interrupt vector */
  508. Eagle[dev].oldvec = getirq(Eagle[dev].vec);
  509. /* Set new interrupt vector */
  510. if(setirq(Eagle[dev].vec,eghandle[dev]) == -1){
  511. printf("IRQ %u out of rangen",Eagle[dev].vec);
  512. Egnbr--;
  513. return -1;
  514. }
  515. /* Create interface structures and fill in details */
  516. if_pca = (struct iface *)callocw(1,sizeof(struct iface));
  517. if_pcb = (struct iface *)callocw(1,sizeof(struct iface));
  518. if_pca->addr = if_pcb->addr = Ip_addr;
  519. if(argc > 8)
  520. if_pca->addr = resolve(argv[8]);
  521. if(argc > 9)
  522. if_pcb->addr = resolve(argv[9]);
  523. if(if_pca->addr == 0 || if_pcb->addr == 0){
  524. printf(Noipaddr);
  525. free(if_pca);
  526. free(if_pcb);
  527. return -1;
  528. }
  529. /* Append "a" to interface associated with A channel */
  530. if_pca->name = mallocw((unsigned)strlen(argv[4])+2);
  531. strcpy(if_pca->name,argv[4]);
  532. strcat(if_pca->name,"a");
  533. /* Append "b" to iface associated with B channel */
  534. if_pcb->name = mallocw((unsigned)strlen(argv[4])+2);
  535. strcpy(if_pcb->name,argv[4]);
  536. strcat(if_pcb->name,"b");
  537. if_pcb->mtu = if_pca->mtu = atoi(argv[6]);
  538. if_pcb->ioctl = if_pca->ioctl = eg_ctl;
  539. if_pca->dev = 2*dev; /* eg0a */
  540. if_pcb->dev = 2*dev + 1; /* eg0b */
  541. if_pcb->stop = if_pca->stop = eg_stop;
  542. if_pcb->raw = if_pca->raw = eg_raw;
  543. /* Must work, was checked at top */
  544. setencap(if_pca,argv[3]);
  545. setencap(if_pcb,argv[3]);
  546. if(if_pcb->hwaddr == NULL)
  547. if_pcb->hwaddr = mallocw(AXALEN);
  548. memcpy(if_pcb->hwaddr,Mycall,AXALEN);
  549. if(if_pca->hwaddr == NULL)
  550. if_pca->hwaddr = mallocw(AXALEN);
  551. memcpy(if_pca->hwaddr,Mycall,AXALEN);
  552. /* Link em in to the interface chain */
  553. if_pca->next = if_pcb;
  554. if_pcb->next = Ifaces;
  555. Ifaces = if_pca;
  556. /* set params in egchan table for CHANNEL B */
  557. hp = &Egchan[2*dev+1]; /* eg1 is offset 1 */
  558. hp->iface = if_pcb;
  559. hp->stata = Eagle[dev].addr + CHANA + CTL; /* permanent status */
  560. hp->statb = Eagle[dev].addr + CHANB + CTL; /* addrs for CHANA/B*/
  561. hp->dmactrl = Eagle[dev].addr + DMACTRL; /* Eagle control reg */
  562. hp->speed = (uint16)atoi(argv[7]);
  563. hp->base = Eagle[dev].addr + CHANB;
  564. hp->bufsiz = atoi(argv[5]);
  565. hp->tstate = IDLE;
  566. /* default KISS Params */
  567. hp->txdelay = 25; /* 250 Ms */
  568. hp->persist = 64; /* 25% persistence */
  569. hp->slotime = 10; /* 100 Ms */
  570. hp->squeldelay = 20; /* 200 Ms */
  571. write_scc(CTL+hp->stata,R9,FHWRES);  /* Hardware reset */
  572. /* one time only */
  573. /* Disable interrupts with Master interrupt ctrl reg */
  574. write_scc(CTL+hp->stata,R9,0);
  575. egchanparam(hp);
  576. /* Pre-allocate a receive buffer */
  577. hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  578. if(hp->rcvbuf == NULL) {
  579.     /* No memory, abort receiver */
  580.     printf("EGATTACH: No memory available for Receive buffersn");
  581.     /* Restore original interrupt vector */
  582.     setirq(Eagle[dev].vec,Eagle[dev].oldvec);
  583.     Egnbr--;
  584.     return(-1);
  585. }
  586. hp->rcp = hp->rcvbuf->data;
  587. hp->rcvbuf->cnt = 0;
  588. hp->sndq = NULL;
  589. /* set params in egchan table for CHANNEL A */
  590. hp = &Egchan[2*dev]; /* eg0a is offset 0 */
  591. hp->iface = if_pca;
  592. hp->speed = (uint16)atoi(argv[7]);
  593. hp->base = Eagle[dev].addr + CHANA;
  594. hp->bufsiz = atoi(argv[5]);
  595. hp->tstate = IDLE;
  596. /* default KISS Params */
  597. hp->txdelay = 25; /* 250 Ms */
  598. hp->persist = 64; /* 25% persistence */
  599. hp->slotime = 10; /* 100 Ms */
  600. hp->squeldelay = 20; /* 200 Ms */
  601. egchanparam(hp);
  602. /* Pre-allocate a receive buffer */
  603. hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  604. if(hp->rcvbuf == NULL) {
  605. /* No memory, abort receiver */
  606. printf("EGATTACH: No memory available for Receive buffersn");
  607. /* Restore original interrupt vector */
  608. setirq(Eagle[dev].vec,Eagle[dev].oldvec);
  609. Egnbr--;
  610. return -1;
  611. }
  612. hp->rcp = hp->rcvbuf->data;
  613. hp->rcvbuf->cnt = 0;
  614. hp->sndq = NULL;
  615. write_scc(CTL+hp->base,R9,MIE|NV); /* master interrupt enable */
  616. /* Enable interrupts on the EAGLE card itself */
  617. outportb(hp->dmactrl,INTENABLE);
  618. /* Enable interrupt */
  619. maskon(Eagle[dev].vec);
  620. cp = if_name(if_pca," tx");
  621. if_pca->txproc = newproc(cp,512,if_tx,0,if_pca,NULL,0);
  622. free(cp);
  623. cp = if_name(if_pcb," tx");
  624. if_pcb->txproc = newproc(cp,512,if_tx,0,if_pcb,NULL,0);
  625. free(cp);
  626. return 0;
  627. }
  628. /* Shut down interface */
  629. static int
  630. eg_stop(iface)
  631. struct iface *iface;
  632. {
  633. int dev;
  634. dev = iface->dev;
  635. if(dev & 1)
  636. return 0;
  637. dev >>= 1; /* Convert back into eagle number */
  638. /* Turn off interrupts */
  639. maskoff(Eagle[dev].vec);
  640. /* Restore original interrupt vector */
  641. setirq(Eagle[dev].vec,Eagle[dev].oldvec);
  642. /* Force hardware reset */
  643. write_scc(CTL+Eagle[dev].addr + CHANA,R9,FHWRES);
  644. /* resets interrupt enable on eagle card itself */
  645. outportb(Eagle[dev].addr+DMACTRL,0);
  646. return 0;
  647. }
  648. /* Send raw packet on eagle card */
  649. static int
  650. eg_raw(
  651. struct iface *iface,
  652. struct mbuf **bpp
  653. ){
  654. char kickflag;
  655. struct egchan *hp;
  656. dump(iface,IF_TRACE_OUT,*bpp);
  657. iface->rawsndcnt++;
  658. iface->lastsent = secclock();
  659. hp = &Egchan[iface->dev];
  660. kickflag = (hp->sndq == NULL) & (hp->sndbuf == NULL); /* clever! flag=1 if something in queue */
  661. enqueue(&hp->sndq,bpp);
  662. if(kickflag) /* simulate interrupt to xmit */
  663. egtxint(hp); /* process interrupt */
  664. return 0;
  665. }
  666. /* routine to delay n increments of 10 milliseconds
  667.  * about right on a turbo XT - will be slow on 4.77
  668.  * Still looking for a way to use the 8253 timer...
  669.  */
  670. static void
  671. waitmsec(n)
  672. int n;
  673. {
  674. long i;
  675. for(i=0L; i < (200L*n); i++)
  676. ;  /* simple loop delay */
  677. }
  678. /* display EAGLE Channel stats */
  679. int
  680. doegstat(argc,argv,p)
  681. int argc;
  682. char *argv[];
  683. void *p;
  684. {
  685. struct egchan *hp0, *hp1;
  686. int i;
  687. for(i=0; i<EGMAX; i++) {
  688. hp0 = &Egchan[i];
  689. hp1 = &Egchan[i+1];
  690. printf("EAGLE Board Statistics:nn");
  691. printf("Base AddrtRxintstTxintstExintstEnquedtCrcerrtAbortstRxOverstRFramesn");
  692. printf("---------t------t------t------t------t------t------t-------t-------n");
  693. printf("0x%xtt%ldt%ldt%ldt%dt%dt%dt%dt%dnRcv State=%sn", hp0->base, hp0->rxints,
  694.     hp0->txints, hp0->exints, hp0->enqueued, hp0->crcerr, hp0->aborts,
  695.     hp0->rovers,hp0->rxframes,
  696.     hp0->rstate==0?"IDLE":hp0->rstate==1?"ACTIVE":hp0->rstate==2?"RXERROR":hp0->rstate==3?"RXABORT":"TOOBIG");
  697. printf("0x%xtt%ldt%ldt%ldt%dt%dt%dt%dt%dnRcv State=%snn", hp1->base, hp1->rxints,
  698.     hp1->txints, hp1->exints, hp1->enqueued, hp1->crcerr, hp1->aborts,
  699.     hp1->rovers,hp1->rxframes,
  700.     hp1->rstate==0?"IDLE":hp1->rstate==1?"ACTIVE":hp1->rstate==2?"RXERROR":hp1->rstate==3?"RXABORT":"TOOBIG");
  701. }
  702. return 0;
  703. }
  704. /* Subroutine to set kiss params in channel tables */
  705. static int32
  706. eg_ctl(iface,cmd,set,val)
  707. struct iface *iface;
  708. int cmd;
  709. int set;
  710. int32 val;
  711. {
  712. struct egchan *hp;
  713. hp = &Egchan[iface->dev];     /* point to channel table */
  714. switch(cmd){
  715. case PARAM_TXDELAY:
  716. if(set)
  717. hp->txdelay = val;
  718. return hp->txdelay;
  719. case PARAM_PERSIST:
  720. if(set)
  721. hp->persist = val;
  722. return hp->persist;
  723. case PARAM_SLOTTIME:
  724. if(set)
  725. hp->slotime = val;
  726. return hp->slotime;
  727. case PARAM_TXTAIL:
  728. if(set)
  729. hp->squeldelay = val;
  730. return hp->squeldelay;
  731. }
  732. return -1;
  733. }