home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / MISC / BBENCH21.ZIP / SOURCE.ZIP / BENCHCOD.C next >
Encoding:
C/C++ Source or Header  |  1990-08-24  |  39.1 KB  |  1,560 lines

  1. /*«PL1»*/
  2. /*
  3. ** Low-level Benchmarks for 80x86 machines.
  4. ** BYTE Magazine
  5. ** Apr. 1990
  6. **
  7. ** This module contains the high level source for the BYTE benchmarks
  8. ** Routines called from this module may be found in BENCHSUBS.ASM.
  9. **
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <stdarg.h>
  14. #include <dos.h>
  15. #include <mem.h>
  16. #include <math.h>
  17. #include <float.h>
  18. #include "benchdef.h"
  19. #include "win.h"
  20.  
  21. /* Typedefs */
  22. typedef struct {
  23.     unsigned int maxhead;    /* Max head number */
  24.     unsigned int maxcyl;    /* Max cylinder number */
  25.     unsigned int sectspertrack;    /* Sectors per track */
  26. } harddiskspecs;
  27.  
  28. /* external globals */
  29. extern unsigned long ll_filelen();
  30. extern volatile struct mcfig machine_config;
  31. extern int tdef[14];
  32. extern int oldlen;
  33.  
  34. /* window prototypes  (winsubs.asm)*/
  35. extern int chattr (win_handle *, int, int, int, int, int, int);
  36. extern int winputch (win_handle *, int, int, char);
  37. extern void clearscreen (void);
  38.  
  39. /* misc prototypes (miscsubs.asm) */
  40. extern void click(void);
  41.  
  42. /*local prototypes */
  43. char *gfname(int);
  44. long randwc(long);
  45. long randnum(long);
  46. double timetodouble( unsigned int *);
  47. void adjust_bar(win_handle*, int, int);
  48.  
  49. /****************************
  50. *          sieve            *
  51. *****************************
  52. ** The (in)famous sieve of Eratosthenes.
  53. ** Call with:
  54. **  sieve (winptr,dotime,acttime,iters)
  55. ** Where:
  56. **  winptr= handle of window upon which to draw slidey-bar; null means don't
  57. **  dotime = # of seconds for the system to execute the sieve
  58. ** Returns:
  59. **  acttime[3] = pointer to a 3-element array
  60. **               acttime[0] = # of microseconds actually elapsed
  61. **               acttime[1] = # of milliseconds actually elapsed
  62. **               acttime[2] = # of seconds actually elapsed
  63. **  iters = number of iterations performed in acttime
  64. */
  65. sieve(winptr,dotime,acttime,iters)
  66. win_handle *winptr;        /* current window */
  67. unsigned int dotime;        /* Seconds to execute */
  68. unsigned int acttime[3];    /* Actual elapsed time */
  69. unsigned int *iters;        /* # of iterations performed */
  70. {
  71. unsigned int mysegptr;        /* Place to hold pointer for segment */
  72. unsigned int mytime[3];        /* Local for time accumulation */
  73.  
  74. /* Clear # of iterations and actual time */
  75. *iters=0;
  76. acttime[0]=acttime[1]=acttime[2]=0;
  77.  
  78. /* Get a segment for the array */
  79. if(allocmem(SIEVESIZE/16+1,&mysegptr)!=-1)
  80.     return;                /* Allocation failed */
  81.  
  82. /* Loop and execute */
  83. do {
  84.     start_timer();
  85. /*
  86. ** NOTE: If you want to see how many primes the do_sieve() function
  87. ** finds, simply examine its return value.  We don't do that here.
  88. */
  89.     do_sieve(mysegptr,SIEVESIZE);
  90.  
  91.     stop_timer(mytime);
  92.  
  93.     /* Accumulate elapsed time into total time */
  94.     accumtime(mytime,acttime);
  95.  
  96.     *iters+=1;            /* Increment iterations */
  97.  
  98.     if(winptr!=NULL)
  99.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  100.  
  101. } while(acttime[2]<dotime);
  102.  
  103. /* Free the array segment */
  104. freemem(mysegptr);
  105.  
  106. }
  107.  
  108. /****************************
  109. *           sort            *
  110. *****************************
  111. ** The Sort benchmark (new and improved!)
  112. ** Call with:
  113. **   sort(winptr,dotime,acttime,iters)
  114. ** Where:
  115. **   winptr= handle of window upon which to draw slidey-bar; null means don't
  116. **   dotime = # of seconds to perform the sort
  117. ** Returns:
  118. **   acttime[3] = pointer to a 3-element array
  119. **                acttime[0]=# of microseconds elapsed
  120. **                acttime[1]=# of milliseconds elapsed
  121. **                acttime[3]=# of seconds elapsed
  122. **   iters = # of iterations completed
  123. **
  124. ** NOTE: Here, a SINGLE iteration is considered to be 1 pass
  125. **       of the quick sort and 1 pass of the shell sort.
  126. */
  127. sort(winptr, dotime,acttime,iters)
  128. win_handle *winptr;        /* current window */
  129. unsigned int dotime;        /* Time to do iterations */
  130. unsigned int acttime[3];    /* Actual elapsed time */
  131. unsigned int *iters;        /* # of iterations */
  132. {
  133. unsigned int mysegptr;        /* Pointer to array segment */
  134. unsigned int mytime[3];        /* Local for elapsed time */
  135. unsigned int rarrayseg;        /* Pointer to random array */
  136.  
  137. /* Clear iterations and actual time */
  138. *iters=0;
  139. acttime[0]=acttime[1]=acttime[2]=0;
  140.  
  141. /* Allocate memory segments for the arrays */
  142. if(allocmem(SORTSIZE/8+1,&mysegptr)!=-1)
  143.     return;            /* Return if failure */
  144. if(allocmem(SORTSIZE/8+1,&rarrayseg)!=-1)
  145. {    freemem(mysegptr);
  146.     return;            /* Return if failure */
  147. }
  148.  
  149. /* Restart the random number generator */
  150. randnum(1L);
  151.  
  152. /* Fill up the random array */
  153. rload_int_seg(rarrayseg,SORTSIZE,32767);
  154.  
  155. do {
  156.  
  157.     /* Copy random array into local */
  158.     segcopy(mysegptr,rarrayseg,SORTSIZE+SORTSIZE);
  159.  
  160.     start_timer();
  161.  
  162.     /* Do a quicksort */
  163.     do_qsort(mysegptr,0,SORTSIZE);
  164.  
  165.     stop_timer(mytime);
  166.     accumtime(mytime,acttime);
  167.  
  168.     /* Fill the array again */
  169.     segcopy(mysegptr,rarrayseg,SORTSIZE+SORTSIZE);
  170.  
  171.     start_timer();
  172.  
  173.     /* Do a shellsort */
  174.     do_shell(mysegptr,SORTSIZE);
  175.  
  176.     stop_timer(mytime);
  177.     accumtime(mytime,acttime);
  178.  
  179.     *iters+=1;        /* Increment iterations counter */
  180.  
  181.     if(winptr!=NULL)
  182.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  183.  
  184. } while(acttime[2]<dotime);
  185.  
  186. /* Free the memory segments */
  187. freemem(rarrayseg);
  188. freemem(mysegptr);
  189.  
  190. }
  191.  
  192. /****************************
  193. *      movetest             *
  194. *****************************
  195. ** Executes the string move benchmarks.
  196. ** Call with:
  197. **  dotime = max # of seconds for each test
  198. **  nk = # of K bytes to move
  199. ** Returns:
  200. **  acttime[5][3] = Matrix of results.  First index picks:
  201. **                     0=byte-wide
  202. **                     1=word-wide, odd address
  203. **                     2=word-wide, even address
  204. **                     3=dword-wide, odd address
  205. **                     4=dword-wide, even address
  206. **         The last two are filled only if is386!=0.
  207. **         Second index picks 0=micr, 1=milli, 2=seconds.
  208. ** iters[5] = # of iterations for each test.
  209. */
  210. movetest(winptr, dotime,nk,acttime,iters)
  211. win_handle *winptr;        /* current window */
  212. unsigned int dotime;        /* Time to run each test */
  213. unsigned int nk;        /* K bytes to move */
  214. unsigned int acttime[5][3];    /* Actual elapsed time */
  215. unsigned int iters[5];        /* Iterations for each test */
  216. {
  217. unsigned int ssegptr;        /* Source segment */
  218. unsigned int dsegptr;        /* Destination segment */
  219. unsigned int i,j;            /* Index variables */
  220. unsigned int totloops;        /* processor dependent number of loops */
  221.  
  222. /* Clear out the results arrays */
  223. for(i=0;i<5;i++)
  224. {    iters[i]=0;
  225.     for(j=0;j<3;j++)
  226.         acttime[i][j]=0;
  227. }
  228.  
  229. /* Allocate source and destination segments */
  230. if(allocmem(nk*64+1,&ssegptr)!=-1) return;
  231. if(allocmem(nk*64+1,&dsegptr)!=-1)
  232. {    freemem(ssegptr);
  233.     return;
  234. }
  235.  
  236. /* Loop through the tests */
  237.  
  238. /* Can we do 386 stuff? */
  239. totloops=(machine_config.proc_type>286)? 5:3;
  240.  
  241. for(i=0; i<totloops; ++i)
  242. {
  243.     moveloop(i,ssegptr,dsegptr,nk,dotime,acttime,iters);
  244.  
  245.     if(winptr!=NULL)
  246.         adjust_bar(winptr, i+1, totloops);  /* slide the bar */
  247.  
  248. }
  249.  
  250. /* Free up segments */
  251. freemem(dsegptr);
  252. freemem(ssegptr);
  253.  
  254. return;
  255. }
  256.  
  257. /****************************
  258. *      moveloop             *
  259. *****************************
  260. * Inner loop of movetest
  261. * i selects which test:
  262. *   0 = byte wide
  263. *   1 = word wide odd boundary
  264. *   2 = word wide even boundary
  265. *   3 = double word wide odd boundary
  266. *   4 = double word wide even boundary
  267. */
  268.  
  269. moveloop(i,seg1,seg2,nk,dotime,acttime,iters)
  270. unsigned int i;        /* Which test to perform */
  271. unsigned int seg1;    /* Segment 1 (source) */
  272. unsigned int seg2;    /* Segment 2 (destination) */
  273. unsigned int nk;    /* Number of K bytes */
  274. unsigned int dotime;    /* Max seconds to do */
  275. unsigned int acttime[5][3];    /* Actual elapsed time */
  276. unsigned int iters[5];    /* Iterations */
  277. {
  278. unsigned int nb;        /* Number of bytes to move */
  279. unsigned int nw;        /* Number of words to move */
  280. unsigned int nd;        /* Number of doublewords to move */
  281. unsigned int soff;        /* Source offset */
  282. unsigned int doff;        /* Destination offset */
  283. unsigned int myactime[3];    /* Local for accumulating time */
  284. unsigned int eltime[3];        /* Local for elapsed time per iteration */
  285.  
  286. /* Clear accumulators */
  287. myactime[0]=myactime[1]=myactime[2]=0;
  288.  
  289. /* Set bytes, words, and doublewords */
  290. nb=nk*1024;            /* Calc number of bytes */
  291. nw=nb>>1;            /* Calc number of words */
  292. nd=nw>>1;            /* Calc number of dwords */
  293.  
  294. /* Set even/odd boundary */
  295. soff=doff=0;
  296. if((i&1)!=0) soff=doff=1;
  297.  
  298. do {
  299. /* The i variable tells us which test to perform */
  300.     switch(i) {
  301.  
  302.     case 0:        /* Byte wide */
  303.         start_timer();
  304.         do_bmove(seg1,soff,seg2,doff,nb);
  305.         stop_timer(eltime);
  306.         break;
  307.  
  308.     case 1:        /* Word wide odd */
  309.     case 2:        /* Word wide even */
  310.         start_timer();
  311.         do_wmove(seg1,soff,seg2,doff,nw);
  312.         stop_timer(eltime);
  313.         break;
  314.  
  315.     case 3:        /* Dword wide odd */
  316.     case 4:        /* Dword wide even */
  317.         start_timer();
  318.         do_dmove(seg1,soff,seg2,doff,nd);
  319.         stop_timer(eltime);
  320.         break;
  321.  
  322.     default:
  323.         break;
  324.  
  325.     }    /* End of switch */
  326.  
  327.     accumtime(eltime,myactime);
  328.     iters[i]++;
  329. } while(myactime[2]<dotime);
  330.  
  331. acttime[i][0]=myactime[0]; acttime[i][1]=myactime[1];
  332. acttime[i][2]=myactime[2];
  333. return;
  334. }
  335.  
  336. /****************************
  337. *      ifourbang            *
  338. *****************************
  339. ** Integer math tests.
  340. ** Note, n indicates the number of times each 4 operations
  341. ** (add, subtract, multiply, and divide) are performed.
  342. ** Maximum is 8192.
  343. */
  344. ifourbang(winptr, dotime, n, acttime,iters)
  345. win_handle *winptr;        /* current window handlke */
  346. unsigned int dotime;        /* Seconds to perform operations */
  347. unsigned int n;            /* number of operations */
  348. unsigned int acttime[3];    /* Actual elapsed time */
  349. unsigned int *iters;        /* Iterations completed */
  350. {
  351. unsigned int i;            /* Index */
  352. unsigned int rn;        /* Random number */
  353. unsigned int mysegptr;        /* Pointer to working segment */
  354. unsigned int huge *isegptr;    /* Actual pointer to rands */
  355. unsigned int mytime[3];        /* Local for elapsed time */
  356.  
  357.  
  358. /* Clear iterations and actual time */
  359. *iters=0;
  360. acttime[0]=acttime[1]=acttime[2]=0;
  361.  
  362. /* Allocate memory segments for the arrays */
  363. if(allocmem(n/2,&mysegptr)!=-1)
  364.     return;            /* Return if failure */
  365.  
  366. /* Build the random array */
  367. isegptr=MK_FP(mysegptr,0);
  368. i=0;
  369. do {
  370.     if(i==0) *(isegptr+i)=2;
  371.     else *(isegptr+i)=*(isegptr+i-1)+1;
  372.     ++i;
  373.     *(isegptr+i)=*(isegptr+i-1)-1; ++i;
  374.     *(isegptr+i)=*(isegptr+i-1)+2; ++i;
  375.     *(isegptr+i)=*(isegptr+i-1)-1; ++i;
  376. } while(i<(n*4));
  377.  
  378. do {
  379.     start_timer();
  380.  
  381.     do_ifourbang(mysegptr,n);
  382.  
  383.     stop_timer(mytime);
  384.     accumtime(mytime,acttime);
  385.     *iters+=1;
  386.  
  387.     if(winptr!=NULL)
  388.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  389.  
  390. }while(acttime[2]<dotime);
  391.  
  392. /* Free memory segments */
  393. freemem(mysegptr);
  394. }
  395.  
  396. /****************************
  397. *      ffourbang            *
  398. *****************************
  399. ** Floating-point version of ifourbang.
  400. */
  401. ffourbang(winptr,dotime,acttime,iters)
  402. win_handle *winptr;        /* current window handle */
  403. unsigned int dotime;        /* # of seconds to do the test */
  404. unsigned int acttime[3];    /* Actual elapsed time */
  405. unsigned int *iters;        /* # of iterations */
  406. {
  407. unsigned int mytime[3];        /* Local for elapsed time */
  408.  
  409. /* Clear iterations and actual time */
  410. *iters=0;
  411. acttime[0]=acttime[1]=acttime[2]=0;
  412.  
  413. do {
  414.     start_timer();
  415.     do_fourbang(FFITERS);
  416.     stop_timer(mytime);
  417.     accumtime(mytime,acttime);
  418.     *iters+=1;
  419.  
  420.     if(winptr!=NULL)
  421.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  422.  
  423. } while(acttime[2]<dotime);
  424. }
  425.  
  426. /****************************
  427. *       fourier             *
  428. *****************************
  429. ** Calculates fourier coefficients for a square wave.
  430. */
  431. fourier(winptr, dotime,acttime,iters)
  432. win_handle *winptr;        /* current window handle */
  433. unsigned int dotime;        /* Time to do test */
  434. unsigned int acttime[3];    /* Actual elapsed time */
  435. unsigned int *iters;        /* Iterations */
  436. {
  437. double coeffs[NCOEFFS*2];    /* Coefficients array */
  438. unsigned int mytime[3];        /* Local time */
  439.  
  440. /* Clear iterations and actual time */
  441. *iters=0;
  442. acttime[0]=acttime[1]=acttime[2]=0;
  443.  
  444. do{
  445.     start_timer();
  446.     square_fourier(NCOEFFS,coeffs);
  447.     stop_timer(mytime);
  448.     accumtime(mytime,acttime);
  449.     *iters+=1;
  450.  
  451.     if(winptr!=NULL)
  452.         adjust_bar(winptr, acttime[2], dotime);  /* slide the bar */
  453.  
  454. } while(acttime[2]<dotime);
  455. }
  456.  
  457. /****************************
  458. *       textbench           *
  459. *****************************
  460. ** Random text display benchmark (cursor positioning)
  461. ** This routine tests appropriate modes.
  462. */
  463. textbench(dotime,n,avgips)
  464. unsigned int dotime;        /* # of seconds to do the test */
  465. unsigned int n;            /* # of characters to display */
  466. double *avgips;            /* average iterations per second */
  467.  
  468. {
  469. /* Maximum column # */
  470. unsigned int acttime[3][3];    /* Actual elapsed time */
  471. unsigned int iters[3];        /* Iterations */
  472. unsigned int cmax[3]={80,80,80};
  473. unsigned int modes[3]={2,3,7};
  474. unsigned int nummodes;
  475. unsigned int vpage;        /* Video page segment */
  476. unsigned int rcseg;        /* Row/column segment number */
  477. unsigned int attseg;        /* Attributes segment */
  478. int i,j;            /* Indices */
  479. unsigned char far *attsegptr;    /* Far pointer to attribute seg */
  480. unsigned int mytime[3];        /* Local for elapsed time */
  481.  
  482. /* just for looks */
  483. clearscreen();
  484. printf("Preparing text benchmarks ...");
  485.  
  486. /* set modes according to type */
  487.  
  488. switch(machine_config.graphics_type){
  489.     case MDA:
  490.     case HERC:
  491.             nummodes=1;
  492.             modes[0]=7;
  493.             break;
  494.     case CGA:
  495.             nummodes=2;
  496.             break;
  497.     case EGAM:
  498.     case EGAC:
  499.     case VGA:
  500.             nummodes=3;
  501.             break;
  502. }
  503.  
  504. /* Clear all the accumulators */
  505. for(i=0;i<3;i++)
  506. {    iters[i]=0;
  507.     for(j=0;j<3;j++)
  508.     acttime[i][j]=0;
  509. }
  510. /* Allocate the row/column and attributes segments */
  511. if(allocmem(n/8+1,&rcseg)!=-1)
  512.     return;
  513. if(allocmem(n/16+1,&attseg)!=-1)
  514. {    freemem(rcseg);
  515.     return;
  516. }
  517.  
  518. /* Restart the random number generator */
  519. randnum(1L);
  520.  
  521. /* Fill the attributes segment */
  522. attsegptr=MK_FP(attseg,0);
  523. for(i=0;i<n;i++)
  524.     *(attsegptr+i)=(unsigned char)randwc(256L);
  525.  
  526.  
  527. /* Loop through the tests */
  528. clearscreen();
  529. for(i=0;i<nummodes;i++)
  530. {    textbloop(dotime,n,mytime,&iters[i],modes[i],cmax[i],rcseg,attseg);
  531.     acttime[i][0]=mytime[0];
  532.     acttime[i][1]=mytime[1];
  533.     acttime[i][2]=mytime[2];
  534. }
  535.  
  536. /* Clean up after yourself */
  537. freemem(attseg);
  538. freemem(rcseg);
  539.  
  540. /* calculate avgips */
  541.  
  542. *avgips=0;
  543. for(i=0;i<nummodes;i++){
  544.     *(avgips)+=((double)iters[i])/timetodouble(acttime[i]);
  545.     }
  546. *avgips/=nummodes;
  547.  
  548. return;
  549. }
  550.  
  551. /****************************
  552. *       textbloop           *
  553. *****************************
  554. ** Inner loop for the random text benchmark.
  555. */
  556. textbloop(dotime,n,acttime,iters,vmode,cmax,rcseg,attseg)
  557. unsigned int dotime;        /* Max seconds to execute */
  558. unsigned int n;            /* Number of entries */
  559. unsigned int acttime[3];    /* Actual time */
  560. unsigned int *iters;        /* Iterations */
  561. unsigned int vmode;        /* Graphics mode */
  562. unsigned int cmax;        /* Column max */
  563. unsigned int rcseg;        /* Row/column segment */
  564. unsigned int attseg;        /* Attributes segment */
  565. {
  566. unsigned int vpage;        /* Video page segment */
  567. unsigned int far *rcsptr;    /* Pointer to row/col segment */
  568. unsigned int eltime[3];        /* Holding for elapsed time */
  569. unsigned int i;            /* Index */
  570. unsigned int myvmode;        /* Saved video mode */
  571.  
  572. /* just for looks */
  573. printf("Running random text benchmark ...");
  574.  
  575. /* Build far pointer */
  576. rcsptr=MK_FP(rcseg,0);
  577.  
  578. /* Fill up the row/column segment */
  579. for(i=0;i<n;i++)
  580. {    *(rcsptr+i)=(unsigned int)(abs((randwc(25L)<<8))+
  581.         abs(randwc((long)cmax)));
  582. }
  583.  
  584. /* Determine the video page segment */
  585. vpage=0;
  586.  
  587. /* Get the current video mode and save it */
  588. myvmode=gvmode();
  589.  
  590. /* Put the system in the proper video mode */
  591. svmode(vmode);
  592.  
  593. /* Clear accumulators */
  594. *iters=0;
  595. acttime[0]=acttime[1]=acttime[2]=0;
  596.  
  597. /* Do the benchmark */
  598. do {
  599.     start_timer();
  600.     random_text(rcseg,attseg,n,vpage);
  601.     stop_timer(eltime);
  602.     accumtime(eltime,acttime);
  603.     *iters+=1;        /* Bump iterations */
  604.     svmode(vmode);        /* Clear the screen */
  605. } while(acttime[2]<dotime);
  606.  
  607. /* Return the system to original mode */
  608. svmode(myvmode);
  609.  
  610. return;
  611. }
  612.  
  613. /****************************
  614.  *       tscroll             *
  615. *****************************
  616. * Text scrolling benchmark
  617. */
  618. tscroll(dotime,n,avgips)
  619. unsigned int dotime;        /* # of seconds to do each test */
  620. unsigned int n;            /* # of characters to display */
  621. double *avgips;            /* average iterations for modes */
  622. {
  623. /* Maximum column # */
  624. unsigned int acttime[3][3];    /* Actual elapsed time */
  625. unsigned int iters[3];        /* Iterations */
  626. unsigned int cmax[3]={80,80,80};
  627. unsigned int modes[3]={2,3,7};
  628. unsigned int nummodes;
  629. unsigned int rcseg;        /* Row/column/attr segment */
  630. unsigned int i,j;        /* Indices */
  631. unsigned int mytime[3];
  632.  
  633. /* set modes according to type */
  634.  
  635. switch(machine_config.graphics_type){
  636.     case MDA:
  637.     case HERC:
  638.             nummodes=1;
  639.             modes[0]=7;
  640.             break;
  641.     case CGA:
  642.             nummodes=2;
  643.             break;
  644.     case EGAM:
  645.     case EGAC:
  646.     case VGA:
  647.             nummodes=3;
  648.             break;
  649. }
  650.  
  651. /* Clear all the accumulators */
  652. for(i=0;i<3;i++)
  653. {    iters[i]=0;
  654.     for(j=0;j<3;j++)
  655.     acttime[i][j]=0;
  656. }
  657.  
  658. /* Allocate memory for the row/column,attribute segments */
  659. if(allocmem(n*3/8+1,&rcseg)!=-1) return;
  660.  
  661. /* Restart the random number generator */
  662. randnum(1L);
  663.  
  664. /* Loop through the tests */
  665. for(i=0;i<nummodes;i++)
  666. {
  667.     scrolloop(dotime,n,mytime,&iters[i],modes[i],cmax[i],rcseg);
  668.     acttime[i][0]=mytime[0];
  669.     acttime[i][1]=mytime[1];
  670.     acttime[i][2]=mytime[2];
  671. }
  672.  
  673. /* Clean up after yourself */
  674. freemem(rcseg);
  675.  
  676. /* calculate avgips */
  677.  
  678. *avgips=0;
  679. for(i=0;i<nummodes;i++){
  680.     *avgips+=(double)iters[i]/timetodouble(acttime[i]);
  681.     }
  682. *avgips/=nummodes;
  683.  
  684. return;
  685. }
  686.  
  687. /****************************
  688. *       scrolloop           *
  689. *****************************
  690. * Inner loop for the text scroll benchmark.
  691. */
  692. scrolloop(dotime,n,acttime,iters,vmode,cmax,rcseg)
  693. unsigned int dotime;        /* Max seconds to execute */
  694. unsigned int n;            /* Size of rcseg array */
  695. unsigned int acttime[3];    /* Actual elapsed time */
  696. unsigned int *iters;        /* Iterations completed */
  697. unsigned int vmode;        /* Video mode */
  698. unsigned int cmax;        /* Column max */
  699. unsigned int rcseg;        /* Row/column/attribute segment */
  700. {
  701. unsigned int vpage;        /* Video page */
  702. unsigned int far *rcsptr;    /* Pointer to row/column segment */
  703. unsigned int eltime[3];        /* Local for elapsed time */
  704. unsigned int i,j;        /* Indices */
  705. unsigned int myvmode;        /* Local for current video mode */
  706. unsigned int ulr,ulc,lrr,lrc;    /* Corner coordinates for window */
  707.  
  708. /* just for looks */
  709. printf("Running scroll benchmark ...");
  710.  
  711. /* Build the row/column/attributes array */
  712. rcsptr=MK_FP(rcseg,0);
  713. for(i=0;i<n;i++)
  714. {
  715.     j=3*i;
  716.     ulr=(unsigned int)abs(randwc(24L));
  717.     ulc=(unsigned int)abs(randwc((long)(cmax-1)));
  718.     lrr=ulr+(unsigned int)abs(randwc(24L-(long)ulr));
  719.     lrc=ulc+(unsigned int)abs(randwc((long)(cmax-ulc-1)));
  720.     *(rcsptr+j)=(ulr<<8)+ulc;
  721.     *(rcsptr+j+1)=(lrr<<8)+lrc;
  722.     lrc=(unsigned int)abs(randwc(256L));    /* Attributes */
  723.     ulc=(unsigned int)abs(randwc((long)(lrr-ulr+1)));
  724.     *(rcsptr+j+2)=(lrc<<8)+ulc;
  725. }
  726.  
  727. /* Set video page */
  728. vpage=0;
  729.  
  730. /* Get the current video mode */
  731. myvmode=gvmode();
  732.  
  733. /* Put the system in the proper video mode */
  734. svmode(vmode);
  735.  
  736. /* Clear the accumulators */
  737. *iters=0;
  738. acttime[0]=acttime[1]=acttime[2]=0;
  739.  
  740. /* Do the benchmark */
  741. do {
  742.     start_timer();
  743.     scroll_text(rcseg,n>>1,vpage);
  744.     stop_timer(eltime);
  745.     svmode(vmode);        /* Clear display */
  746.     *iters+=1;        /* Bump iterations */
  747.     accumtime(eltime,acttime);
  748. } while(acttime[2]<dotime);
  749.  
  750. /* Return system to original mode */
  751. svmode(myvmode);
  752.  
  753. return;
  754. }
  755.  
  756. /****************************
  757. *     graph_bench           *
  758. *****************************
  759. ** Do the graphics filled-circle benchmark.
  760. ** The results array is a 2-dimensional array that has the following
  761. ** format:
  762. **   results[i][j]        i -> picks a group
  763. **                              j -> picks member of group.
  764. **   Each group is 5 elements big.
  765. **     results[i][0] = mode
  766. **     results[i][1]= # iterations completed
  767. **     results[i][2]= microseconds elapsed
  768. **     results[i][3]= milliseconds elapsed
  769. **     retuslt[i][4]= seconds elapsed
  770. */
  771. graph_bench(dotime, avgips)
  772. unsigned int dotime;        /* Max seconds for each test */
  773. double *avgips;
  774. {
  775. unsigned int results[11][5];    /* Results array */
  776. int i,j;            /* Indices */
  777. int gatype;            /* Graphics adaptor type */
  778. int mvector[11];        /* Mode vector */
  779. int nmodes;            /* Number of modes in vector */
  780. int cx,cy;            /* Center of circle */
  781. int color;            /* Foreground color */
  782. unsigned int esseg;        /* Graphics segment */
  783. unsigned int floodseg;        /* Segment for flood routine */
  784. unsigned int acttime[3];    /* Time accumulator */
  785. unsigned int eltime[3];        /* Elapsed time per loop */
  786. unsigned int iters;        /* Iterations */
  787. int mymode;            /* Storage for current mode */
  788. union REGS myregs;
  789. struct SREGS mysregs;
  790.  
  791. /* Clear results array */
  792. for(i=0;i<11;i++)
  793.     for(j=0;j<5;j++)
  794.         results[i][j]=0;
  795.  
  796. /* Allocate memory for the flood segment (16K should be more
  797. ** than enough) */
  798. if(allocmem(1024,&floodseg)!=-1) return;
  799.  
  800. /* Determine what type of graphics adaptor we've got. */
  801. if((gatype=machine_config.graphics_type)==0) {
  802.     *avgips=0;
  803.     return;
  804.     }
  805.  
  806. /* Load up the modes vector */
  807. build_mvector(gatype,&nmodes,mvector);
  808. if(nmodes==0){
  809.     *avgips=0;
  810.     return;
  811.     }
  812.  
  813. /* Loop through each of the modes in the vector */
  814. for(i=0;i<nmodes;i++)
  815. {
  816.     mymode=gvmode();            /* Get current mode */
  817.     acttime[0]=acttime[1]=acttime[2]=0;    /* Clear acc. time */
  818.     iters=0;
  819.     setup_circle(mvector[i],&cx,&cy,&color,&esseg);
  820.     do {
  821.         svmode(mvector[i]);
  822.         /* If graphics mode 4, set pallette */
  823.         if(mvector[i]==4)
  824.         {
  825.             myregs.h.ah=0x0B;
  826.             myregs.x.bx=257;
  827.             intdosx(&myregs,&myregs,&mysregs);
  828.         }
  829.  
  830.         start_timer();
  831.         circle_fill(cx,cy,color,mvector[i],floodseg,esseg);
  832.         stop_timer(eltime);
  833.         accumtime(eltime,acttime);
  834.         iters++;
  835.     } while(acttime[2]<dotime);
  836.     svmode(mymode);            /* Restore mode */
  837.  
  838. /* Put results into results array */
  839.     results[i][0]=mvector[i];    /* Mode */
  840.     results[i][1]=iters;        /* Iterations */
  841.     results[i][2]=acttime[0];    /* Microseconds */
  842.     results[i][3]=acttime[1];    /* Milliseconds */
  843.     results[i][4]=acttime[2];    /* Seconds */
  844. }
  845.  
  846. /* All done, release the flood segment */
  847. freemem(floodseg);
  848.  
  849. /* calculate avgips */
  850.  
  851. *avgips=0;
  852. for(i=0;i<nmodes;i++){
  853.     *avgips+=(double)results[i][1]/timetodouble(&results[i][2]);
  854.     }
  855. *avgips/=nmodes;
  856.  
  857. return;
  858. }
  859.  
  860. /****************************
  861. *    circle_fill            *
  862. *****************************
  863. * Performs the circle fill algorithm.
  864. */
  865. circle_fill(cx,cy,color,mode,floodseg,esseg)
  866. int cx,cy;        /* Coordinates of center */
  867. int color;        /* Foreground color */
  868. int mode;        /* Graphics mode */
  869. unsigned int floodseg;    /* Segment for flood stack */
  870. unsigned int esseg;    /* Grahics segment */
  871. {
  872. int radius;        /* Circle radius */
  873. int i;            /* Index */
  874.  
  875. radius=8;        /* Starting radius */
  876.  
  877. /* Draw an initial circle */
  878. draw_circle(cx,cy,radius,color,mode,esseg);
  879.  
  880. /* Draw and fill the rest */
  881. for(i=0;i<NUMCIRC;++i) {
  882.     radius+=8;
  883.     draw_circle(cx,cy,radius,color,mode,esseg);
  884.     do_flood(cx+radius-4,cy,color,mode,floodseg,esseg);
  885. }
  886. return;
  887. }
  888.  
  889. /****************************
  890. *    setup_circle           *
  891. *****************************
  892. * Setup variables needed to draw a circle.
  893. */
  894. setup_circle(mode,cx,cy,color,esseg)
  895. int mode;        /* Grahics mode */
  896. int *cx,*cy;        /* Center of circle (returned) */
  897. int *color;        /* Color (returned) */
  898. unsigned int *esseg;    /* ES segment for drawing (returned) */
  899. {
  900.  
  901.     switch(mode) {
  902.  
  903.         case 4:
  904.         case 5:    *cx=160;
  905.             *cy=100;
  906.             *color=3;
  907.             *esseg=0xB800;
  908.             return;
  909.         case 6:    *cx=320;
  910.             *cy=100;
  911.             *color=1;
  912.             *esseg=0xB800;
  913.             return;
  914.         case 13:
  915.             *cx=160;
  916.             *cy=100;
  917.             *color=7;
  918.             *esseg=0xA000;
  919.             return;
  920.         case 14:
  921.             *cx=320;
  922.             *cy=100;
  923.             *color=15;
  924.             *esseg=0xA000;
  925.             return;
  926.         case 15:
  927.             *cx=320;
  928.             *cy=175;
  929.             *color=1;
  930.             *esseg=0xA000;
  931.             return;
  932.         case 16:
  933.             *cx=320;
  934.             *cy=175;
  935.             *color=3;
  936.             *esseg=0xA000;
  937.             return;
  938.         case 17:
  939.         case 18:
  940.             *cx=320;
  941.             *cy=240;
  942.             *color= (mode==17) ? 1 : 15;
  943.             *esseg=0xA000;
  944.             return;
  945.         case 19:
  946.             *cx=160;
  947.             *cy=100;
  948.             *color=15;
  949.             *esseg=0xA000;
  950.             return;
  951.         case 255:
  952.             *cx=360;
  953.             *cy=174;
  954.             *color=1;
  955.             *esseg=0xB000;
  956.             return;
  957.     }
  958. }
  959.  
  960. /****************************
  961. *     build_mvector         *
  962. *****************************
  963. ** Builds a mode vector.
  964. ** Pass in a graphics adaptor type, this routine returns a vector
  965. ** of video modes that the adaptor can support.
  966. */
  967. build_mvector(gatype,n,vector)
  968. int gatype;        /* Graphics adaptor type */
  969. int *n;            /* Returned length of vector */
  970. int vector[];        /* Vector of supported modes */
  971. {
  972. int i;            /* Index */
  973.  
  974. switch(gatype) {
  975.     case 0:            /* NO graphics adaptor! */
  976.         *n=0;
  977.         return;
  978.  
  979.     case 1:            /* VGA */
  980.         vector[0]=4; vector[1]=5; vector[2]=6;
  981.         vector[3]=13; vector[4]=14; vector[5]=15;
  982.         vector[6]=16; vector[7]=17;vector[8]=18;
  983.         vector[9]=19;
  984.         *n=10;
  985.         return;
  986.  
  987.     case 2:            /* EGA enhanced */
  988.         vector[0]=4; vector[1]=5; vector[2]=6;
  989.         vector[3]=13; vector[4]=14;
  990.         vector[5]=16;
  991.         *n=6;
  992.         return;
  993.  
  994.     case 3:            /* CGA */
  995.         vector[0]=4; vector[1]=5; vector[2]=6;
  996.         *n=3;
  997.         return;
  998.  
  999.     case 4:            /* EGA monochrome */
  1000.         vector[0]=6; vector[1]=15;
  1001.         *n=2;
  1002.         return;
  1003.  
  1004.     case 5:            /* Hercules */
  1005.         vector[0]=255;
  1006.         *n=1;
  1007.         return;
  1008.  
  1009.     case 6:            /* MDA */
  1010.     default:
  1011.         *n=0;
  1012.         return;
  1013. }
  1014. }
  1015.  
  1016. /****************************
  1017. *      do_fileio            *
  1018. *****************************
  1019. * Performs the file i/o benchmark.
  1020. */
  1021. do_fileio(winptr,dotime,rbytes,wbytes,accrtime,accwtime,maxbytes)
  1022. win_handle *winptr;        /* current window */
  1023. unsigned int dotime;        /* User-selected time */
  1024. unsigned long *rbytes;        /* Total bytes read */
  1025. unsigned long *wbytes;        /* Total bytes written */
  1026. unsigned int accrtime[3];    /* Accumulated read time */
  1027. unsigned int accwtime[3];    /* Accumulated write time */
  1028. unsigned long maxbytes;        /* Maximum bytes avail */
  1029. {
  1030. unsigned int buffseg;        /* Buffer segment for reading/writing */
  1031. unsigned int i;            /* Index */
  1032. char huge *buffptr;        /* Pointer to buffer */
  1033. unsigned long mymax;        /* My accumulated maximum */
  1034.  
  1035. /* Clear all the results */
  1036. *rbytes=0L;
  1037. *wbytes=0L;
  1038. accrtime[0]=accrtime[1]=accrtime[2]=0;
  1039. accwtime[0]=accwtime[1]=accwtime[2]=0;
  1040.  
  1041. /* Allocate a buffer segment (if you can) */
  1042. if(allocmem(2500+1,&buffseg)!=-1) return;
  1043. buffptr=(char huge *) MK_FP(buffseg,0);
  1044.  
  1045. /* Fill up the memory segment */
  1046. for(i=0;i<40000;i++)
  1047.     *buffptr++='A';
  1048.  
  1049. /* Initialize maximum */
  1050. mymax=0L;
  1051.  
  1052. /* Create the files */
  1053. for (i=0;i<20;i++)
  1054.     kreate(i,buffseg,&mymax);
  1055.  
  1056. /* Extend them */
  1057. for(i=0;i<20;i++)
  1058.     appnd(i,buffseg,&mymax);
  1059.  
  1060. randnum(1L);
  1061.  
  1062. /* Do random i/o */
  1063. random_fio(winptr,dotime,buffseg,rbytes,wbytes,accrtime,accwtime,
  1064.         maxbytes,&mymax);
  1065.  
  1066. /* Clean up after yourself */
  1067. freemem(buffseg);
  1068. for(i=0;i<20;i++)
  1069.     remove(gfname(i));
  1070.  
  1071. return;
  1072. }
  1073.  
  1074. /****************************
  1075. *         kreate            *
  1076. *****************************
  1077. *  Create file n.  Write the assigned number of bytes to
  1078. *  the file and close it.  Accumulate the number of bytes
  1079. *  written and the aggregate time.
  1080. */
  1081. kreate(n,buffseg,mymax)
  1082. int n;                /* File number */
  1083. unsigned int buffseg;        /* Pointer to buffer segment */
  1084. unsigned long *mymax;        /* Bytes written */
  1085. {
  1086. int fh;                /* File handle */
  1087. unsigned int nb;        /* # of bytes to write */
  1088. unsigned int wvector[20]={4000,1000,500,2800,2500,
  1089.             1400,8000,8800,300,21111,
  1090.             2000,6000,200,48800,1300,
  1091.             9870,3000,2816,8660,127};
  1092.  
  1093. /* Open the file */
  1094. fh=ll_create(gfname(n));
  1095. nb=wvector[n];            /* Number of bytes to write */
  1096. ll_seekwrite(fh,0L,0,buffseg,nb);    /* Do the write */
  1097. *mymax+=(unsigned long)nb;    /* Accumulate bytes written */
  1098. ll_close(fh);            /* Close the file */
  1099. return;
  1100. }
  1101.  
  1102. /****************************
  1103. *        appnd              *
  1104. *****************************
  1105. * This routine opens file n and appends the appropriate number of
  1106. * bytes.
  1107. */
  1108. appnd(n,buffseg,mymax)
  1109. int n;                /* File number */
  1110. unsigned int buffseg;        /* Buffer segment */
  1111. unsigned long *mymax;        /* Total bytes written */
  1112. {
  1113. int fh;                /* File handle */
  1114. unsigned int nb;        /* Number of bytes */
  1115. unsigned int wvector[20]={1200,2030,31111,3400,9099,
  1116.             2075,7000,400,2200,2700,
  1117.             2360,1495,5960,3430,70,
  1118.             3600,8900,1233,4000,1000};
  1119.  
  1120. fh=ll_open(gfname(n));        /* Open the file */
  1121. nb=wvector[n];            /* Number of bytes to write */
  1122. ll_seekwrite(fh,0L,2,buffseg,nb);    /* Do the write */
  1123. *mymax+=(unsigned long)nb;    /* Accumulate bytes written */
  1124. ll_close(fh);            /* Close the file */
  1125. return;
  1126. }
  1127.  
  1128. /****************************
  1129. *       random_fio          *
  1130. *****************************
  1131. * This is the random i/o portion of the file i/o benchmark.
  1132. * The routine randomly selects, reads, and writes the 20
  1133. * files.  The system continues the testing until the aggregate
  1134. * time (read and write) exceed the selected time (dotime)
  1135. */
  1136. random_fio(winptr, dotime,buffseg,rbytes,wbytes,accrtime,accwtime,
  1137.         maxbytes,mymax)
  1138. win_handle *winptr;            /* current window */
  1139. unsigned int dotime;            /* User selected time */
  1140. unsigned int buffseg;            /* Read/write buffer segment */
  1141. unsigned long *wbytes;            /* Total bytes written */
  1142. unsigned long *rbytes;            /* Total bytes read */
  1143. unsigned int accwtime[3];        /* Total write-time */
  1144. unsigned int accrtime[3];        /* Total read-time */
  1145. unsigned long maxbytes;            /* Max space avail. */
  1146. unsigned long *mymax;
  1147. {
  1148. int fh;                    /* File handle */
  1149. unsigned long offset;            /* Byte offset */
  1150. unsigned long flen;            /* File length */
  1151. unsigned int eltime[3];            /* Elapsed time */
  1152. unsigned int nb;            /* Number of bytes */
  1153. int n;                    /* File number */
  1154. int i;                    /* Loop index */
  1155. unsigned long avg;            /* Avg. bytes read per loop */
  1156.  
  1157. do {
  1158.     avg=0L;                /* Clear averaging var. */
  1159.  
  1160.     /* For each pass, do 3 reads and 1 write */
  1161.     for(i=0;i<3;i++)
  1162.     {
  1163.         n=(int)abs(randwc(20L));
  1164.         fh=ll_open(gfname(n));
  1165.         flen=ll_filelen(fh);        /* Get file length */
  1166.         offset=abs(randwc(flen));    /* Get random offset */
  1167.         flen=flen-offset;
  1168.         if(flen==0L) ++flen;
  1169.         nb=(flen>32000L) ? 32000 : (unsigned int)flen;
  1170.         nb=(unsigned int)abs(randwc((unsigned long)nb));
  1171.         start_timer();            /* Start timing */
  1172.         ll_seekread(fh,offset,0,buffseg,nb);
  1173.         stop_timer(eltime);
  1174.         accumtime(eltime,accrtime);
  1175.         *rbytes+=(unsigned long)nb;
  1176.         avg+=(unsigned long)nb;
  1177.         ll_close(fh);
  1178.     }
  1179.  
  1180.     n=(int)abs(randwc(20L));        /* No resonance */
  1181.     n=(int)abs(randwc(20L));        /* Pick file */
  1182.     fh=ll_open(gfname(n));
  1183.     flen=ll_filelen(fh);            /* Get file length */
  1184.     offset=abs(randwc(flen));        /* Get random offset */
  1185.     nb=(unsigned int)(avg/3L);
  1186.     if((offset+(unsigned long)nb)>flen)
  1187.     {    *mymax+=((offset+(unsigned long)nb)-flen);
  1188.         if(*mymax>maxbytes) return;
  1189.     }
  1190.     start_timer();                /* Start timing */
  1191.     ll_seekwrite(fh,offset,0,buffseg,nb);    /* Do the write */
  1192.     stop_timer(eltime);            /* Done timing */
  1193.     accumtime(eltime,accwtime);
  1194.     *wbytes+=(unsigned long)nb;
  1195.     ll_close(fh);
  1196.  
  1197.     if(winptr!=NULL)
  1198.         adjust_bar(winptr, accrtime[2]+accwtime[2], dotime); /* bar */
  1199.  
  1200. } while(accrtime[2]+accwtime[2]<dotime);
  1201. return;
  1202.  
  1203. }
  1204.  
  1205. /****************************
  1206. *     gfname                *
  1207. *****************************
  1208. ** For file i/o routines.  Pass this guy and integer between
  1209. ** 0 and 19 and he returns a pointer to a null-terminated string
  1210. ** holding the file's name.
  1211. */
  1212. char *gfname(n)
  1213. int n;            /* Selection number */
  1214. {
  1215. static char fname[20];    /* File name buffer */
  1216.  
  1217. /* Build the name */
  1218. strcpy(fname,"BYTEDAT.");
  1219. itoa(n,fname+8,10);
  1220.  
  1221. return(fname);
  1222. }
  1223.  
  1224. /****************************
  1225. *     ll_diskseek           *
  1226. *****************************
  1227. ** Low level disk seek benchmark (hard disks)
  1228. ** NOTE: This test requires that the throughput test be already
  1229. ** run so that bytes per second is available.
  1230. */
  1231. ll_diskseek(drive,bytespersec,seektime)
  1232. unsigned int drive;        /* Drive number (0=1st hard disk) */
  1233. double bytespersec;        /* Bytes per sec from throughput test */
  1234. double *seektime;        /* Avg seek time */
  1235. {
  1236. unsigned int buffseg;        /* Buffer segment */
  1237. harddiskspecs myhdisk;        /* Hard disk specs */
  1238. unsigned int mytime[3];        /* Local for elapsed time */
  1239. unsigned int i;            /* Index */
  1240. double divisor;
  1241. double transtime;
  1242. double thistime;
  1243.  
  1244.  
  1245. /* Allocate memory segments for the arrays */
  1246. if(allocmem(512/16+1,&buffseg)!=-1)
  1247.     return;
  1248.  
  1249. /* Determine the drive's maximum cylinder number */
  1250. if(get_hdinfo(drive+0x80,&myhdisk)==0)
  1251. {    freemem(buffseg);
  1252.     return;
  1253. }
  1254. divisor=(long)myhdisk.maxcyl*(long)(myhdisk.maxcyl-1);
  1255. transtime=(double)512.0/bytespersec;
  1256. drive +=0x80;                /* Hard disk */
  1257. for(i=1;i<myhdisk.maxcyl;i++)
  1258. {    hd_1seek(drive,0,buffseg);    /* Seek to 0 */
  1259.     start_timer();
  1260.     hd_1seek(drive,i,buffseg);    /* Seek distance=i */
  1261.     stop_timer(mytime);
  1262.     thistime=timetodouble(mytime);    /* Get time */
  1263.     thistime-=transtime;        /* Subtract transfer time */
  1264.     thistime=thistime*((double)(myhdisk.maxcyl-i)/(double)divisor);
  1265.     *(seektime)+=thistime+thistime;    /* Times 2 */
  1266. }
  1267.  
  1268. /* Free memory segments */
  1269. freemem(buffseg);
  1270.  
  1271. return;
  1272. }
  1273.  
  1274. /****************************
  1275. *     ll_hdthru             *
  1276. *****************************
  1277. ** Low level hard disk read throughput.
  1278. */
  1279. ll_hdthru(drive,n,bpersec)
  1280. unsigned int drive;        /* Drive to test */
  1281. unsigned int n;            /* # of iterations to test */
  1282. double *bpersec;        /* Bytes per second transfer */
  1283. {
  1284. unsigned int cysecarrseg;    /* Cylinder/array segment */
  1285. unsigned int buffseg;        /* Buffer segment */
  1286. harddiskspecs myhdisk;        /* Hard disk specs */
  1287. unsigned int far *cysecptr;    /* Far pointer to cyl/sect array */
  1288. unsigned int eltime[3];        /* Local for elapsed time */
  1289. unsigned int seektime1[3];
  1290. unsigned int seektime2[3];
  1291. unsigned int cyl;        /* Cylinder */
  1292. unsigned int sect;        /* Sector */
  1293. unsigned long totbytes;        /* Total bytes */
  1294. unsigned int i;            /* Index */
  1295.  
  1296. /* Clear return value */
  1297. *bpersec=0.0;
  1298.  
  1299. /* Determine the configuration of the hard disk */
  1300. if(get_hdinfo(drive+0x80,&myhdisk)==0)
  1301.     return;
  1302.  
  1303. /* Build the cylinder/sector and # of sectors arrays */
  1304. if(allocmem(n/4+1,&cysecarrseg)!=-1)
  1305.     return;
  1306. cysecptr=MK_FP(cysecarrseg,0);        /* Make a pointer */
  1307. if(allocmem((myhdisk.sectspertrack*512)/16+1,&buffseg)!=-1)
  1308. {    freemem(cysecarrseg);
  1309.     return;
  1310. }
  1311.  
  1312. /* Build arrays for first test */
  1313. randnum(1L);
  1314. i=0;
  1315. totbytes=0L;
  1316. do {
  1317.     cyl=abs((int)randwc((unsigned long)myhdisk.maxcyl));
  1318.     sect=abs((int)randwc((unsigned long)myhdisk.sectspertrack))+1;
  1319.     *(cysecptr+i)=(sect&0x3f)+((cyl&255)<<8)+((cyl&0x300)>>2);
  1320.     ++i;
  1321.     *(cysecptr+i)=myhdisk.sectspertrack-sect+1;
  1322.     totbytes+=(unsigned long)*(cysecptr+i);
  1323. } while(++i<((n*2)-1));
  1324.  
  1325. totbytes=(totbytes-(unsigned long)n)*512L;    /* FIX!!! */
  1326.  
  1327. /* Do first test */
  1328. seektime1[0]=seektime1[1]=seektime1[2]=0;
  1329. start_timer();
  1330. i=hd_rread(drive+0x80,cysecarrseg,buffseg,n);
  1331. stop_timer(eltime);
  1332. if(i!=0) printf("Whoops at %d\n",i);
  1333. accumtime(eltime,seektime1);
  1334.  
  1335. /* Fix up array for second test */
  1336. for(i=0;i<n;i++)
  1337.     *(cysecptr+2*i+1)=1;
  1338.  
  1339. /* Do second test */
  1340. seektime2[0]=seektime2[1]=seektime2[2]=0;
  1341. start_timer();
  1342. i=hd_rread(drive+0x80,cysecarrseg,buffseg,n);
  1343. stop_timer(eltime);
  1344. if(i!=0) printf("2Whoops at %d\n",i);
  1345. accumtime(eltime,seektime2);
  1346.  
  1347. /* Calculate bytes per second */
  1348. *bpersec=(double)totbytes/(timetodouble(seektime1)-timetodouble(seektime2));
  1349.  
  1350. /* Close it up */
  1351. freemem(cysecarrseg);
  1352. freemem(buffseg);
  1353.  
  1354. return;
  1355. }
  1356.  
  1357. /****************************
  1358. *     get_hdinfo            *
  1359. *****************************
  1360. ** Return hard disk information.
  1361. ** Call with:
  1362. **    drive = hard disk number (0x80 is first drive, 0x81 is second)
  1363. ** Returns:
  1364. **    hdinf structure filled with disk information
  1365. **    return value is number of drives connected to first
  1366. **       controller
  1367. */
  1368. int get_hdinfo(drive,hdinf)
  1369. unsigned int drive;    /* Drive to get information on */
  1370. harddiskspecs *hdinf;    /* Structure of hard disk info */
  1371. {
  1372.  
  1373. union REGS inregs, outregs;    /* For talking to the BIOS */
  1374.  
  1375. /* Make the call to INT 13H */
  1376. inregs.h.ah=8;
  1377. inregs.h.dl=drive;
  1378. int86(0x13,&inregs,&outregs);
  1379.  
  1380. /* Pass back results */
  1381. hdinf->maxhead=outregs.h.dh;
  1382. hdinf->maxcyl=outregs.h.ch + ((outregs.h.cl & 0xC0)<<2);
  1383. hdinf->sectspertrack=outregs.h.cl & 0x3F;
  1384.  
  1385. /* Return number of attached drives */
  1386. return((int)outregs.h.dl);
  1387. }
  1388.  
  1389. /****************************
  1390. *     segcopy              *
  1391. *****************************
  1392. * Given two segments, copies n bytes from source to
  1393. * destination.
  1394. */
  1395. segcopy(destin,source,n)
  1396. unsigned int destin;        /* Destination segment */
  1397. unsigned int source;        /* Source segment */
  1398. unsigned int n;        /* Number of bytes */
  1399. {
  1400. char huge *dptr;
  1401. char huge *sptr;
  1402.  
  1403. /* Make some far pointers */
  1404. dptr=MK_FP(destin,0);
  1405. sptr=MK_FP(source,0);
  1406.  
  1407. do {
  1408.     *dptr++=*sptr++;
  1409. } while(--n);
  1410.  
  1411. }
  1412.  
  1413. /****************************
  1414. *     rload_int_seg         *
  1415. *****************************
  1416. ** Load a segment with random integers.
  1417. ** Call with:
  1418. **   rload_int_seg(segptr,n,max)
  1419. ** Where:
  1420. **   segptr = unsigned integer holding the segment
  1421. **   n = number of elements to load the array
  1422. **   max = maximum value (must be unsigned)
  1423. */
  1424. rload_int_seg(segptr,n,max)
  1425. unsigned int segptr;
  1426. unsigned int n;
  1427. int max;
  1428. {
  1429. int huge *mysegptr;    /* For coercion */
  1430. unsigned int i;        /* Index */
  1431.  
  1432. /* Set up my pointer */
  1433. mysegptr=MK_FP(segptr,0);
  1434.  
  1435. /* Loop and load the array */
  1436. for(i=0;i<n;i++)
  1437.     *mysegptr++=(int)randwc((long)max);
  1438. }
  1439.  
  1440. /****************************
  1441. *      accumtime()          *
  1442. *****************************
  1443. ** Accumulate elapsed time.
  1444. ** Call with:
  1445. **   accumtime(eltime,tottime)
  1446. ** Where:
  1447. **   eltime[3] = array of elapsed time to be added to
  1448. **               tottime
  1449. ** Returns:
  1450. **   tottime[3] = total time
  1451. */
  1452. accumtime(eltime,tottime)
  1453. unsigned int eltime[3];        /* Elapsed time */
  1454. unsigned int tottime[3];    /* Total time */
  1455. {
  1456.  
  1457. /* Add in microseconds */
  1458. tottime[0]+=eltime[0];
  1459.  
  1460. /* Handle overflow */
  1461. if(tottime[0]>=1000)
  1462. {    tottime[0]-=1000;
  1463.     tottime[1]+=1;
  1464. }
  1465.  
  1466. /* Add in milliseconds */
  1467. tottime[1]+=eltime[1];
  1468.  
  1469. /* Handle overflow */
  1470. if(tottime[1]>=1000)
  1471. {    tottime[1]-=1000;
  1472.     tottime[2]+=1;
  1473. }
  1474.  
  1475. /* Add in seconds */
  1476. tottime[2]+=eltime[2];
  1477. }
  1478.  
  1479. /****************************
  1480. *         randwc()          *
  1481. *****************************
  1482. ** Returns random modulo num.
  1483. */
  1484. long randwc(num)
  1485. long num;
  1486. {
  1487.     return(randnum(0L)%num);
  1488. }
  1489.  
  1490. /****************************
  1491. *        randnum()          *
  1492. *****************************
  1493. ** Second order linear congruential generator.
  1494. ** Constants suggested by J. G. Skellam.
  1495. ** If val==0, returns next member of sequence.
  1496. **    val!=0, restart generator.
  1497. */
  1498. long randnum(lngval)
  1499. long lngval;
  1500. {
  1501.     register long interm;
  1502.     static long randw[2] = { 13L , 117L };
  1503.  
  1504.     if (lngval!=0L)
  1505.     {    randw[0]=13L; randw[1]=117L; }
  1506.  
  1507.     interm=(randw[0]*254754L+randw[1]*529562L)%999563L;
  1508.     randw[1]=randw[0];
  1509.     randw[0]=interm;
  1510.     return(interm);
  1511. }
  1512.  
  1513. /****************************
  1514. *     timetodouble          *
  1515. *****************************
  1516. * Convert a time array micro, milli, seconds to a floating-point
  1517. * double value.
  1518. */
  1519. double timetodouble(histime)
  1520. unsigned int histime[3];
  1521. {
  1522. double temp;        /* Local for holding time */
  1523.  
  1524.     temp=(double)histime[0];    /* Microseconds */
  1525.     temp=temp/1000.0;
  1526.     temp+=(double)histime[1];    /* Milliseconds */
  1527.     temp=temp/1000.0;
  1528.     temp+=(double)histime[2];    /* Seconds */
  1529.  
  1530.     return(temp);
  1531. }
  1532.  
  1533. void adjust_bar(win_handle *winptr, int curr, int tot)
  1534. /****************************
  1535. **      adjust_bar          *
  1536. *****************************
  1537. **
  1538. **
  1539. ** Colors the sliding bar graph
  1540. */
  1541. {
  1542. double curlen;
  1543. int i;
  1544.  
  1545.     curlen = ((double)curr/tot)*20;
  1546.  
  1547.     curlen=(curlen>20) ? 20: curlen;
  1548.  
  1549.     for(i=oldlen;i< (int) curlen;i++){
  1550.         winputch(winptr, 39+i, 23, 0xb2);
  1551.         if (tdef[13])
  1552.             click();
  1553.         }
  1554.  
  1555.     chattr(winptr, 39, 23, (int) curlen, 1, WHITE, RED);
  1556.  
  1557.     oldlen=curlen;
  1558.     return;
  1559. }
  1560.