home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8710 / 6 < prev    next >
Encoding:
Internet Message Format  |  1990-07-13  |  23.2 KB

  1. Path: uunet!husc6!necntc!ncoast!allbery
  2. From: lee@srs.UUCP (Lee Hasiuk)
  3. Newsgroups: comp.sources.misc
  4. Subject: Sun Multibus to VME Adapter Switch Setting Program
  5. Message-ID: <4845@ncoast.UUCP>
  6. Date: 13 Oct 87 02:42:08 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Lines: 768
  9. Approved: allbery@ncoast.UUCP
  10. X-Archive: comp.sources.misc/8710/6
  11.  
  12. I have written a program (enclosed) which will hopefully make it much
  13. easier for those of you faced with having to set up Sun VME to Multibus
  14. adapters.  The program is called vme2mb and takes as arguments a
  15. description of your device and outputs a complete list of switch
  16. settings.
  17.  
  18. Enjoy!
  19.  
  20. Lee Hasiuk
  21. Speech Recognition Systems
  22. Rochester, NY
  23. {rutgers, ames, allegra}!rochester!srs!lee
  24.  
  25. #!/bin/sh
  26. #
  27. # shar archiver, delete everything above the #!/bin/sh line
  28. # and run through sh (not csh)
  29. #
  30. echo 'shar: extracting "vme2mb.doc" (4755 characters)'
  31. # 'vme2mb.doc' has a checksum of 54470 on BSD and 51163 on System V.
  32. sed 's/^X//' > vme2mb.doc << 'XXX_EOF_XXX'
  33. Xvme2mb- Determine switch settings for a Sun VME to Multibus adapter
  34. X
  35. XSYNOPSIS
  36. X
  37. Xvme2mb {-m addr,size} {-i addr,size} {-v vec} {-d 20/24} {-o offset}
  38. X
  39. XDESCRIPTION
  40. X
  41. XGiven a description of a device in Multibus address space, produce switch
  42. Xsettings for a Sun Microsystems VME to Multibus Adapter part # 501-1054.
  43. XThe settings are output in an order which is helpful when setting up the
  44. Xboard.  If the board is oriented as follows (looking at the component side):
  45. X
  46. X            (TOP)
  47. X---------------      ------------------     ----------------
  48. X| VMEbus P1   |      |   VMEbus P2    |     |  VMEbus P3   |
  49. X------------------------------------------------------------
  50. X|                      DIP2   DIP10                        |
  51. X|        DIP8   DIP6                                       |
  52. X|               DIP1   DIP9                         |
  53. X|        DIP7   DIP5                                       |
  54. X|                                                          |
  55. X|                      DIP3                                |
  56. X| DIP12  DIP11  DIP4                                       |
  57. X------------------------------------------------------------
  58. X|     Mutilbus P2     |   |          Multibus P1           |   
  59. X-----------------------   ----------------------------------
  60. X              (BOTTOM)
  61. X
  62. Xthe switch settings are output starting from the left, going
  63. Xdown each column from top to bottom until the bottom of the right hand
  64. Xcolumn is reached.
  65. X
  66. XOPTIONS
  67. X
  68. XAll numbers supplied to the program may be in decimal or hexadecimal notation.
  69. XHexadecimal numbers must be preceeded by 0x or 0X.
  70. X
  71. X-m addr,size
  72. XDefault: no memory address response
  73. X
  74. XSets the memory address space response of the board.  'addr' is the base
  75. Xaddress, and 'size' is the number of bytes which your device uses, starting
  76. Xat the given address.  'size' will be rounded up to 256 or the closest power
  77. Xof two, whichever is greater, due to the implementation of the adapter board.
  78. XMay be used with -i option below for boards with both memory and I/O response.
  79. X
  80. X-i addr,size
  81. XDefault: no I/O address response
  82. X
  83. XSets the I/O address space response of the board.  'addr' is the base
  84. Xaddress, and 'size' is the number of bytes which your device uses, starting
  85. Xat the given address.  'size' will be rounded up to the closest non-zero
  86. Xpower of two, due to the implementation of the adapter board.
  87. XMay be used with -m option above for boards with both memory and I/O response.
  88. X
  89. X-v vec
  90. XDefault: interrupt vector assumed to be in PROM
  91. X
  92. XSets the interrupt vector which is generated when the Multibus board requests
  93. Xan interrupt at any level.  If the vector is not specified, the board is
  94. Xsetup so that none of the vector switches are set.  This is the proper setting
  95. Xwhen interrupt vectors are stored in a PROM supplied by the user.
  96. X
  97. X-d 20/24
  98. XDefault: -d 20
  99. X
  100. XSets the number of bits that your Multibus board supplies when doing DMA
  101. Xtransfers to the VMEbus.  The only legal values for this parameter are 20
  102. Xor 24 (or 0x14/0x18).  BEWARE: Some Sun boards that would appear to be
  103. X24 bit DMA devices will not work when they pass all 24 bits.  The
  104. XXylogics 472 tape controller (xtc0) comes to mind as having this problem.
  105. X24 bit DMA isn't necessary unless you expect your board to transfer data
  106. Xdirectly to another VMEbus device.
  107. X
  108. X-o off
  109. XDefault: -o 0x000000
  110. X
  111. XSets the DMA offset when setting up a 20 bit (-d 20) DMA device to do
  112. XDMA to other than the Sun DVMA space.  Only the top 4 bits of the supplied
  113. X24 bit value are used, the other bits must be zero.  It is extremely rare
  114. Xfor a device to require the use of this parameter.
  115. X
  116. XOUTPUT
  117. X
  118. XThe output is a list of all the dip switches on the board, with the settings
  119. Xfor each section of each switch.  Each switch has 8 sections which can either
  120. Xbe ON (switch up if board held in above orientation), OFF (switch down),
  121. Xor X.  X means that it doesn't matter which way the switch is set.
  122. X
  123. XEXAMPLES
  124. X
  125. XHere are a few vme2mb command lines for various well-known Sun devices:
  126. X
  127. X1) Xylogics 450 disk controller
  128. X   Address space: Multibus I/O
  129. X   Base address: 0xee40
  130. X   Size: 6 bytes (rounded to 8)
  131. X   Vector: 0x48
  132. X   DMA address provided: 24 bits
  133. X
  134. X   vme2mb -i 0xee40,8 -v 0x48 -d 24
  135. X
  136. X2) Tapemaster 1/2 inch tape controller
  137. X   Address space: Multibus I/O
  138. X   Base address: 0x60
  139. X   Size: 2 bytes
  140. X   Vector: 0x60
  141. X   DMA address provided: 20 bits
  142. X
  143. X   vme2mb -i 0x60,2 -v 0x60
  144. X
  145. XSEE ALSO
  146. X
  147. XSun VME-Multibus Adapter Board User's Manual
  148. XPart Number 800-1193-05
  149. XRevision: A of 25 September 1986
  150. X
  151. XBEWARE of earlier revisions (also labelled A, but with earlier dates),
  152. Xthey contain incorrect information about setting up the DMA dip switch!
  153. X
  154. XTRADEMARKS
  155. X
  156. XMultibus is a trademark of Intel Corporation
  157. X
  158. XSun, Sun Microsystems, Sun Workstation, and DVMA are registered trademarks
  159. Xof Sun Microsystems, Incorporated.
  160. XXX_EOF_XXX
  161. if test 4755 -ne "`wc -c < vme2mb.doc`"
  162. then
  163.     echo 'shar: transmission error on "vme2mb.doc"'
  164. fi
  165. chk=`sum vme2mb.doc | awk '{print $1}'`
  166. if test 54470 -ne $chk -a 51163 -ne $chk
  167. then
  168.     echo 'shar: checksum error on "vme2mb.doc"'
  169. fi
  170. echo 'shar: extracting "Makefile" (40 characters)'
  171. # 'Makefile' has a checksum of 46411 on BSD and 3199 on System V.
  172. sed 's/^X//' > Makefile << 'XXX_EOF_XXX'
  173. Xvme2mb: vme2mb.c
  174. X    cc -o vme2mb vme2mb.c
  175. XXX_EOF_XXX
  176. if test 40 -ne "`wc -c < Makefile`"
  177. then
  178.     echo 'shar: transmission error on "Makefile"'
  179. fi
  180. chk=`sum Makefile | awk '{print $1}'`
  181. if test 46411 -ne $chk -a 3199 -ne $chk
  182. then
  183.     echo 'shar: checksum error on "Makefile"'
  184. fi
  185. echo 'shar: extracting "vme2mb.c" (16196 characters)'
  186. # 'vme2mb.c' has a checksum of 51222 on BSD and 40552 on System V.
  187. sed 's/^X//' > vme2mb.c << 'XXX_EOF_XXX'
  188. X#ifndef lint
  189. Xstatic char sccsId[] = "@(#)vme2mb.c    1.1 9/30/87 SRS";
  190. X#endif
  191. X
  192. X/*
  193. X * Produce switch settings for a Sun VME to Multibus adapter.
  194. X *
  195. X * Lee Hasiuk
  196. X * Speech Recognition Systems
  197. X * 1895 Mt. Hope Ave.
  198. X * Rochester, NY 14620
  199. X * (716) 271-0600
  200. X *
  201. X */
  202. X
  203. X#include <stdio.h>
  204. X#include <strings.h>
  205. X#include <ctype.h>
  206. X
  207. Xtypedef short boolean;
  208. X
  209. X#define FALSE 0
  210. X#define TRUE 1
  211. X#define DONTCARE -1
  212. X
  213. X#define NSW 8            /* # of switches in a dip switch */
  214. X#define NDIP (12 + 1)        /* # of dip switches on board, 0 not used */
  215. X
  216. X/* 
  217. X * Structure defining a dip switch; sense is TRUE if a switch is ON for a 1
  218. X * or FALSE is switch is ON for a 0.  Bits is an array with one element for
  219. X * each section of a dip switch.  The value stored in element i of bits is
  220. X * the bit number (0 = LSB, 31 = MSB) which the i+1th section of the dip
  221. X * switch is set for.  For example, if sense was FALSE and bits[0]
  222. X * was 23, section 1 of the dip switch would be ON if bit 23 of the number
  223. X * being used to set it was 0.  The meaning of the number being used to set 
  224. X * the dip switch varies with the dip switch.  If bits[n] is -1, the
  225. X * n+1th section of the dip switch is not bit specific, and may be 
  226. X * either a don't care or be used in some other way.
  227. X */
  228. Xtypedef struct {
  229. X    boolean sense;        
  230. X    short bits[NSW];
  231. X} dipSw;
  232. X
  233. X/* The board's switches and their meanings */
  234. X#define X DONTCARE
  235. Xstatic dipSw dips[] = {
  236. X        /* 1   2   3   4   5   6   7   8  - section number of switch */
  237. X    { FALSE,   X,  X,  X,  X,  X,  X,  X,  X },        /* DIP0 - not real */
  238. X    { FALSE,   X,  7,  6,  5,  4,  3,  2,  1 },        /* DIP1 */
  239. X    { FALSE,   X,  7,  6,  5,  4,  3,  2,  1 },        /* DIP2 */
  240. X    { FALSE,  15, 14, 13, 12, 11, 10,  9,  8 },        /* DIP3 */
  241. X    { FALSE,  15, 14, 13, 12, 11, 10,  9,  8 },        /* DIP4 */
  242. X    { FALSE,  15, 14, 13, 12, 11, 10,  9,  8 },        /* DIP5 */
  243. X    { FALSE,  15, 14, 13, 12, 11, 10,  9,  8 },        /* DIP6 */
  244. X    { FALSE,  23, 22, 21, 20, 19, 18, 17, 16 },        /* DIP7 */
  245. X    { FALSE,  23, 22, 21, 20, 19, 18, 17, 16 },        /* DIP8 */
  246. X    {  TRUE,   0,  0,  0,  0,  0,  0,  0,  0 },        /* DIP9 */
  247. X    {  TRUE,   0,  0,  0,  0,  0,  0,  0,  0 },        /* DIP10 */
  248. X    {  TRUE,  23, 22, 21, 20,  X,  X,  X,  X },        /* DIP11 */
  249. X    { FALSE,   0,  1,  2,  3,  4,  5,  6,  7 },        /* DIP12 */
  250. X};
  251. X#undef X
  252. X
  253. X/* 
  254. X * Order that switch settings will be listed.  Looking at component side
  255. X * of board, with VME connectors farthest from you, we go top to bottom,
  256. X * and left to right.
  257. X *                    (TOP)
  258. X * ---------------      ------------------     ----------------
  259. X * | VMEbus P1   |      |   VMEbus P2    |     |  VMEbus P3   |
  260. X * ------------------------------------------------------------
  261. X * |                      DIP2   DIP10                        |
  262. X * |        DIP8   DIP6                                       |
  263. X * |                  DIP1   DIP9                         |
  264. X * |        DIP7   DIP5                                       |
  265. X * |                                                          |
  266. X * |                      DIP3                                |
  267. X * | DIP12  DIP11  DIP4                                       |
  268. X * ------------------------------------------------------------
  269. X * |     Mutilbus P2     |   |          Multibus P1           |   
  270. X * -----------------------   ----------------------------------
  271. X *                          (BOTTOM)
  272. X */
  273. Xstatic int dumpOrder[] = { 12, 8, 7, 11, 6, 5, 4, 2, 1, 3, 10, 9 };
  274. X
  275. Xmain(argc, argv)
  276. Xint argc;
  277. Xchar *argv[];
  278. X{
  279. X    static long memDescr[2] = {0, 0};
  280. X    static long ioDescr[2] = {0, 0};
  281. X    long intVec = -1;    /* If no vector supplied, may be PROMed, switches off */
  282. X    long dmaSize = 20;  /* Default to 20 bit addressing; a must for xt0 */
  283. X    long dmaOff = 0;    /* DMA offset is usually 0 - DVMA space */
  284. X    boolean set[NDIP][NSW]; /* Settings go here */
  285. X    char opt;
  286. X    extern char *optarg;
  287. X    extern int opterr;
  288. X
  289. X    /* Though we could run with no args, they probably want a usage message */
  290. X    if (argc < 2)
  291. X    usage();
  292. X
  293. X    opterr = 0;
  294. X    while ((opt = getopt(argc, argv, "m:i:v:d:o:")) != EOF) {
  295. X    switch (opt) {
  296. X    case 'm':
  297. X
  298. X        /* Multibus memory space specified, 2 numbers to parse */
  299. X        getVals(optarg, memDescr, 2);
  300. X        break;
  301. X    case 'i':
  302. X
  303. X        /* Multibus i/o space specified, 2 numbers to parse */
  304. X        getVals(optarg, ioDescr, 2);
  305. X        break;
  306. X    case 'v':
  307. X
  308. X        /* Interrupt vector supplied, 1 number to parse */
  309. X        getVals(optarg, &intVec, 1);
  310. X        break;
  311. X    case 'd':
  312. X    
  313. X        /* DMA type specified, 1 number to parse */
  314. X        getVals(optarg, &dmaSize, 1);
  315. X        break;
  316. X    case 'o':
  317. X
  318. X        /* DMA offset specified, 1 number to parse */
  319. X        getVals(optarg, &dmaOff, 1);
  320. X        break;
  321. X    default:
  322. X
  323. X        /* Huh ? */
  324. X        usage();
  325. X    }
  326. X    }
  327. X
  328. X    /* Given their parameters, set up the switches */
  329. X    vme2mb(dips, set, memDescr, ioDescr, intVec, dmaSize, dmaOff);
  330. X
  331. X    /* Now print out the mess - somebody want to add graphics? */
  332. X    showSettings(set, NDIP - 1, dumpOrder);
  333. X
  334. X    exit(0);
  335. X}
  336. X
  337. X/*
  338. X * Give a usage message and leave.
  339. X */
  340. Xstatic
  341. Xusage()
  342. X{
  343. X    (void)fprintf(stderr, "\
  344. XUsage: vme2mb {-m addr,size} {-i addr,size} {-v vec} {-d 20/24} {-o offset}\n");
  345. X    exit(1);
  346. X}
  347. X
  348. X/*
  349. X * Given a set of switches, and the board's parameters, set up switches
  350. X * as specified by the parameters.  Output goes into an array which
  351. X * is index by [switch #][section # - 1] and a FALSE indicates an off,
  352. X * TRUE an ON, and DONTCARE can be either.
  353. X */
  354. Xstatic
  355. Xvme2mb(dips, set, mem, io, vec, dsiz, doff)
  356. XdipSw dips[];
  357. Xboolean set[][NSW];
  358. Xlong mem[], io[], vec, dsiz, doff;
  359. X{
  360. X
  361. X    /* Set up mem space switches; dip 8 & 6 are blksize (min 256), 7 & 5 base */
  362. X    doAddrSpace(mem, (long) 256, dips, set, 8, 6, 7, 5);
  363. X
  364. X    /* Set up io space; dip 4 & 2 are blocksize (min 2), 3 & 1 base */
  365. X    doAddrSpace(io, (long) 2, dips, set, 4, 2, 3, 1);
  366. X
  367. X    /* Set up interrupt vector in dip 12 */
  368. X    doIntVec(vec, dips, set, 12);
  369. X
  370. X    /* Set up dma in dip 11 */
  371. X    doDma(dsiz, doff, dips, set, 11);
  372. X
  373. X    /* Dip 9 and 10 are unused, usually set to all off */
  374. X    setSw((long) 0, &dips[9], set[9]);
  375. X    setSw((long) 0, &dips[10], set[10]);
  376. X}
  377. X
  378. X/*
  379. X * Given 20 or 24 bit DMA size and possibly a 24 bit offset, set up
  380. X * the DMA dip switch.
  381. X */
  382. Xstatic
  383. XdoDma(dsiz, doff, dip, set, sw)
  384. Xlong dsiz, doff;    /* DMA size (20 or 24) and offset */
  385. XdipSw dip[];        /* DIP switch descriptions */
  386. Xshort set[][NSW];    /* Where the settings go */
  387. Xint sw;            /* Switch to set */
  388. X{
  389. X
  390. X    /* 20 bit DMA ? */
  391. X    if (dsiz == 20) {
  392. X
  393. X    /* Offset can only have bits set in MSN of 24 bit address */
  394. X    if ((doff & 0x0fffff) != 0)
  395. X        err("Only bits 23-20 of DMA offset may be used", (char *) 0);
  396. X
  397. X    /* Set offset switches */
  398. X    setSw(doff, &dip[sw], set[sw]);
  399. X
  400. X    /* Force sections 5-8 off; no 24 bit address supplied by Multibus bd */
  401. X    forceSw(set[sw], 5, FALSE);
  402. X    forceSw(set[sw], 6, FALSE);
  403. X    forceSw(set[sw], 7, FALSE);
  404. X    forceSw(set[sw], 8, FALSE);
  405. X    }
  406. X
  407. X    /* 24 bit DMA ? */
  408. X    else if (dsiz == 24) {
  409. X
  410. X    /* No offset allowed */
  411. X    if (doff != 0)
  412. X        err("Can't use DMA offset with 24 bit DMA", (char *) 0);
  413. X
  414. X    /* Switches are 1-4 off, 5-8 on to pass high bits unaltered */
  415. X    forceSw(set[sw], 1, FALSE);
  416. X    forceSw(set[sw], 2, FALSE);
  417. X    forceSw(set[sw], 3, FALSE);
  418. X    forceSw(set[sw], 4, FALSE);
  419. X    forceSw(set[sw], 5, TRUE);
  420. X    forceSw(set[sw], 6, TRUE);
  421. X    forceSw(set[sw], 7, TRUE);
  422. X    forceSw(set[sw], 8, TRUE);
  423. X    }
  424. X    else
  425. X
  426. X    /* Unknown DMA request */
  427. X    err("DMA size must be either 20 or 24", (char *) 0);
  428. X}
  429. X
  430. X/*
  431. X * Set up the dip switch used for interrupt vector generation.  Should be
  432. X * passed a -1 for vec if no vector is supplied by user; this forces all
  433. X * switch sections off, we is the way we would be if user provided a PROM
  434. X * for interrupt vector generation.
  435. X */
  436. Xstatic
  437. XdoIntVec(vec, dip, set, sw)
  438. Xlong vec;        /* Interrupt vector */
  439. XdipSw dip[];        /* DIP switch descriptions */
  440. Xshort set[][NSW];    /* Where the settings go */
  441. Xint sw;            /* Switch # to set */
  442. X{
  443. X
  444. X    /* Classic switch; just set it and return */
  445. X    setSw(vec, &dip[sw], set[sw]);
  446. X}
  447. X
  448. X/*
  449. X * Set up switches for an address space;  address spaces are specified by
  450. X * a two element array, the 0th element being the base address, and the 
  451. X * next element the size.  Four switches are provided for setting; two
  452. X * for the block size (order unimportant) and two for the base address
  453. X * (order also unimportant).  If the block size is 0, the switch is set
  454. X * for no response in that address space.  If block size is less than
  455. X * minimum, it is set to minimum.  If it isn't a power of two, it is
  456. X * rounded to the next highest power of two.
  457. X */
  458. Xstatic
  459. XdoAddrSpace(space, minblk, dip, set, block1, block2, addr1, addr2)
  460. Xlong space[];        /* Adress space description */
  461. Xlong minblk;        /* Minimum blocksize allowed */
  462. XdipSw dip[];        /* DIP switch descriptions */
  463. Xshort set[][NSW];    /* Where the settings go */
  464. Xint block1, block2;    /* Switches for block size */
  465. Xint addr1, addr2;     /* Switches for base address */
  466. X{
  467. X
  468. X    /* Does board use this space ? */
  469. X    if (space[1] != 0) {
  470. X
  471. X    /* Yes, make the block size a power of two, at least minblk */
  472. X    makeValidBlockSize(&space[1], minblk);
  473. X
  474. X    /* Set the block size switches */
  475. X    doBlockSize(space[1], &dip[block1], set[block1]);
  476. X    doBlockSize(space[1], &dip[block2], set[block2]);
  477. X
  478. X    /* Set the base address switches */
  479. X    doBaseAddr(space[0], space[1], &dip[addr1], set[addr1]);
  480. X    doBaseAddr(space[0], space[1], &dip[addr2], set[addr2]);
  481. X    }
  482. X    else {
  483. X
  484. X    /* Address space not used, set switches for no response */
  485. X    setSw((long) -1, &dip[block1], set[block1]);
  486. X    setSw((long) -1, &dip[block2], set[block2]);
  487. X    setSw((long) 0, &dip[addr1], set[addr1]);
  488. X    setSw((long) 0, &dip[addr2], set[addr2]);
  489. X    }
  490. X}
  491. X
  492. X/*
  493. X * Apply the algorithm for converting a block size to a number that the
  494. X * switch setter can use.  The goal is to covert a number with a single
  495. X * bit set (a legal block size) to a number with all of the bits that
  496. X * are less than that bit set, and the original bit not set.  Sounds
  497. X * like subtracting 1, doesn't it?
  498. X */
  499. Xstatic 
  500. XdoBlockSize(size, dipswp, settings) 
  501. Xlong size; 
  502. XdipSw *dipswp;
  503. Xboolean settings[];
  504. X{
  505. X
  506. X    /* Apply the 'algorithm' */
  507. X    size -= 1;
  508. X
  509. X    /* Set the switches */
  510. X    setSw(size, dipswp, settings);
  511. X}
  512. X
  513. X/*
  514. X * Apply the algorithm for converting a block size and a base address
  515. X * to a number that the switch setter can use.  The goal is to take the
  516. X * blocksize (with one bit set), subtract one from it (thus setting
  517. X * bits lower than the one set), then or'ing this number with the
  518. X * base address.
  519. X */
  520. Xstatic 
  521. XdoBaseAddr(base, size, dipswp, settings)
  522. Xlong base, size;
  523. XdipSw *dipswp;
  524. Xboolean settings[];
  525. X{
  526. X    /* Apply the 'algorithm' */
  527. X    base |= size - 1;
  528. X
  529. X    /* Set the switches */
  530. X    setSw(base, dipswp, settings);
  531. X}
  532. X
  533. X/*
  534. X * Print out the dip switch settings in the order specified by an array of
  535. X * ints indexing into the setting array.
  536. X */
  537. XshowSettings(set, nset, order)
  538. Xboolean set[][NSW];
  539. Xint nset;
  540. Xint order[];
  541. X{
  542. X    int i;
  543. X
  544. X    for (i = 0; i < nset; i++)
  545. X    dumpSw(set, order[i]);
  546. X}
  547. X
  548. X/*
  549. X * Given a switch number and the settings; print out the settings for
  550. X * that switch.
  551. X */
  552. Xstatic
  553. XdumpSw(set, sw)
  554. Xboolean set[][NSW];    /* The array of switch settings */
  555. Xint sw;            /* Switch # to be displayed */
  556. X{
  557. X    int i;
  558. X
  559. X    (void)printf("DIP%-2d: ", sw);
  560. X    for (i = 0; i < NSW; i++) {
  561. X    if (set[sw][i] == TRUE)
  562. X        (void)printf("%d ON   ", i + 1);
  563. X    else if (set[sw][i] == FALSE)
  564. X        (void)printf("%d OFF  ", i + 1);
  565. X    else
  566. X        (void)printf("%d X    ", i + 1);
  567. X    }
  568. X    (void)printf("\n");
  569. X}
  570. X
  571. X/*
  572. X * Force a section of an already chosen DIP switch to a particular
  573. X * (ON, OFF, DONTCARE) value.  The section number is 1 through 8,
  574. X * but the setting array is indexed 0 through 7.
  575. X */
  576. Xstatic 
  577. XforceSw(settings, sw, how)
  578. Xboolean settings[];
  579. Xint sw;
  580. Xboolean how;
  581. X{
  582. X
  583. X    /* Force the setting */
  584. X    settings[sw - 1] = how;
  585. X}
  586. X
  587. X/*
  588. X * Given a number and a description of how a dip switch is set (based on
  589. X * which sections are affected by which bits of the number), set the dip
  590. X * switch by putting the states of the switches in an array.
  591. X */
  592. Xstatic
  593. XsetSw(val, dipswp, settings)
  594. Xlong val;        /* Value to set in the switches */
  595. XdipSw *dipswp;        /* Description of this switch */
  596. Xboolean settings[];    /* Where the settings go */
  597. X{
  598. X    int i;
  599. X    short bit;
  600. X
  601. X    /* Go through each section of the switch */
  602. X    for (i = 0; i < NSW; i++) {
  603. X
  604. X    /* Is this position used (!= DONTCARE) ? */
  605. X    if ((bit = dipswp->bits[i]) != DONTCARE) {
  606. X
  607. X        /* Position used, is corresponding bit set in the input value? */
  608. X        if (val & (1 << bit))
  609. X
  610. X        /* Bit set, set the switch according to its sense */
  611. X        settings[i] = dipswp->sense;
  612. X        else
  613. X
  614. X        /* Bit not set, set the switch opposite to its sense */
  615. X        settings[i] = !dipswp->sense;
  616. X    }
  617. X    else
  618. X
  619. X        /* Position not used, switch is a don't care, for now */
  620. X        settings[i] = DONTCARE;
  621. X    }
  622. X}
  623. X
  624. X/*
  625. X * Convert a potential block size for a device into a valid one.  This
  626. X * involves making sure that it is at least a minimum value (smallest that
  627. X * can be set with the switches) and a power of 2.  If either does not hold,
  628. X * the block size is rounded up and a warning sent to stderr.
  629. X */
  630. Xstatic
  631. XmakeValidBlockSize(valp, minval)
  632. Xlong *valp;        /* Pointer to number to be made valid */
  633. Xlong minval;        /* Minimum block size allowable */
  634. X{
  635. X    long val = *valp;
  636. X    int highest, lowest, i;
  637. X
  638. X    /* Block size must be at least minval */
  639. X    if (val < minval) {
  640. X
  641. X    /* It wasn't; print a warning, set it to minimum and return */
  642. X    (void)fprintf(stderr, 
  643. X              "Set blocksize of %ld to minimum allowable of %ld\n",
  644. X              val, minval);
  645. X    *valp = minval;
  646. X    return;
  647. X    }
  648. X
  649. X    /* Find the highest bit set; and ensure that it's also the lowest */
  650. X    highest = lowest = 0;
  651. X
  652. X    /* Cycle through the bits */
  653. X    for (i = 1; i <= 32; i++) {
  654. X
  655. X    /* Bit set ? */
  656. X    if (val & 1) {
  657. X
  658. X        /* Bit is set, has lowest been detected ? */
  659. X        if (lowest == 0)
  660. X
  661. X        /* No, this is the lowest bit */
  662. X        lowest = i;
  663. X
  664. X        /* Bit is set, may be highest bit */
  665. X        highest = i;
  666. X    }
  667. X
  668. X    /* Get to next bit */
  669. X    val >>= 1;
  670. X    }
  671. X
  672. X    /* Are highest and lowest the same bit ? */
  673. X    if (highest != lowest) {
  674. X
  675. X    /* No, round up, print warning and return */
  676. X    val = 1 << highest;
  677. X    (void)fprintf(stderr, "Blocksize of %ld rounded up to %ld\n", 
  678. X              *valp, val);
  679. X    *valp = val;
  680. X    }
  681. X}
  682. X
  683. X/* 
  684. X * Print an error message with possibly one string argument.  Exit with
  685. X * non-zero status.
  686. X */
  687. Xstatic 
  688. Xerr(fmt, param)
  689. Xchar *fmt, *param;
  690. X{
  691. X    (void)fprintf(stderr, fmt, param);
  692. X    (void)fprintf(stderr, "\n");
  693. X    exit(1);
  694. X}
  695. X
  696. X/*
  697. X * Given a string containing numbers in hex or decimal format, an array
  698. X * to place their binary values in and a count, parse the string.  The
  699. X * numbers are separated by commas.
  700. X */
  701. Xstatic
  702. XgetVals(str, vals, count)
  703. Xchar *str;        /* String containing the numbers */
  704. Xlong *vals;        /* Array to place the values in */
  705. Xint count;        /* Number of values to be parsed */
  706. X{
  707. X    long numParse();
  708. X    char *p, *strtok();
  709. X    char buf[255];
  710. X
  711. X    /* Make a copy of the string, since strtok() will trash it */
  712. X    (void)strcpy(buf, str);
  713. X
  714. X    /* Parse it based on commas as separators */
  715. X    p = strtok(buf, ",");
  716. X
  717. X    /* Cycle until end of string or we get all that we want */
  718. X    while (p && count--) {
  719. X
  720. X    /* Extract the value, place it in the array */
  721. X    *vals++ = numParse(p);
  722. X
  723. X    /* Advance to next possible number */
  724. X    p = strtok((char *) 0, ",");
  725. X    }
  726. X
  727. X    /* If we didn't parse the whole string, or didn't get all the values we
  728. X       need, perhaps the user doesn't understand how we work */
  729. X    if (p || count)
  730. X    usage();
  731. X}
  732. X
  733. X/*
  734. X * Take a string, and extract either a hexadecimal or decimal number from it.
  735. X * It is a fatal error if we can't get either.
  736. X * Returns the value.
  737. X */
  738. Xstatic long
  739. XnumParse(str)
  740. Xchar *str;
  741. X{
  742. X    long scanval;
  743. X    char foo[255];
  744. X
  745. X    /* Convert upper case to lower case (to parse 0x) */
  746. X    lcase(str);
  747. X
  748. X    /* Scanf parsing; number may be hex, with no garbage afterward */
  749. X    if (sscanf(str, "0x%lx%[^\1-\127]", &scanval, foo) == 1 ||
  750. X
  751. X    /* Or decimal, again with no garbage */
  752. X        sscanf(str, "%ld%[^\1-\127]", &scanval, foo) == 1)
  753. X        return(scanval);
  754. X
  755. X    /* Didn't grok it */
  756. X    err("Cannot parse number: %s", str);
  757. X    /*NOTREACHED*/
  758. X}
  759. X
  760. X/*
  761. X * Convert upper case characters in a string to lower case.
  762. X */
  763. Xlcase(p)
  764. Xchar *p;
  765. X{
  766. X    for (; *p != '\0'; p++)
  767. X    if (isupper(*p))
  768. X        *p = tolower(*p);
  769. X}
  770. XXX_EOF_XXX
  771. if test 16196 -ne "`wc -c < vme2mb.c`"
  772. then
  773.     echo 'shar: transmission error on "vme2mb.c"'
  774. fi
  775. chk=`sum vme2mb.c | awk '{print $1}'`
  776. if test 51222 -ne $chk -a 40552 -ne $chk
  777. then
  778.     echo 'shar: checksum error on "vme2mb.c"'
  779. fi
  780.