home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / HS.C < prev    next >
C/C++ Source or Header  |  1992-05-15  |  18KB  |  720 lines

  1. /* Interface driver for the DRSI PCPA or the Eagle 8530 boards for the IBM PC
  2.  * connected to a WA4DSY 56kbps modem. Uses polling-loop transfers with
  3.  * interrupts disabled for maximum speed.
  4.  *
  5.  * This driver is a bit of a kludge. A DMA-driven card and driver (e.g.,
  6.  * the PI) is much better, but this is better than nothing if all you have
  7.  * is a "dumb" 8530 card.
  8.  *
  9.  * Copyright 1991 Phil Karn, KA9Q
  10.  */
  11. #include <stdio.h>
  12. #include <dos.h>
  13. #include "global.h"
  14. #include "mbuf.h"
  15. #include "iface.h"
  16. #include "pktdrvr.h"
  17. #include "netuser.h"
  18. #include "hs.h"
  19. #include "z8530.h"
  20. #include "ax25.h"
  21. #include "trace.h"
  22. #include "pc.h"
  23. #include "proc.h"
  24. #include "devparam.h"
  25.  
  26. static void flushrx __ARGS((int16 data));
  27. static void hdlcparam __ARGS((struct hdlc *hp));
  28. static void hexint __ARGS((struct hdlc *hp));
  29. static void hrxint __ARGS((struct hdlc *hp));
  30. static int hs_stop __ARGS((struct iface *iface));
  31. static int hs_raw __ARGS((struct iface *iface,struct mbuf *bp));
  32. static int32 hs_ctl __ARGS((struct iface *,int cmd,int set,int32 val));
  33. static void hstxoff __ARGS((struct hdlc *hp));
  34. static void hstxon __ARGS((struct hdlc *hp));
  35. static void htxint __ARGS((struct hdlc *hp));
  36. static void init_delay __ARGS((void));
  37. static void msdelay __ARGS((void));
  38.  
  39. static struct hs Hs[NHS];
  40. static INTERRUPT (*Hshandle[])() = { hs0vec };
  41. static struct hdlc Hdlc[2*NHS];
  42. static int16 Nhs;
  43.  
  44. /* Master interrupt handler for the PC-100 card. All interrupts come
  45.  * here first, then are switched out to the appropriate routine.
  46.  */
  47. INTERRUPT (far *(hsint)(dev))()
  48. int dev;
  49. {
  50.     register char iv;
  51.     int16 hsbase;
  52.     struct hs *hsp;
  53.     register struct hdlc *hp;
  54.     
  55.     hsp = &Hs[dev];
  56.     hsp->ints++;
  57.     hsbase = hsp->addr;
  58.  
  59. #ifdef    foo
  60.     outportb(hsbase+4,0x8+0x10);    /* HIT EAGLE INTACK */
  61.     (void)inportb(hsbase+CHANA+CTL,R0);
  62.     outportb(hsbase+4,0x8);        /***/
  63. #endif
  64.  
  65.     /* Read interrupt status from channel A */
  66.     while((iv = read_scc(hsbase+CHANA+CTL,R3)) != 0){
  67.         if(iv & CHARxIP){
  68.             /* Channel A Rcv Interrupt Pending */
  69.             hp = &Hdlc[2*dev];
  70.             hrxint(hp);
  71.         } else if(iv & CHATxIP){
  72.             /* Channel A Transmit Int Pending */
  73.             hp = &Hdlc[2*dev];
  74.             htxint(hp);
  75.         } else if(iv & CHAEXT){
  76.             /* Channel A External Status Int */
  77.             hp = &Hdlc[2*dev];
  78.             hexint(hp);
  79.         } else if(iv & CHBRxIP){
  80.             /* Channel B Rcv Interrupt Pending */
  81.             hp = &Hdlc[(2*dev)+1];
  82.             hrxint(hp);
  83.         } else if(iv & CHBTxIP){
  84.             /* Channel B Transmit Int Pending */
  85.             hp = &Hdlc[(2*dev)+1];
  86.             htxint(hp);
  87.         } else if(iv & CHBEXT){
  88.             /* Channel B External Status Int */
  89.             hp = &Hdlc[(2*dev)+1];
  90.             hexint(hp);
  91.         }
  92.         /* Reset interrupt pending state */
  93.         write_scc(hp->ctl,R0,RES_H_IUS);
  94.         outportb(hsbase+CHANA+CTL,0);    /* Restore pointer to 0 */
  95.         outportb(hsbase+CHANB+CTL,0);    /* Restore pointer to 0 */
  96.     }
  97.     outportb(hsbase+CHANA+CTL,0);    /* Restore pointer to 0 */
  98.     outportb(hsbase+CHANB+CTL,0);    /* Restore pointer to 0 */
  99.     return hsp->chain ? hsp->save.vec : NULL;
  100. }
  101. /* HDLC SIO External/Status interrupts
  102.  * The only one that can happen in this driver is a DCD change
  103.  */
  104. static void
  105. hexint(hp)
  106. register struct hdlc *hp;
  107. {
  108.     struct mbuf *rcvbuf;
  109.     char *cp;
  110.     int cnt,data;
  111.     register int ctl;
  112.  
  113.     ctl = hp->ctl;
  114.     data = hp->data;
  115.     hp->exints++;
  116.  
  117.     /* Allocate a receive buffer */
  118.     if((rcvbuf = alloc_mbuf(hp->bufsiz+sizeof(struct iface *))) == NULLBUF){
  119.         /* Alloc failed; refuse to proceed */
  120.         hp->nomem++;
  121.         write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
  122.         write_scc(ctl,R0,RES_EXT_INT);
  123.         return;
  124.     }
  125.     /* Allow space for descriptor on front */
  126.     rcvbuf->data += sizeof(struct iface *);
  127.     cnt = 0;
  128.  
  129.     /* Disable DCDIE bit so we can track changes in DCD */
  130.     write_scc(ctl,R15,0);
  131.  
  132.     write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
  133.     flushrx(data);
  134.     while((cnt = rx8530(ctl,data,cp,hp->bufsiz)) != -1){
  135.         if(cnt > 4){
  136.             /* Good frame */
  137.             hp->good++;
  138.             /* Toss crc */
  139.             rcvbuf->cnt = cnt - 1;
  140.             net_route(hp->iface,rcvbuf);
  141.             /* Replenish buffer */
  142.             rcvbuf = alloc_mbuf(hp->bufsiz + sizeof(struct iface *));
  143.         }
  144.         /* Start new buffer */
  145.         if(rcvbuf == NULLBUF)
  146.             break;    /* alloc failed */
  147.         rcvbuf->data +=  sizeof(struct iface *);
  148.     }    
  149.     write_scc(ctl,R0,RES_EXT_INT);
  150.     write_scc(ctl,R15,DCDIE);    /* Re-enable DCD */
  151.     write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
  152.  
  153.     /* Get rid of fragmentary buffer */
  154.     free_p(rcvbuf);
  155. }
  156. static void
  157. flushrx(data)
  158. register int16 data;
  159. {
  160.     register int i = 5;
  161.     while(i-- != 0)
  162.         (void)inportb(data);
  163. }
  164. /* HDLC receiver interrupt handler.
  165.  * Not used in this driver
  166.  */
  167. static void
  168. hrxint(hp)
  169. register struct hdlc *hp;
  170. {
  171. }
  172. /* HDLC transmit interrupt service routine
  173.  * Not used in this driver
  174.  */
  175. static void
  176. htxint(hp)
  177. register struct hdlc *hp;
  178. {
  179. }
  180.  
  181. /* (re)Initialize HDLC controller parameters */
  182. static void
  183. hdlcparam(hp)
  184. register struct hdlc *hp;
  185. {
  186.     register int16 ctl;
  187.  
  188.     /* Initialize 8530 channel for SDLC operation */
  189.     ctl = hp->ctl;
  190.     DISABLE();
  191.  
  192. #ifdef    foo
  193.     switch(ctl & 2){
  194.     case CHANA:
  195.         write_scc(ctl,R9,CHRA);    /* Reset channel A */
  196.         break;
  197.     case CHANB:
  198.         write_scc(ctl,R9,CHRB);    /* Reset channel B */
  199.         break;
  200.     }
  201.     pause(1L);    /* Allow plenty of time for resetting */
  202. #endif
  203.  
  204.     /* Deselect interrupts for now */
  205.     write_scc(ctl,R1,0);
  206.     write_scc(ctl,R15,0);
  207.  
  208.     /* X1 clock, SDLC mode, Sync modes enable, parity disable */
  209.     write_scc(ctl,R4,X1CLK | SDLC | SYNC_ENAB);
  210.  
  211.     /* CRC preset 1, NRZ encoding, no active on poll, flag idle,
  212.      * flag on underrun, no loop mode, 8 bit sync
  213.      */
  214.     write_scc(ctl,R10,CRCPS|NRZ);
  215.  
  216.     /* 8530 gets both tx and rx clock from modem.
  217.      * By default, TRxC = transmit clock, RTxC = receive clock
  218.      * (swapped 11 Feb 1990 to use new DRSI wiring) UNLESS
  219.      * the 'r' parameter is specified
  220.      */
  221.     if(!hp->clkrev)
  222.         write_scc(ctl,R11,RCRTxCP | TCTRxCP);
  223.     else
  224.         write_scc(ctl,R11,RCTRxCP | TCRTxCP);
  225.  
  226.     /* Note: baud rate generator not used */
  227.  
  228.     /* Null out SDLC start address */
  229.     write_scc(ctl,R6,0);
  230.  
  231.     /* SDLC flag */
  232.     write_scc(ctl,R7,FLAG);
  233.  
  234.     /* DTR On, 8 bit TX chars, no break, TX enable, SDLC CRC,
  235.      * RTS off, TxCRC enable
  236.      */
  237.     write_scc(ctl,R5,DTR|Tx8|TxENAB|TxCRC_ENAB);
  238.  
  239.     /* 8 bit RX chars, auto enables off, no hunt mode, RxCRC enable,
  240.      * no address search, no inhibit sync chars, disable RX. Rx is
  241.      * started only by an actual DCD interrupt
  242.      */
  243.     write_scc(ctl,R3,RxENABLE|RxCRC_ENAB|Rx8);
  244.  
  245.     /* Dummy interrupt vector
  246.      * (This probably isn't necessary)
  247.      */
  248.     write_scc(ctl,R2,0);
  249.  
  250.     /* Enable only the external interrupts (modem interrupts) since
  251.      * polling is used for all actual tx/rx operations
  252.      */
  253.     write_scc(ctl,R1,EXT_INT_ENAB);
  254.  
  255.     /* Enable only DCD interrupts */
  256.     write_scc(ctl,R15,DCDIE);
  257.  
  258.     /* No reset, status low, master int enable, enable lower chain,
  259.      * no vector
  260.      */
  261.     write_scc(ctl,R9,MIE|NV);
  262.  
  263.     RESTORE();
  264. }
  265. /* Attach a high speed iterface to the system
  266.  * argv[0]: hardware type, must be "hs"
  267.  * argv[1]: I/O address, e.g., "0x380"
  268.  * argv[2]: vector, e.g., "2"
  269.  * argv[3]: mode, must be "ax25"
  270.  * argv[4]: interface base label, e.g., "drsi0". Driver appends "a" and "b".
  271.  * argv[5]: receiver packet buffer size in bytes
  272.  * argv[6]: maximum transmission unit, bytes
  273.  * argv[7]: keyup delay, milliseconds
  274.  * argv[8]: persistence value, 0-255
  275.  * argv[9]: "r" to reverse sense of clock leads (optional)
  276.  */
  277. int
  278. hs_attach(argc,argv,p)
  279. int argc;
  280. char *argv[];
  281. void *p;
  282. {
  283.     register struct iface *if_hsa,*if_hsb;
  284.     struct hdlc *hp;
  285.     int dev;
  286.     char *cp;
  287.  
  288.     if(Nhs >= NHS){
  289.         printf("Too many hs controllers\n");
  290.         return -1;
  291.     }
  292.     if(if_lookup(argv[4]) != NULLIF){
  293.         printf("Interface %s already exists\n",argv[4]);
  294.         return -1;
  295.     }
  296.     dev = Nhs++;
  297.  
  298.     /* Initialize hardware-level control structure */
  299.     Hs[dev].addr = htoi(argv[1]);
  300.     Hs[dev].vec = atoi(argv[2]);
  301.     if(strchr(argv[2],'c') != NULLCHAR)
  302.         Hs[dev].chain = 1;
  303.     else
  304.         Hs[dev].chain = 0;
  305.  
  306.     /* Save original interrupt vector */
  307.     Hs[dev].save.vec = getirq(Hs[dev].vec);
  308.     /* Set new interrupt vector */
  309.     if(setirq(Hs[dev].vec,Hshandle[dev]) == -1){
  310.         printf("IRQ %u out of range\n",Hs[dev].vec);
  311.         Nhs--;
  312.         return -1;
  313.     }
  314.     /* Create interface structures and fill in details */
  315.     if_hsa = (struct iface *)callocw(1,sizeof(struct iface));
  316.     if_hsb = (struct iface *)callocw(1,sizeof(struct iface));
  317.  
  318.     if_hsa->addr = if_hsb->addr = Ip_addr;
  319.     if_hsa->name = mallocw(strlen(argv[4])+2);
  320.     strcpy(if_hsa->name,argv[4]);
  321.     strcat(if_hsa->name,"a");
  322.     if_hsb->name = mallocw(strlen(argv[4])+2);
  323.     strcpy(if_hsb->name,argv[4]);
  324.     strcat(if_hsb->name,"b");
  325.     if_hsb->mtu = if_hsa->mtu = atoi(argv[6]);
  326.     if_hsa->dev = 2*dev;
  327.     if_hsb->dev = 2*dev + 1;
  328.     if_hsb->stop = if_hsa->stop = hs_stop;
  329.     if_hsb->raw = if_hsa->raw = hs_raw;
  330.     if_hsa->ioctl = if_hsb->ioctl = hs_ctl;
  331.  
  332.     if(strcmp(argv[3],"ax25") == 0){
  333.         if(Mycall[0] == '\0'){
  334.             printf("set mycall first\n");
  335.             free((char *)if_hsa);
  336.             free((char *)if_hsb);
  337.             return -1;
  338.         }        
  339.         setencap(if_hsa,"AX25");
  340.         setencap(if_hsb,"AX25");
  341.         if(if_hsb->hwaddr == NULLCHAR)
  342.             if_hsb->hwaddr = mallocw(AXALEN);
  343.         memcpy(if_hsb->hwaddr,Mycall,AXALEN);
  344.         if(if_hsa->hwaddr == NULLCHAR)
  345.             if_hsa->hwaddr = mallocw(AXALEN);
  346.         memcpy(if_hsa->hwaddr,Mycall,AXALEN);
  347.     } else {
  348.         printf("Mode %s unknown for interface %s\n",
  349.             argv[3],argv[4]);
  350.         free((char *)if_hsa);
  351.         free((char *)if_hsb);
  352.         return -1;
  353.     }
  354.     if_hsa->next = if_hsb;
  355.     if_hsb->next = Ifaces;
  356.     Ifaces = if_hsa;
  357.  
  358.     write_scc(Hs[dev].addr+CHANA+CTL,R9,FHWRES);
  359.     hp = &Hdlc[2*dev+1];
  360.     hp->ctl = Hs[dev].addr + CHANB + CTL;
  361.     hp->data = Hs[dev].addr + CHANB + DATA;
  362.     hp->bufsiz = atoi(argv[5]);
  363.     if(argc > 7)
  364.         hp->txdelay = atol(argv[7]);
  365.     else
  366.         hp->txdelay = 15L;
  367.     if(argc > 8)
  368.         hp->p = atoi(argv[8]);
  369.     else
  370.         hp->p = 64;
  371.     if(argc > 9 && argv[9][0] == 'r')
  372.         hp->clkrev = 1;
  373.     else
  374.         hp->clkrev = 0;
  375.     hp->iface = if_hsb;
  376.     hdlcparam(hp);
  377.  
  378.     hp = &Hdlc[2*dev];
  379.     hp->ctl = Hs[dev].addr + CHANA + CTL;
  380.     hp->data = Hs[dev].addr + CHANA + DATA;
  381.     hp->bufsiz = atoi(argv[5]);
  382.     hp->txdelay = Hdlc[2*dev+1].txdelay;
  383.     hp->p = Hdlc[2*dev+1].p;
  384.     if(argc > 9 && argv[9][0] == 'r')
  385.         hp->clkrev = 1;
  386.     else
  387.         hp->clkrev = 0;
  388.     hp->iface = if_hsa;
  389.     hdlcparam(hp);
  390.  
  391.     outportb(Hs[dev].addr + 4,0x08);    /*EAGLE INT GATE */
  392.     /* Clear mask (enable interrupt) in 8259 interrupt controller */
  393.     maskon(Hs[dev].vec);
  394.  
  395.     /* Initialize timing delay loop */
  396.     init_delay();
  397.     cp = if_name(if_hsa," tx");
  398.     if_hsa->txproc = newproc(cp,512,if_tx,0,if_hsa,NULL,0);
  399.     free(cp);
  400.     cp = if_name(if_hsb," tx");
  401.     if_hsb->txproc = newproc(cp,512,if_tx,0,if_hsb,NULL,0);
  402.     free(cp);
  403.     return 0;
  404. }
  405. static int
  406. hs_stop(iface)
  407. struct iface *iface;
  408. {
  409.     int dev;
  410.  
  411.     dev = iface->dev;
  412.     if(dev & 1)
  413.         return -1;    /* Valid only for the first device */
  414.     dev >>= 1;    /* Convert back into hs number */
  415.  
  416.     /* Turn off interrupts */
  417.     maskoff(Hs[dev].vec);
  418.  
  419.     /* Restore original interrupt vector */
  420.     setirq(Hs[dev].vec,Hs[dev].save.vec);
  421.  
  422.     /* Force hardware reset */
  423.     write_scc(Hs[dev].addr + CHANA+CTL,R9,FHWRES);
  424.     return 0;
  425. }
  426. /* Send raw packet */
  427. static int
  428. hs_raw(iface,bp)
  429. struct iface *iface;
  430. struct mbuf *bp;
  431. {
  432.  
  433.     struct hdlc *hp;
  434.     struct mbuf *nbp;
  435.     register int16 cnt;
  436.     register char *cp;
  437.     int16 ctl,data;
  438.  
  439.     dump(iface,IF_TRACE_OUT,bp);
  440.     iface->rawsndcnt++;
  441.     iface->lastsent = secclock();
  442.     hp = &Hdlc[iface->dev];
  443.     hp->txpkts++;
  444.  
  445.     ctl = hp->ctl;
  446.     data = hp->data;
  447.  
  448.     cnt = len_p(bp);
  449.     /* If buffer isn't contiguous (which is almost always
  450.      * the case) copy it to a new buffer for speed
  451.      */
  452.     if(bp->next != NULLBUF){
  453.         if((nbp = copy_p(bp,cnt)) == NULLBUF){
  454.             hp->nomem++;
  455.             free_p(bp);
  456.             return -1;
  457.         }
  458.         free_p(bp);
  459.         bp = nbp;
  460.     }
  461.     cp = bp->data;
  462.     /* Turn transmitter on */
  463.     hstxon(hp);
  464.     /* Initialize transmitter CRC */
  465.     write_scc(ctl,R0,RES_Tx_CRC);
  466.     for(;;){
  467.         /* Wait for the transmitter to become ready */
  468.         while(!(inportb(ctl) & Tx_BUF_EMP))
  469.             ;
  470.         if(cnt-- == 0)
  471.             break;
  472.         outportb(data,*cp++); /* Send the character */
  473.     }
  474.     write_scc(ctl,R0,RES_EOM_L);    /* Allow CRC generation */
  475.     /* End of frame. Wait for TxEOM to go high, indicating start of
  476.      * CRC transmission. Note that we don't reset the transmit
  477.      * interrupt pending flag as one ordinarily would, since we're
  478.      * not using tx interrupts.
  479.      */
  480.     while(!(inportb(ctl) & TxEOM))
  481.         ;
  482.  
  483.     free_p(bp);
  484.     hstxoff(hp);    /* Shut down tx */
  485.     /* Hold off to give other guy a chance to
  486.      * respond
  487.      */
  488.     hp->deftime = msclock() + hp->txdelay + 500;
  489.     return 0;
  490. }
  491.  
  492. /* Turn on high speed transmitter. Does p-persistence, then sends a dummy
  493.  * frame to allow for keyup delay. Returns with transmitter on and interrupts
  494.  * disabled
  495.  */
  496. static void
  497. hstxon(hp)
  498. struct hdlc *hp;
  499. {
  500.     int16 ctl;
  501.     int i;
  502.     long ca;
  503.     int32 t;
  504.  
  505.     ctl = hp->ctl;
  506.  
  507.     /* Defer logic. Wait until deftime is in the past (so we
  508.      * defer to any overheard CTS messages) AND the p-persistence
  509.      * dice roll succeeds. The computation of ca allows for clock
  510.      * rollover (which happens every 49+ days).
  511.      */
  512.     for(;;){
  513.         t = msclock();
  514.         ca = hp->deftime - t;
  515.         if(ca > 0){
  516.             pause(ca);
  517.             continue;
  518.         }
  519.         hp->deftime = t;    /* Keep from getting too old */
  520.         if((rand() & 0xff) > uchar(hp->p)){
  521.             pause((long)MSPTICK);
  522.             continue;
  523.         }
  524.         break;
  525.     }
  526.     /* Prevent distractions. In particular, block off the DCD interrupt
  527.      * so we don't hear our own carrier and hang in the interrupt handler!
  528.      * Note that simply disabling CPU interrupts isn't enough since
  529.      * the call to pause will block and the kernel will re-enable
  530.      * them.
  531.      */
  532.     write_scc(ctl,R9,0);    /* Disable all SCC interrupts */
  533.     disable();
  534.  
  535.     /* Turn on carrier, enable transmitter */
  536.     write_scc(ctl,R5,TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR);
  537.  
  538.     /* Delay for keyup interval */
  539.     for(i=hp->txdelay;i != 0;i--)
  540.         msdelay();
  541.  
  542. }
  543. /* Turn transmitter off at the end of a series of frames */
  544. static void
  545. hstxoff(hp)
  546. struct hdlc *hp;
  547. {
  548.     int cnt;
  549.     int16 ctl,data;
  550.  
  551.     ctl = hp->ctl;
  552.     data = hp->data;
  553.     /* To allow the SCC buffering to drain, we begin a dummy frame,
  554.      * then abort it
  555.      */
  556.     for(cnt=5;cnt != 0;cnt--){
  557.         while(!(inportb(ctl) & Tx_BUF_EMP))
  558.             ;
  559.         outportb(data,0);
  560.     }
  561.     write_scc(ctl,R0,SEND_ABORT);
  562.  
  563.     /* Turn off carrier and disable transmitter */
  564.     write_scc(ctl,R5,TxCRC_ENAB | Tx8 | DTR);
  565.     /* Re-Enable SCC interrupts */
  566.     write_scc(ctl,R9,MIE|NV);        
  567.     enable();    /* Turn interrupts back on */
  568. }
  569.  
  570. int
  571. dohs(argc,argv,p)
  572. int argc;
  573. char *argv[];
  574. void *p;
  575. {
  576.     register int i;
  577.     register struct hdlc *hp;
  578.  
  579.     for(i=0;i<2*Nhs;i++){
  580.         hp = &Hdlc[i];
  581.         if(printf("port %d: txpkts %lu ints %lu rxpkts %lu rxbytes %lu nomem %lu toobig %lu crcerr %lu aborts %lu overrun %lu\n",
  582.          i,hp->txpkts,hp->exints,hp->good,hp->rxbytes,
  583.          hp->nomem,hp->toobig,hp->crcerr,hp->aborts,
  584.          hp->overrun) == EOF)
  585.             break;
  586.     }
  587.     return 0;
  588. }
  589. static int32
  590. hs_ctl(iface,cmd,set,val)
  591. struct iface *iface;
  592. int cmd;
  593. int set;
  594. int32 val;
  595. {
  596.     register struct hdlc *hp;
  597.     int32 t,ca;
  598.  
  599.     hp = &Hdlc[iface->dev];
  600.     switch(cmd){
  601.     case PARAM_TXDELAY:    /* Tx keyup delay */
  602.         if(set)
  603.             hp->txdelay = val;
  604.         return hp->txdelay;
  605.     case PARAM_PERSIST:
  606.         if(set)
  607.             hp->p = val;
  608.         return uchar(hp->p);
  609.     case PARAM_MUTE:
  610.         /* Mute transmitter for specified # of ms */
  611.         if(set){
  612.             if(val == -1){
  613.                 /* Special case for duration of a CTS */
  614.                 val = hp->txdelay + 500;
  615.             }
  616.             hp->deftime = msclock() + val;
  617.         }
  618.         t = msclock();
  619.         ca = hp->deftime - t;
  620.         if(ca < 0){
  621.             hp->deftime = t;
  622.             ca = 0;
  623.         }
  624.         return ca;
  625.     }
  626.     return -1;
  627. }
  628. #ifdef    notdef        /* replaced with assembler in 8530.asm */
  629. /* Read data from the 8530 receiver.
  630.  * Returns when either a good frame is received, or when carrier drops.
  631.  * If a good frame is received, the length is returned; otherwise -1.
  632.  */
  633. int
  634. rx8530(ctl,data,buf,bufsize)
  635. int16 ctl,data;
  636. char *buf;
  637. int16 bufsize;
  638. {
  639.     int cnt = 0;
  640.     register char status;
  641.     char error;
  642.     register char *cp = buf;
  643.  
  644.     for(;;){
  645.         status = inportb(ctl);
  646.         if(!(status & DCD)){
  647.             cnt = -1;
  648.             break;
  649.         } else if(status & BRK_ABRT){
  650.             cp = buf;
  651.             cnt = 0;
  652.         } else if(status & Rx_CH_AV){
  653.             /* Receive character is ready, get it */
  654.             *cp++ = inportb(data);
  655.             if(++cnt > bufsize){
  656.                 /* Buffer overflow, start again */
  657.                 write_scc(ctl,R3,ENT_HM|RxENABLE|RxCRC_ENAB|Rx8);
  658.                 cp = buf;
  659.                 cnt = 0;
  660.             }
  661.         } else if((error = read_scc(ctl,R1)) & END_FR){
  662.             if(!(error & CRC_ERR))
  663.                 break;    /* Good frame! */
  664.             /* Bad frame, start again */
  665.             cp = buf;
  666.             cnt = 0;
  667.         }
  668.     }
  669.     return cnt;
  670. }
  671. #endif
  672.  
  673. static int32 Del_const;
  674.  
  675. /* Find the value of Del_const that will cause one execution of mloop()
  676.  * to take one millisecond
  677.  */
  678. static void
  679. init_delay()
  680. {
  681.     int32 start,delay;
  682.     register int i,j;
  683.     int success = 0;
  684.  
  685.     /* Start with small value to make things tolerable on slow machines */
  686.     Del_const = 10;
  687.     printf("Del_const = %lu\n",Del_const);
  688.     /* Limit the number of iterations in case we don't converge */
  689.     for(i=0;i<5;i++){
  690.         start = msclock();
  691.         for(j=0;j<1000;j++)
  692.             msdelay();
  693.         delay = msclock()-start;
  694.         printf("delay %lu\n",delay);
  695.         if(delay == 0){
  696.             /* Too fast for accurate measurement on coarse clk */    
  697.             Del_const *= 10;
  698.             printf("Del_const = %lu\n",Del_const);
  699.             continue;
  700.         }
  701.         Del_const = (Del_const * 1000)/delay;
  702.         printf("Del_const = %lu\n",Del_const);
  703.         if(delay > 950 && delay < 1050){
  704.             success = 1;
  705.             break;    /* Within 1 tick - Close enough */
  706.         }
  707.     }
  708.     if(!success)
  709.         printf("HS: Warning: auto delay set failed\n");
  710. }
  711. /* Delay for one millisecond (once calibrated by init_delay()) */
  712. static void
  713. msdelay()
  714. {
  715.     int32 i;
  716.  
  717.     for(i=Del_const;i !=0;i--)
  718.         ;
  719. }
  720.