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

TCP/IP协议栈

开发平台:

Visual C++

  1. /*
  2.  * Version with Stopwatches
  3.  *
  4.  * 0 - Not used
  5.  * 1 - rx_fsm run time
  6.  * 2 - drtx_active run time (per character tx time)
  7.  * 
  8.  * Interface driver for the DRSI board for KA9Q's TCP/IP on an IBM-PC ONLY!
  9.  *
  10.  * Derived from a driver written by Art Goldman, WA3CVG
  11.  * (c) Copyright 1987 All Rights Reserved
  12.  * Permission for non-commercial use is hereby granted provided this notice
  13.  * is retained.  For info call: (301) 997-3838.
  14.  *
  15.  * Heavily re-written from the original,  a driver for the EAGLE board into
  16.  * a driver for the DRSI PC* Packet adpator. Copyright as original, all
  17.  * amendments likewise providing credit given and notice retained.
  18.  * Stu Phillips - N6TTO, W6/G8HQA (yes Virginia,  really !).
  19.  * For info call: (408) 285-4142
  20.  *
  21.  * This driver supports 1 (one) DRSI board.
  22.  * 
  23.  * Reformatted and added ANSI-style declarations, integrated into NOS
  24.  * by KA9Q, 10/14/89
  25.  *
  26.  * Latest set of defect fixes added 1/2/90 by N6TTO
  27.  * 1. Made P-PERSIST work properly
  28.  * 2. Fixed UNDERRUN bug when in DEFER state
  29.  * 3. Tx now defers correctly when DCD is high (!)
  30.  *
  31.  * Changed 3/4/90 by N6TTO
  32.  * Changed method of enabling the IRQ to the 8259 to call maskon()
  33.  * instead of clrbit(); change made to allow interrupts > 8 to work
  34.  * on an AT.
  35.  *
  36.  * Changed 11/14/90 by N6TTO
  37.  * Fixed incompatiblity between current NOS memory allocation scheme
  38.  * and changes made to speed up drsi transmit state machine.
  39.  *
  40.  */
  41. #include <stdio.h>
  42. #include <dos.h>
  43. #include <time.h>
  44. #include "global.h"
  45. #include "mbuf.h"
  46. #include "iface.h"
  47. #include "pktdrvr.h"
  48. #include "netuser.h"
  49. #include "drsi.h"
  50. #include "ax25.h"
  51. #include "trace.h"
  52. #include "nospc.h"
  53. #include "z8530.h"
  54. #include "devparam.h"
  55. static int32 dr_ctl(struct iface *iface,int cmd,int set,int32 val);
  56. static int dr_raw(struct iface *iface,struct mbuf **bpp);
  57. static int dr_stop(struct iface *iface);
  58. static void dr_wake(struct drchan *hp,int rx_or_tx,
  59. void (*routine)(struct drchan *),int ticks);
  60. static int drchanparam(struct drchan *hp);
  61. static void drexint(struct drchan *hp);
  62. static void drinitctc(unsigned port);
  63. static void drrx_active(struct drchan *hp);
  64. static void drrx_enable(struct drchan *hp);
  65. static void drtx_active(struct drchan *hp);
  66. static void drtx_defer(struct drchan *hp);
  67. static void drtx_downtx(struct drchan *hp);
  68. static void drtx_flagout(struct drchan *hp);
  69. static void drtx_idle(struct drchan *hp);
  70. static void drtx_rrts(struct drchan *hp);
  71. static void drtx_tfirst(struct drchan *hp);
  72. static char read_ctc(unsigned port,unsigned reg);
  73. static void rx_fsm(struct drchan *hp);
  74. static void tx_fsm(struct drchan *hp);
  75. static void write_ctc(uint16 port,uint8 reg,uint8 val);
  76. struct DRTAB Drsi[DRMAX]; /* Device table - one entry per card */
  77. INTERRUPT (*Drhandle[])(void) = { dr0vec };  /* handler interrupt vector table */
  78. struct drchan Drchan[2*DRMAX];  /* channel table - 2 entries per card */
  79. uint16 Drnbr;
  80. /* Set specified routine to be 'woken' up after specified number
  81.  * of ticks (allows CPU to be freed up and reminders posted);
  82.  */
  83. static void
  84. dr_wake(hp, rx_or_tx, routine, ticks)
  85. struct drchan *hp;
  86. int rx_or_tx;
  87. void (*routine)(struct drchan *);
  88. int ticks;
  89. {
  90. hp->w[rx_or_tx].wcall = routine;
  91. hp->w[rx_or_tx].wakecnt = ticks;
  92. }
  93. /* Master interrupt handler.  One interrupt at a time is handled.
  94.  * here. Service routines are called from here.
  95.  */
  96. INTERRUPT (far *(drint)(dev))()
  97. int dev;
  98. {
  99. register char st;
  100. register uint16 pcbase, i;
  101. struct drchan *hpa,*hpb;
  102. struct DRTAB *dp;
  103. dp = &Drsi[dev];
  104. dp->ints++;
  105. pcbase = dp->addr;
  106. hpa = &Drchan[2 * dev];
  107. hpb = &Drchan[(2 * dev)+1];
  108. yuk:
  109. /* Check CTC for timer interrupt */
  110. st = read_ctc(pcbase, Z8536_CSR3);
  111. if(st & Z_IP){
  112. /* Reset interrupt pending */
  113. write_ctc(pcbase, Z8536_CSR3, Z_CIP|Z_GCB);
  114. for(i=0;i<=1;i++){
  115. if(hpa->w[i].wakecnt){
  116. if(--hpa->w[i].wakecnt == 0){
  117. (hpa->w[i].wcall)(hpa);
  118. }
  119. }
  120. if(hpb->w[i].wakecnt){
  121. if(--hpb->w[i].wakecnt == 0){
  122. (hpb->w[i].wcall)(hpb);
  123. }
  124. }
  125. }
  126. }
  127. /* Check the SIO for interrupts */
  128. /* Read interrupt status register from channel A */
  129. while((st = read_scc(pcbase+CHANA+CTL,R3)) != 0){
  130. /* Use IFs to process ALL interrupts pending
  131.  * because we need to check all interrupt conditions
  132.  */
  133. if(st & CHARxIP){
  134. /* Channel A Rcv Interrupt Pending */
  135. rx_fsm(hpa);
  136. }
  137. if(st & CHBRxIP){
  138. /* Channel B Rcv Interrupt Pending */
  139. rx_fsm(hpb);
  140. }
  141. if(st & CHATxIP){
  142. /* Channel A Transmit Int Pending */
  143. tx_fsm(hpa);
  144. }
  145. if(st & CHBTxIP){
  146. /* Channel B Transmit Int Pending */
  147. tx_fsm(hpb);
  148. }
  149. if(st & CHAEXT){
  150. /* Channel A External Status Int */
  151. drexint(hpa);
  152. }
  153. if(st & CHBEXT){
  154. /* Channel B External Status Int */
  155. drexint(hpb);
  156. }
  157. /* Reset highest interrupt under service */
  158. write_scc(hpa->base+CTL,R0,RES_H_IUS);
  159. } /* End of while loop on int processing */
  160. if(read_ctc(pcbase, Z8536_CSR3) & Z_IP)
  161. goto yuk;
  162. return dp->chain ? dp->oldvec : NULL;
  163. }
  164. /* DRSI SIO External/Status interrupts
  165.  * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
  166.  * Receiver automatically goes to Hunt on an abort.
  167.  *
  168.  * If the Tx Underrun interrupt hits, change state and
  169.  * issue a reset command for it, and return.
  170.  */
  171. static void
  172. drexint(hp)
  173. register struct drchan *hp;
  174. {
  175. register int base = hp->base;
  176. char st;
  177. int i_state;
  178. i_state = dirps();
  179. hp->exints++;
  180. st = read_scc(base+CTL,R0);     /* Fetch status */
  181. /* Check for Tx UNDERRUN/EOM - only in Transmit Mode */
  182.         /* Note that the TxEOM bit remains set once we go    */
  183. /* back to receive.  The following qualifications    */
  184. /* are necessary to prevent an aborted frame causing */
  185. /* a queued transmit frame to be tossed when in      */
  186. /* DEFER state on transmit.      */
  187. if((hp->tstate != DEFER) && (hp->rstate==0) && (st & TxEOM)){
  188. if(hp->tstate != UNDERRUN){
  189. /* This is an unexpected underrun.  Discard the current
  190.  * frame (there's no way to rewind),  kill the transmitter
  191.  * and return to receive with a wakeup posted to get the
  192.  * next (if any) frame.  Any recovery will have to be done
  193.  * by higher level protocols (yuk).
  194.  */
  195. write_scc(base, R5, Tx8|DTR); /* Tx off now */
  196. write_scc(base, R1, 0); /* Prevent ext.status int */
  197. write_scc(base, R0, RES_Tx_P);  /* Reset Tx int pending */
  198. write_scc(base, R0, ERR_RES);
  199. write_scc(base, R0, RES_EOM_L); /* Reset underrun latch */
  200. free_p(&hp->sndbuf);
  201. hp->tstate = IDLE;
  202. hp->tx_state = drtx_idle;
  203. dr_wake(hp, TX, tx_fsm, hp->slotime);
  204. hp->rstate = ENABLE;
  205. hp->rx_state = drrx_enable;
  206. drrx_enable(hp);
  207. }
  208. }
  209. /* Receive Mode only
  210.  * This triggers when hunt mode is entered, & since an ABORT
  211.  * automatically enters hunt mode, we use that to clean up
  212.  * any waiting garbage
  213.  */
  214. if((hp->rstate != IDLE) && (st & BRK_ABRT)){
  215. if(hp->rcvbuf != NULL){
  216. hp->rcp = hp->rcvbuf->data;
  217. hp->rcvbuf->cnt = 0;
  218. }
  219. while(read_scc(base,R0) & Rx_CH_AV)
  220. (void) inportb(base+DATA);
  221. hp->aborts++;
  222. hp->rstate = ACTIVE;
  223. write_scc(base, R0, ERR_RES);
  224. }
  225. /* reset external status latch */
  226. write_scc(base,R0,RES_EXT_INT);
  227. restore(i_state);
  228. }
  229. /* Receive Finite State Machine - dispatcher */
  230. static void
  231. rx_fsm(hp)
  232. struct drchan *hp;
  233. {
  234. int i_state;
  235. i_state = dirps();
  236. hp->rxints++;
  237. (*hp->rx_state)(hp);
  238. restore(i_state);
  239. }
  240. /* drrx_enable
  241.  * Receive ENABLE state processor
  242.  */
  243. static void
  244. drrx_enable(hp)
  245. struct drchan *hp;
  246. {
  247. register uint16 base = hp->base;
  248. write_scc(base, R1, INT_ALL_Rx|EXT_INT_ENAB);
  249. write_scc(base, R15, BRKIE); /* Allow ABORT Int */
  250. write_scc(base, R14, BRSRC|BRENABL|SEARCH);
  251. /* Turn on rx and enter hunt mode */
  252. write_scc(base, R3, ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
  253. if(hp->rcvbuf != NULL){
  254. hp->rcvbuf->cnt = 0;
  255. hp->rcp = hp->rcvbuf->data;
  256. }
  257. hp->rstate = ACTIVE;
  258. hp->rx_state = drrx_active;
  259. }
  260. /* drrx_active
  261.  * Receive ACTIVE state processor
  262.  */
  263. static void
  264. drrx_active(hp)
  265. struct drchan *hp;
  266. {
  267. register uint16 base = hp->base;
  268. unsigned char rse,st;
  269. struct mbuf *bp;
  270. /* Allocate a receive buffer if not already present */
  271. if(hp->rcvbuf == NULL){
  272. bp = hp->rcvbuf = alloc_mbuf(hp->bufsiz);
  273. if(bp == NULL){
  274. /* No buffer - abort the receiver */
  275. write_scc(base, R3, ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
  276. /* Clear character from rx buffer in SIO */
  277. (void) inportb(base+DATA);
  278. return;
  279. }
  280. hp->rcvbuf->cnt = 0; 
  281. hp->rcp = hp->rcvbuf->data;
  282. }
  283. st = read_scc(base, R0); /* get interrupt status from R0 */
  284. rse = read_scc(base,R1); /* get special status from R1 */
  285. if(st & Rx_CH_AV){
  286. /* there is a char to be stored
  287.  * read special condition bits before reading the data char
  288.  * (already read above)
  289.  */
  290. if(rse & Rx_OVR){
  291. /* Rx overrun - toss buffer */
  292. hp->rcp = hp->rcvbuf->data; /* reset buffer pointers */
  293. hp->rcvbuf->cnt = 0;
  294. hp->rstate = RXERROR; /* set error flag */
  295. hp->rovers++; /* count overruns */
  296. } else if(hp->rcvbuf->cnt >= hp->bufsiz){
  297. /* Too large -- toss buffer */
  298. hp->toobig++;
  299. hp->rcp = hp->rcvbuf->data; /* reset buffer pointers */
  300. hp->rcvbuf->cnt = 0;
  301. hp->rstate = TOOBIG; /* when set, chars are not stored */
  302. }
  303. /* ok, we can store the received character now */
  304. if((hp->rstate == ACTIVE) && ((st & BRK_ABRT) == 0)){
  305. *hp->rcp++ = inportb(base+DATA); /* char to rcv buff */
  306. hp->rcvbuf->cnt++;  /* bump count */
  307. } else {
  308. /* got to empty FIFO */
  309. (void) inportb(base+DATA);
  310. hp->rcp = hp->rcvbuf->data; /* reset buffer pointers */
  311. hp->rcvbuf->cnt = 0;
  312. hp->rstate = RXABORT;
  313. write_scc(base,R0,ERR_RES); /* reset err latch */
  314. }
  315. }
  316. /* The End of Frame bit is ALWAYS associated with a character,
  317.  * usually, it is the last CRC char.  Only when EOF is true can
  318.  * we look at the CRC byte to see if we have a valid frame
  319.  */
  320. if(rse & END_FR){
  321. hp->rxframes++;
  322. /* END OF FRAME -- Make sure Rx was active */
  323. if(hp->rcvbuf->cnt > 0){ /* any data to store */
  324. /* looks like a frame was received
  325.  * now is the only time we can check for CRC error
  326.  */
  327. if((rse & CRC_ERR) || (hp->rstate > ACTIVE) ||
  328.  (hp->rcvbuf->cnt < 10) || (st & BRK_ABRT)){
  329. /* error occurred; toss frame */
  330. if(rse & CRC_ERR)
  331. hp->crcerr++; /* count CRC errs */
  332. hp->rcp = hp->rcvbuf->data;
  333. hp->rcvbuf->cnt = 0;
  334. hp->rstate = ACTIVE;   /* Clear error state */
  335. } else {
  336. /* Here we have a valid frame */
  337. hp->rcvbuf->cnt -= 2;    /* chuck FCS bytes */
  338.     /* queue it in */
  339. net_route(hp->iface,&hp->rcvbuf);
  340. hp->enqueued++;
  341. /* packet queued - reset buffer pointer */
  342. hp->rcvbuf = NULL;
  343. } /* end good frame queued */
  344. }  /* end check for active receive upon EOF */
  345. }
  346. }
  347. /*
  348.  * TX finite state machine - dispatcher
  349.  */
  350. static void
  351. tx_fsm(hp)
  352. struct drchan *hp;
  353. {
  354. int i_state;
  355. i_state = dirps();
  356. if(hp->tstate != DEFER && hp->tstate)
  357. hp->txints++;
  358. (*hp->tx_state)(hp);
  359. restore(i_state);
  360. }
  361. /* drtx_idle
  362.  * Transmit IDLE transmit state processor
  363.  */
  364. static void
  365. drtx_idle(hp)
  366. struct drchan *hp;
  367. {
  368. register uint16 base;
  369. /* Tx idle - is there a frame to transmit ? */
  370. if((hp->sndbuf = dequeue(&hp->sndq)) == NULL){
  371. /* Nothing to send - return to receive mode
  372.  * Turn Tx off - any trailing flag should have been sent
  373.  * by now
  374.  */
  375. #ifdef DRSIDEBUG
  376. printf("Nothing to TXn");
  377. #endif
  378. base = hp->base;
  379. write_scc(base, R5, Tx8|DTR);   /* Tx off now */
  380. write_scc(base, R0, ERR_RES); /* Reset error bits */
  381. /* Delay for squelch tail before enabling receiver */
  382. hp->rstate = ENABLE;
  383. hp->rx_state = drrx_enable;
  384. dr_wake(hp, RX, rx_fsm, hp->squeldelay);
  385. } else {
  386. /* Frame to transmit */
  387. hp->tstate = DEFER;
  388. hp->tx_state = drtx_defer;
  389. drtx_defer(hp);
  390. }
  391. }
  392. /* drtx_defer
  393.  * Transmit DEFER state processor
  394.  */
  395. static void
  396. drtx_defer(hp)
  397. struct drchan *hp;
  398. {
  399. register uint16 base = hp->base;
  400. /* We may have defered a previous tx attempt - in any event...
  401.  * Check DCD in case someone is already transmitting
  402.  * then check to see if we should defer due to P-PERSIST.
  403.  */
  404. #ifdef DRSIDEBUG
  405. printf("drtx_defer - checking for DCDn");
  406. #endif
  407. if((read_scc(base+CTL, R0) & DCD) > 0){
  408. /* Carrier detected - defer */
  409. hp->txdefers++;
  410. dr_wake(hp, TX, tx_fsm, 10); /* Defer for 100 mS */
  411. #ifdef DRSIDEBUG
  412. printf("drtx_defer - TX deferredn");
  413. #endif
  414. return;
  415. }
  416. #ifdef DRSIDEBUG
  417. printf("drtx_defer - checking for P-PERSIST backoffn");
  418. #endif
  419. /* P-PERSIST is checked against channel 3 of the 8536 which is
  420.  * the free running counter for the 10 mS tick; The counter
  421.  * goes through 0x6000 ticks per 10 mS or one tick every
  422.  * 407 nS - this is pretty random compared to the DOS time of
  423.  * day clock (0x40:0x6C) used by the other (EAGLE) drivers.
  424.  */
  425.         if (hp->persist <= read_ctc(base,Z8536_CC3LSB)) {
  426. #ifdef DRSIDEBUG
  427.     printf("drtx_defer - BACKOFFn");
  428. #endif
  429.     hp->txppersist++;
  430.     dr_wake (hp, TX, tx_fsm, hp->slotime);
  431.     return;
  432. }
  433. /* No backoff - set RTS and start to transmit frame */
  434. write_scc(base, R1, 0); /* Prevent external status int */
  435. write_scc(base, R3, Rx8); /* Turn Rx off */
  436. hp->rstate = IDLE; /* Mark Rx as idle */
  437. hp->tstate = RRTS;
  438. hp->tx_state = drtx_rrts;
  439. #ifdef DRSIDEBUG
  440. printf("drtx_defer - wake posted for drtx_rrtsn");
  441. #endif
  442. write_scc(base, R9, 0); /* Interrupts off */
  443. write_scc(base,R5,RTS|Tx8|DTR); /* Turn tx on */
  444. dr_wake(hp, TX, tx_fsm, 10);
  445. }
  446. /* drtx_rrts
  447.  * Transmit RRTS state processor
  448.  */
  449. static void
  450. drtx_rrts(hp)
  451. struct drchan *hp;
  452. {
  453. register uint16 base = hp->base;
  454. write_scc(base, R9, 0); /* Interrupts off */
  455. write_scc(base,R5,TxCRC_ENAB|RTS|TxENAB|Tx8|DTR); /* Tx now on */
  456. hp->tstate = TFIRST;
  457. hp->tx_state = drtx_tfirst;
  458. #ifdef DRSIDEBUG
  459. printf("8530 Int status %xn", read_scc(base+CHANA,R3)); 
  460. printf("drtx_rrts - Wake posted for TXDELAYn");
  461. #endif
  462. dr_wake(hp, TX, tx_fsm, hp->txdelay);
  463. }
  464.     
  465. /* drtx_tfirst
  466.  * Transmit TFIRST state processor
  467.  */
  468. static void
  469. drtx_tfirst(hp)
  470. struct drchan *hp;
  471. {
  472. register uint16 base = hp->base;
  473. char c;
  474. /* Copy data to a local buffer to save on mbuf overheads
  475.  * during transmit interrupt time.
  476.  */
  477. hp->drtx_cnt = len_p(hp->sndbuf);
  478. hp->drtx_tcp = hp->drtx_buffer;
  479. pullup(&hp->sndbuf, hp->drtx_tcp, hp->drtx_cnt);
  480. /* Transmit the first character in the buffer */
  481. c = *hp->drtx_tcp++;
  482. hp->drtx_cnt--;
  483. write_scc(base, R0, RES_Tx_CRC); /* Reset CRC */
  484. write_scc(base, R0, RES_EOM_L); /* Reset underrun latch */
  485. outportb(base+DATA, c); /* Output first character */
  486. write_scc(base, R15, TxUIE); /* Allow underrun ints only */
  487. write_scc(base, R1, TxINT_ENAB|EXT_INT_ENAB); /* Tx/Ext status ints on */
  488. write_scc(base, R9, MIE|NV); /* master enable */
  489. hp->tstate = ACTIVE;
  490. hp->tx_state = drtx_active;
  491. }
  492. /* drtx_active
  493.  * Transmit ACTIVE state processor
  494.  */
  495. static void
  496. drtx_active(hp)
  497. struct drchan *hp;
  498. {
  499. if(hp->drtx_cnt-- > 0){
  500. /* Send next character */
  501. outportb(hp->base+DATA, *hp->drtx_tcp++);
  502. } else {
  503. /* No more to send - wait for underrun to hit */
  504. hp->tstate = UNDERRUN;
  505. hp->tx_state = drtx_flagout;
  506. free_p(&hp->sndbuf);
  507. write_scc(hp->base, R0, RES_EOM_L);  /* Send CRC on underrun */
  508. write_scc(hp->base, R0, RES_Tx_P);   /* Reset Tx Int pending */
  509. }
  510. }
  511. /* drtx_flagout
  512.  * Transmit FLAGOUT state processor
  513.  */
  514. static void
  515. drtx_flagout(hp)
  516. struct drchan *hp;
  517. {
  518. /* Arrive here after CRC sent and Tx interrupt fires.
  519.  * Post a wake for ENDDELAY
  520.  */
  521. hp->tstate = UNDERRUN;
  522. hp->tx_state = drtx_downtx;
  523. write_scc(hp->base, R9, 0);
  524. write_scc(hp->base, R0,  RES_Tx_P);
  525. dr_wake(hp, TX, tx_fsm, hp->enddelay);
  526. }
  527. /* drtx_downtx
  528.  * Transmit DOWNTX state processor
  529.  */
  530. static void
  531. drtx_downtx(hp)
  532. struct drchan *hp;
  533. {
  534. register int base = hp->base;
  535. /* See if theres anything left to send - if there is,  send it ! */
  536. if((hp->sndbuf = dequeue(&hp->sndq)) == NULL){
  537. /* Nothing left to send - return to receive */
  538. write_scc(base, R5, Tx8|DTR);   /* Tx off now */
  539. write_scc(base, R0, ERR_RES);   /* Reset error bits */
  540. hp->tstate = IDLE;
  541. hp->tx_state = drtx_idle;
  542. hp->rstate = ENABLE;
  543. hp->rx_state = drrx_enable;
  544. drrx_enable(hp);
  545. } else
  546. drtx_tfirst(hp);
  547. }
  548.     
  549. /* Write CTC register */
  550. static void
  551. write_ctc(base, reg, val)
  552. uint16 base;
  553. uint8 reg,val;
  554. {
  555. int i_state;
  556. i_state = dirps();
  557. /* Select register */
  558. outportb(base+Z8536_MASTER,reg);
  559. outportb(base+Z8536_MASTER,val);
  560. restore(i_state);
  561. }
  562. /* Read CTC register */
  563. static char
  564. read_ctc(base, reg)
  565. uint16 base;
  566. uint8 reg;
  567. {
  568. uint8 c;
  569. uint16 i;
  570. int i_state;
  571. i_state = dirps();
  572. /* Select register */
  573.         outportb(base+Z8536_MASTER,reg);
  574. /* Delay for a short time to allow 8536 to settle */
  575. for(i=0;i<100;i++)
  576. ;
  577. c = inportb(base+Z8536_MASTER);
  578. restore(i_state);
  579. return(c);
  580. }
  581. /* Initialize dr controller parameters */
  582. static int
  583. drchanparam(hp)
  584. register struct drchan *hp;
  585. {
  586. uint16 tc;
  587. long br;
  588. register uint16 base;
  589. int i_state;
  590. /* Initialize 8530 channel for SDLC operation */
  591. base = hp->base;
  592. i_state = dirps();
  593. switch(base & 2){
  594. case 2:
  595. write_scc(base,R9,CHRA); /* Reset channel A */
  596. break;
  597. case 0:
  598. write_scc(base,R9,CHRB); /* Reset channel B */
  599. break;
  600. }
  601. /* Deselect all Rx and Tx interrupts */
  602. write_scc(base,R1,0);
  603. /* Turn off external interrupts (like CTS/CD) */
  604. write_scc(base,R15,0);
  605. /* X1 clock, SDLC mode */
  606. write_scc(base,R4,SDLC|X1CLK);  /* SDLC mode and X1 clock */
  607. /* Now some misc Tx/Rx parameters */
  608. /* CRC PRESET 1, NRZI Mode */
  609. write_scc(base,R10,CRCPS|NRZI);
  610. /* Set up BRG and DPLL multiplexers */
  611. /* Tx Clk from RTxC. Rcv Clk from DPLL, TRxC pin outputs BRG */
  612. write_scc(base,R11,RCDPLL|TCRTxCP|TRxCOI|TRxCBR);
  613. /* Null out SDLC start address */
  614. write_scc(base,R6,0);
  615. /* SDLC flag */
  616. write_scc(base,R7,FLAG);
  617. /* Set up the Transmitter but don't enable it */
  618. /*  DTR, 8 bit TX chars only - TX NOT ENABLED */
  619. write_scc(base,R5,Tx8|DTR);
  620. /* Receiver - initial setup only - more later */
  621. write_scc(base,R3,Rx8);  /* 8 bits/char */
  622. /* Setting up BRG now - turn it off first */
  623. write_scc(base,R14,BRSRC);     /* BRG off, but keep Pclk source */
  624. /* set the 32x time constant for the BRG */
  625. br = hp->speed; /* get desired speed */
  626. tc = ((XTAL/32)/br)-2; /* calc 32X BRG divisor */
  627. write_scc(base,R12,tc);      /* lower byte */
  628. write_scc(base,R13,(tc>>8)); /* upper bite */
  629. /* Time to set up clock control register for RECEIVE mode
  630.  * DRSI has xtal osc going to pclk at 4.9152 Mhz
  631.  * The BRG is sourced from that, and set to 32x clock
  632.  * The DPLL is sourced from the BRG.  BRG is fed to the TRxC pin
  633.  * Transmit clock is provided by the BRG externally divided by
  634.  * 32 in the CTC counter 1 and 2.
  635.  * Receive clock is from the DPLL
  636.  */
  637. /* Following subroutine sets up and ENABLES the receiver */
  638. drrx_enable(hp);
  639. /* DPLL from BRG, BRG source is PCLK */
  640. write_scc(hp->base,R14,BRSRC|SSBR);
  641. /* SEARCH mode, keep BRG source */
  642. write_scc(hp->base,R14,BRSRC|SEARCH);
  643. /* Enable the BRG */
  644. write_scc(hp->base,R14,BRSRC|BRENABL);
  645. /* enable the receive interrupts */
  646. write_scc(hp->base,R1,(INT_ALL_Rx|EXT_INT_ENAB));
  647. write_scc(hp->base,R15,BRKIE); /* ABORT int */
  648. write_scc(hp->base,R9,MIE|NV); /* master enable */
  649. /* Now, turn on the receiver and hunt for a flag */
  650. write_scc(hp->base,R3,RxENABLE|RxCRC_ENAB|Rx8);
  651. restore(i_state);
  652. return 0;
  653. }
  654. /*
  655.  * Initialize the CTC (8536)
  656.  * Only the counter/timers are used - the IO ports are un-comitted.
  657.  * Channels 1 and 2 are linked to provide a /32 counter to convert
  658.  * the SIO BRG to a real clock for Transmit clocking.
  659.  * CTC 3 is left free running on a 10 mS period.  It is always polled
  660.  * and therefore all interrupts from the chip are disabled.
  661.  *
  662.  * Updated 02/16/89 by N6TTO
  663.  * Changed to support the use of the second channel on the 8530.
  664.  * Added so that the driver works on the DRSI type 2 PC Adaptor
  665.  * which has 2 1200 bps modems.
  666.  *
  667.  */
  668. static void
  669. drinitctc(port)
  670. unsigned port;
  671. {
  672. long i;
  673. /* Initialize 8536 CTC */
  674. /* Initialize 8536 */
  675. /* Start by forcing chip into known state */
  676. (void) read_ctc(port, Z8536_MICR);
  677. write_ctc(port, Z8536_MICR, 0x01); /* Reset the CTC */
  678. for(i=0;i < 1000L; i++) /* Loop to delay */
  679. ;
  680. write_ctc(port, Z8536_MICR, 0x00); /* Clear reset and start init seq. */
  681. /* Wait for chip to come ready */
  682. while((read_ctc(port, Z8536_MICR)) != 0x02)
  683. ;
  684. write_ctc(port, Z8536_MICR, 0xa6); /* MIE|NV|CT_VIS|RJA */
  685. write_ctc(port, Z8536_MCCR, 0xf4); /* PBE|CT1E|CT2E|CT3E|PAE */
  686. write_ctc(port, Z8536_CTMS1, 0xe2); /* Continuous,EOE,ECE, Pulse output */
  687. write_ctc(port, Z8536_CTMS2, 0xe2); /* Continuous,EOE,ECE, Pulse output */
  688. write_ctc(port, Z8536_CTMS3, 0x80); /* Continuous,Pulse output */
  689. write_ctc(port, Z8536_CT1MSB, 0x00); /* Load time constant CTC #1 */
  690. write_ctc(port, Z8536_CT1LSB, 0x10);
  691. write_ctc(port, Z8536_CT2MSB, 0x00); /* Load time constant CTC #2 */
  692. write_ctc(port, Z8536_CT2LSB, 0x10);
  693. write_ctc(port, Z8536_CT3MSB, 0x60); /* Load time constant CTC #3 */
  694. write_ctc(port, Z8536_CT3LSB, 0x00);
  695. write_ctc(port, Z8536_IVR, 0x06);
  696. /* Set port direction bits in port A and B
  697.  * Data is input on bits d1 and d5, output on d0 and d4.
  698.  * The direction is set by 1 for input and 0 for output
  699.  */
  700. write_ctc(port, Z8536_PDCA, 0x22);
  701. write_ctc(port, Z8536_PDCB, 0x22);
  702. write_ctc(port, Z8536_CSR1, Z_GCB|Z_TCB);  /* Start CTC #1 running */
  703. write_ctc(port, Z8536_CSR2, Z_GCB|Z_TCB);  /* Start CTC #2 running */
  704. write_ctc(port, Z8536_CSR3, Z_IE|Z_GCB|Z_TCB); /* Start CTC #3 running */
  705. }
  706. /* Attach a DRSI interface to the system
  707.  * argv[0]: hardware type, must be "drsi"
  708.  * argv[1]: I/O address, e.g., "0x300"
  709.  * argv[2]: vector, e.g., "2"
  710.  * argv[3]: mode, must be "ax25"
  711.  * argv[4]: iface label, e.g., "dr0"
  712.  * argv[5]: receiver packet buffer size in bytes
  713.  * argv[6]: maximum transmission unit, bytes
  714.  * argv[7]: iface speed for channel A
  715.  * argv[8]: iface speed for channel B (defaults to same as A if absent)
  716.  * argv[9]: First IP address, optional (defaults to Ip_addr)
  717.  * argv[10]: Second IP address, optional (defaults to Ip_addr)
  718.  */
  719. int
  720. dr_attach(argc,argv)
  721. int argc;
  722. char *argv[];
  723. {
  724. register struct iface *if_pca,*if_pcb;
  725. struct drchan *hp;
  726. int dev;
  727. char *cp;
  728. /* Quick check to make sure args are good and mycall is set */
  729. if(setencap(NULL,argv[3]) == -1){
  730. printf("Mode %s unknown for interface %sn",
  731. argv[3],argv[4]);
  732. return -1;
  733. }
  734. if(if_lookup(argv[4]) != NULL){
  735. printf("Interface %s already existsn", argv[4]);
  736. return -1;
  737. }
  738. if(Mycall[0] == ''){
  739. printf("set mycall firstn");
  740. return -1;
  741. }
  742. /* Note: More than one card can be supported if you give up a COM:
  743.  * port, thus freeing up an IRQ line and port address
  744.  */
  745. if(Drnbr >= DRMAX){
  746. printf("Only %d DRSI controller(s) supported right now!n",DRMAX);
  747. return -1;
  748. }
  749. dev = Drnbr++;
  750. /* Initialize hardware-level control structure */
  751. Drsi[dev].addr = htoi(argv[1]);
  752. Drsi[dev].vec = atoi(argv[2]);
  753. if(strchr(argv[2],'c') != NULL)
  754. Drsi[dev].chain = 1;
  755. else
  756. Drsi[dev].chain = 0;
  757. /* Save original interrupt vector */
  758. Drsi[dev].oldvec = getirq(Drsi[dev].vec);
  759. /* Set new interrupt vector */
  760. if(setirq(Drsi[dev].vec,Drhandle[dev]) == -1){
  761. printf("IRQ %u out of rangen",Drsi[dev].vec);
  762. Drnbr--;
  763. }
  764. /* Initialize the CTC */
  765. drinitctc(Drsi[dev].addr);
  766. /* Create iface structures and fill in details */
  767. if_pca = (struct iface *)callocw(1,sizeof(struct iface));
  768. if_pcb = (struct iface *)callocw(1,sizeof(struct iface));
  769. if_pca->addr = if_pcb->addr = Ip_addr;
  770. if(argc > 9)
  771. if_pca->addr = resolve(argv[9]);
  772. if(argc > 10)
  773. if_pcb->addr = resolve(argv[10]);
  774. if(if_pca->addr == 0 || if_pcb->addr == 0){
  775. printf(Noipaddr);
  776. free(if_pca);
  777. free(if_pcb);
  778. return -1;
  779. }
  780. /* Append "a" to iface associated with A channel */
  781. if_pca->name = mallocw((unsigned)strlen(argv[4])+2);
  782. strcpy(if_pca->name,argv[4]);
  783. strcat(if_pca->name,"a");
  784. /* Append "b" to iface associated with B channel */
  785. if_pcb->name = mallocw((unsigned)strlen(argv[4])+2);
  786. strcpy(if_pcb->name,argv[4]);
  787. strcat(if_pcb->name,"b");
  788. if_pcb->mtu = if_pca->mtu = atoi(argv[6]);
  789. if_pcb->ioctl = if_pca->ioctl = dr_ctl;
  790. if_pca->dev = 2*dev; /* dr0a */
  791. if_pcb->dev = 2*dev + 1; /* dr0b */
  792. if_pcb->stop = if_pca->stop = dr_stop;
  793. if_pcb->raw = if_pca->raw = dr_raw;
  794. setencap(if_pca,argv[3]);
  795. setencap(if_pcb,argv[3]);
  796. if(if_pcb->hwaddr == NULL)
  797. if_pcb->hwaddr = mallocw(sizeof(Mycall));
  798. memcpy(if_pcb->hwaddr,&Mycall,sizeof(Mycall));
  799. if(if_pca->hwaddr == NULL)
  800. if_pca->hwaddr = mallocw(sizeof(Mycall));
  801. memcpy(if_pca->hwaddr,&Mycall,sizeof(Mycall));
  802. /* Link em in to the iface chain */
  803. if_pca->next = if_pcb;
  804. if_pcb->next = Ifaces;
  805. Ifaces = if_pca;
  806. /* set params in drchan table for CHANNEL B */
  807. hp = &Drchan[2*dev+1]; /* dr1 is offset 1 */
  808. hp->iface = if_pcb;
  809. hp->stata = Drsi[dev].addr + CHANA + CTL; /* permanent status */
  810. hp->statb = Drsi[dev].addr + CHANB + CTL; /* addrs for CHANA/B*/
  811. if(argc > 8){
  812. /* Separate speed for channel B */
  813. hp->speed = (uint16)atoi(argv[8]);
  814. } else {
  815. /* Set speed to same as for channel A */
  816. hp->speed = (uint16)atoi(argv[7]);
  817. }
  818. hp->base = Drsi[dev].addr + CHANB;
  819. hp->bufsiz = atoi(argv[5]);
  820. hp->drtx_buffer = mallocw(if_pcb->mtu+100);
  821. hp->tstate = IDLE;
  822. hp->tx_state = drtx_idle;
  823. hp->w[RX].wcall = NULL;
  824. hp->w[RX].wakecnt = 0;
  825. hp->w[TX].wcall = NULL;
  826. hp->w[TX].wakecnt = 0;
  827. /* default KISS Params */
  828. hp->txdelay = 25; /* 250 Ms */
  829. hp->persist = 64; /* 25% persistence */
  830. hp->slotime = 10; /* 100 Ms */
  831. hp->squeldelay = 20; /* 200 Ms */
  832. hp->enddelay = 10; /* 100 Ms */
  833. write_scc(hp->stata,R9,FHWRES); /* Hardware reset */
  834. /* Disable interrupts with Master interrupt ctrl reg */
  835. write_scc(hp->stata,R9,0);
  836. drchanparam(hp); 
  837. /* Initialize buffer pointers */
  838. hp->rcvbuf = NULL;
  839. hp->rcvbuf->cnt = 0;
  840. hp->sndq = NULL;
  841. /* set params in drchan table for CHANNEL A */
  842. hp = &Drchan[2*dev]; /* dr0a is offset 0 */
  843. hp->iface = if_pca;
  844. hp->speed = (uint16)atoi(argv[7]);
  845. hp->base = Drsi[dev].addr + CHANA;
  846. hp->bufsiz = atoi(argv[5]);
  847. hp->drtx_buffer = mallocw(if_pca->mtu+100);
  848. hp->tstate = IDLE;
  849. hp->tx_state = drtx_idle;
  850. hp->w[RX].wcall = NULL;
  851. hp->w[RX].wakecnt = 0;
  852. hp->w[TX].wcall = NULL;
  853. hp->w[TX].wakecnt = 0;
  854. /* default KISS Params */
  855. hp->txdelay = 30; /* 300 Ms */
  856. hp->persist = 64; /* 25% persistence */
  857. hp->slotime = 10; /* 100 Ms */
  858. hp->squeldelay = 20; /* 200 Ms */
  859. hp->enddelay = 10; /* 100 Ms */
  860. drchanparam(hp);
  861. /* Initialize buffer pointers */
  862. hp->rcvbuf = NULL;
  863. hp->rcvbuf->cnt = 0;
  864. hp->sndq = NULL;
  865. write_scc(hp->base,R9,MIE|NV); /* master interrupt enable */
  866. /* Enable interrupt in 8259 interrupt controller */
  867. maskon(Drsi[dev].vec);
  868. cp = if_name(if_pca," tx");
  869. if_pca->txproc = newproc(cp,512,if_tx,0,if_pca,NULL,0);
  870. free(cp);
  871. cp = if_name(if_pcb," tx");
  872. if_pcb->txproc = newproc(cp,512,if_tx,0,if_pcb,NULL,0);
  873. free(cp);
  874. return 0;
  875. }
  876. /* Shut down iface */
  877. static int
  878. dr_stop(iface)
  879. struct iface *iface;
  880. {
  881. uint16 dev;
  882. dev = iface->dev;
  883. if(dev & 1)
  884. return 0;
  885. dev >>= 1; /* Convert back into DRSI number */
  886. /* Set 8259 interrupt mask (turn off interrupts) */
  887. maskoff(Drsi[dev].vec);
  888. /* Restore original interrupt vector */
  889. setirq(Drsi[dev].vec, Drsi[dev].oldvec);
  890. Drnbr--;
  891. /* Force hardware reset */
  892. write_scc(Drsi[dev].addr + CHANA + CTL,R9,FHWRES);
  893. /* Reset the CTC */
  894. (void) read_ctc(Drsi[dev].addr, Z8536_MICR);
  895. write_ctc(Drsi[dev].addr, Z8536_MICR, 0x01);
  896. return 0;
  897. }
  898. /* Send raw packet on DRSI card */
  899. static int
  900. dr_raw(
  901. struct iface *iface,
  902. struct mbuf **bpp
  903. ){
  904. char kickflag;
  905. struct drchan *hp;
  906. int i_state;
  907. dump(iface,IF_TRACE_OUT,*bpp);
  908. iface->rawsndcnt++;
  909. iface->lastsent = secclock();
  910. hp = &Drchan[iface->dev];
  911. i_state = dirps();
  912. kickflag = (hp->sndq == NULL) & (hp->sndbuf == NULL);
  913. /* clever! flag=1 if something in queue */
  914. enqueue(&hp->sndq,bpp);
  915. if(kickflag) /* simulate interrupt to xmit */
  916. tx_fsm(hp); /* process interrupt */
  917. restore(i_state);
  918. return 0;
  919. }
  920. /* display DRSI Channel stats */
  921. int
  922. dodrstat(argc,argv,p)
  923. int argc;
  924. char *argv[];
  925. void *p;
  926. {
  927. struct drchan *hp0, *hp1;
  928. int i;
  929. for(i=0; i<DRMAX; i++){
  930. hp0 = &Drchan[i];
  931. hp1 = &Drchan[i+1];
  932. i = Drchan[i].base;
  933. printf("DRSI Board Statistics - N6TTO 112790.0n");
  934. printf("--------------------------------------n");
  935. printf("Channel - %sn", hp0->iface->name);
  936. printf("Rxints  - %8ld  Txints  - %8ld  Exints  - %8ldn",
  937. hp0->rxints, hp0->txints, hp0->exints);
  938. printf("Enqued  - %8ld  Crcerr  - %8ld  Aborts  - %8ldn",
  939. hp0->enqueued, hp0->crcerr, hp0->aborts);
  940. printf("RFrames - %8ld  Rxovers - %8ld  TooBig  - %8ldn",
  941. hp0->rxframes, hp0->rovers, hp0->toobig);
  942. printf("Txdefer - %8ld  Txppers - %8ld  Nomem   - %8ldn",
  943. hp0->txdefers, hp0->txppersist, hp0->nomem);
  944. printf("Tx state  %8d  Rx state  %8dnn",hp0->tstate,hp0->rstate);
  945. printf("Channel - %sn", hp1->iface->name);
  946. printf("Rxints  - %8ld  Txints  - %8ld  Exints  - %8ldn",
  947. hp1->rxints, hp1->txints, hp1->exints);
  948. printf("Enqued  - %8ld  Crcerr  - %8ld  Aborts  - %8ldn",
  949. hp1->enqueued, hp1->crcerr, hp1->aborts);
  950. printf("RFrames - %8ld  Rxovers - %8ld  TooBig  - %8ldn",
  951. hp1->rxframes, hp1->rovers, hp1->toobig);
  952. printf("Txdefer - %8ld  Txppers - %8ld  Nomem   - %8ldn",
  953. hp1->txdefers, hp1->txppersist, hp1->nomem);
  954. printf("Tx state  %8d  Rx state  %8dn",hp1->tstate,hp1->rstate);
  955. }
  956. return 0;
  957. }
  958. /* Subroutine to set kiss params in channel tables */
  959. static int32
  960. dr_ctl(iface,cmd,set,val)
  961. struct iface *iface;
  962. int cmd;
  963. int set;
  964. int32 val;
  965. {
  966. struct drchan *hp;
  967. hp = &Drchan[iface->dev];
  968. switch(cmd){
  969. case PARAM_TXDELAY:
  970. if(set)
  971. hp->txdelay = val;
  972. return hp->txdelay;
  973. case PARAM_PERSIST:
  974. if(set)
  975. hp->persist = val;
  976. return hp->persist;
  977. case PARAM_SLOTTIME:
  978. if(set)
  979. hp->slotime = val;
  980. return hp->slotime;
  981. case PARAM_TXTAIL:
  982. if(set)
  983. hp->squeldelay = val;
  984. return hp->squeldelay;
  985. case PARAM_ENDDELAY:
  986. if(set)
  987. hp->enddelay = val;
  988. return hp->enddelay;
  989. case PARAM_SPEED:
  990. return hp->speed;
  991. }
  992. return -1;
  993. }