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

TCP/IP协议栈

开发平台:

Visual C++

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