|
|
1.1 root 1: /*
2: * File: asypatch.c
3: *
4: * Purpose: read a spec from stdin and patch the asy driver
5: *
6: * $Log: asypatch.c,v $
7: * Revision 1.3 93/05/18 07:32:22 bin
8: * *** empty log message ***
9: *
10: */
11:
12: /*
13: * ----------------------------------------------------------------------
14: * Includes.
15: */
16: #include <stdio.h>
17: #include <termio.h>
18: #include <sys/ktty.h>
19: #include <sys/asy.h>
20: #ifdef _I386
21: #include <coff.h>
22: #endif
23:
24: /*
25: * ----------------------------------------------------------------------
26: * Definitions.
27: * Constants.
28: * Macros with argument lists.
29: * Typedefs.
30: * Enums.
31: */
32: #define BSZ 256
33: #ifdef _I386
34: #define MAKEPATCH(a1,a2,a3,a4,a5) coffp0(a1,a2,a3,a4,a5)
35: #else
36: #define MAKEPATCH(a1,a2,a3,a4,a5) loutpatch(a1,a2,a3,a4,a5)
37: #endif
38:
39: /*
40: * ----------------------------------------------------------------------
41: * Functions.
42: * Import Functions.
43: * Export Functions.
44: * Local Functions.
45: */
46: void p_rec();
47: void g_rec();
48: void m_rec();
49: void fatal();
50: void asydump();
51: int asy_ver();
52: int get_speed();
53: void usage();
54:
55: /*
56: * ----------------------------------------------------------------------
57: * Global Data.
58: * Import Variables.
59: * Export Variables.
60: * Local Variables.
61: */
62: int line; /* line number in input file */
63: int num_chan; /* highest channel number used */
64: int group; /* next port group to be assigned */
65: unsigned int x1,x2,x3,x4,x5,x6,x7;
66: asy0_t asy0[MAX_ASY];
67: asy_gp_t asy_gp[MAX_ASY];
68: char chan_found[MAX_ASY]; /* true if record seen for the channel */
69: char buf[BSZ]; /* input line buffer */
70: char msg[BSZ]; /* error message line buffer */
71: char expect_chan; /* number of "M" records expected */
72: char outs, irq, nms;
73: char vflag; /* verbose mode */
74: char xflag; /* debug mode */
75: char *cmd; /* command name */
76:
77: /*
78: * ----------------------------------------------------------------------
79: * Code.
80: */
81:
82: /*
83: * main()
84: *
85: * while able to read a line from input
86: * call routine to process the record type
87: */
88: main(argc, argv)
89: int argc;
90: char **argv;
91: {
92: int fd, len, ch, hi_chan, p_ver;
93: char *pfile = 0, *cp;
94:
95: cmd = argv[0];
96:
97: /*
98: * Scan command arguments.
99: */
100: while (cp = *++argv) {
101: if (*cp == '-') {
102: while(*++cp) {
103: switch (*cp) {
104: case 'v':
105: vflag = 1;
106: break;
107: case 'x':
108: xflag = 1;
109: break;
110: default:
111: usage();
112: }
113: }
114: } else {
115: if (pfile)
116: usage();
117: pfile = cp;
118: }
119: }
120:
121: if (!pfile)
122: usage();
123:
124: if (vflag)
125: printf("%s Version %d\n", cmd, ASY_VERSION);
126:
127: while (fgets(buf, BSZ, stdin)) {
128: line++;
129: switch (buf[0]) {
130: case 'P': p_rec(); break;
131: case 'G': g_rec(); break;
132: case 'M': m_rec(); break;
133: }
134: }
135:
136: if (expect_chan) {
137: sprintf(msg, "expecting %d \"M\" entries", expect_chan);
138: fatal(msg);
139: }
140:
141: /*
142: * Find highest channel number in use.
143: */
144: for (hi_chan = -1, ch = 0; ch < MAX_ASY; ch++)
145: if (chan_found[ch])
146: hi_chan = ch;
147:
148: num_chan = hi_chan + 1;
149:
150: if (num_chan == 0)
151: fatal("No channels specified");
152:
153: /*
154: * Make sure the file to be patched is accessible.
155: */
156: if ((fd = open(pfile, 2)) == -1) {
157: sprintf(msg, "can't open file %s\n", pfile);
158: fatal(msg);
159: }
160: close(fd);
161:
162: /*
163: * Version numbers in patch program and driver must match.
164: */
165: p_ver = asy_ver(pfile);
166: if (p_ver != ASY_VERSION) {
167: sprintf(msg, "Wrong versions: asypatch=%d %s=%d\n",
168: ASY_VERSION, pfile, p_ver);
169: fatal(msg);
170: }
171:
172: if (vflag)
173: asydump();
174:
175: /*
176: * Make three or four patches.
177: */
178: if (MAKEPATCH(pfile, "ASY_NUM", &num_chan, sizeof(int), 0) == 0)
179: fatal("can't patch ASY_NUM");
180:
181: if (MAKEPATCH(pfile, "ASYGP_NUM", &group, sizeof(int), 0) == 0)
182: fatal("can't patch ASYGP_NUM");
183:
184: len = num_chan * sizeof(asy0[0]);
185: if (MAKEPATCH(pfile, "asy0", asy0, len, 0) == 0)
186: fatal("can't patch asy0");
187:
188: if (group) {
189: len = group * sizeof(asy_gp[0]);
190: if (MAKEPATCH(pfile, "asy_gp", asy_gp, len, 0) == 0)
191: fatal("can't patch asy_gp");
192: }
193:
194: exit(0);
195: }
196:
197: void
198: p_rec()
199: {
200: asy0_t *a0;
201: int speed;
202:
203: if (expect_chan) {
204: sprintf(msg, "expecting %d \"M\" entries", expect_chan);
205: fatal(msg);
206: }
207:
208: /*
209: * Load a struct from input.
210: *
211: * "P" record is:
212: * P port irq outs excl speed channel nms
213: * port and outs are in hex, others in decimal
214: */
215: if (sscanf(buf+1, "%x%d%x%d%d%d%d",&x1,&x2,&x3,&x4,&x5,&x6,&x7) != 7)
216: fatal("need 7 parameters");
217:
218: if (x6 >= MAX_ASY) {
219: sprintf(msg, "invalid channel #%d\n", x6);
220: fatal(msg);
221: }
222:
223: if (chan_found[x6]) {
224: sprintf(msg, "duplicate channel #%d\n", x6);
225: fatal(msg);
226: }
227:
228: a0 = asy0 + x6;
229: #ifdef _I386
230: if (x1 >= 0x10000)
231: fatal("address must be ffff or less");
232: #endif
233: a0->a_port = x1;
234: if (x2 >= 16)
235: fatal("irq must be 15 or less");
236: a0->a_irqno = x2;
237: #ifdef _I386
238: if (x3 & 0xfffffff3)
239: #else
240: if (x3 & 0xfff3)
241: #endif
242: fatal("only bits 2 & 3 of outs may be nonzero");
243: a0->a_outs = x3;
244: if (x4 > 1)
245: fatal("excl must be 0 or 1");
246: a0->a_ixc = x4;
247: speed = get_speed(x5);
248: if (speed < 0)
249: fatal("invalid speed");
250: else
251: a0->a_speed = speed;
252: a0->a_asy_gp = NO_ASYGP;
253: chan_found[x6] = 1;
254: if (x7 > 1)
255: fatal("nms must be 0 or 1");
256: a0->a_nms = x7;
257: }
258:
259: void
260: g_rec()
261: {
262: int slot;
263: asy_gp_t *gp = asy_gp + group;
264:
265: if (expect_chan) {
266: fprintf(stderr, "expecting %d \"M\" entries", expect_chan);
267: fatal("record out of order");
268: }
269:
270: if (group >= MAX_ASYGP) {
271: fprintf(stderr, "Just found group #%d\n", group);
272: fatal("too many groups");
273: }
274:
275: /*
276: * Load a struct from input.
277: *
278: * "G" record is:
279: * G port irq outs type number-of-channels nms
280: * port and outs are in hex, others in decimal
281: * see asy.h for valid types
282: */
283: if (sscanf(buf+1, "%x%d%x%d%d%d",&x1,&x2,&x3,&x4,&x5,&x6) != 6)
284: fatal("need 6 parameters");
285: #ifdef _I386
286: if (x1 >= 0x10000)
287: fatal("address must be ffff or less");
288: #endif
289: gp->stat_port = x1;
290: if (x2 >= 16)
291: fatal("irq must be 15 or less");
292: irq = gp->irq = x2;
293: #ifdef _I386
294: if (x3 & 0xfffffff3)
295: #else
296: if (x3 & 0xfff3)
297: #endif
298: fatal("only bits 2 & 3 of outs may be nonzero");
299: outs = x3;
300: if (x4 >= PT_MAX)
301: fatal("invalid type");
302: gp->gp_type = x4;
303: if (x5 > MAX_SLOTS || x5 == 0)
304: fatal("number of channels must be in range 1..16");
305: expect_chan = x5;
306: if (x6 > 1)
307: fatal("nms must be 0 or 1");
308: nms = x6;
309: for (slot = 0; slot < MAX_SLOTS; slot++)
310: gp->chan_list[slot] = NO_CHANNEL;
311: group++;
312: }
313:
314: void
315: usage()
316: {
317: fprintf(stderr, "%s Version %d\n", cmd, ASY_VERSION);
318: fprintf(stderr, "Usage: %s [-vx] patchfile < specfile\n", cmd);
319: exit(1);
320: }
321:
322: void
323: fatal(s)
324: char *s;
325: {
326: fprintf(stderr, "%s: line %d %s\n", cmd, line, s);
327: exit(1);
328: }
329:
330: void
331: m_rec()
332: {
333: asy0_t *a0;
334: int speed;
335:
336: if (expect_chan == 0) {
337: fatal("unexpected \"M\" record");
338: }
339:
340: /*
341: * Load a struct from input.
342: *
343: * "M" record is:
344: * M port speed slot channel
345: * port is in hex, speed in decimal
346: */
347: if (sscanf(buf+1, "%x%d%d%d",&x1,&x2,&x3,&x4) != 4)
348: fatal("need 4 parameters");
349:
350: if (x4 >= MAX_ASY) {
351: sprintf(msg, "invalid channel #%d\n", x4);
352: fatal(msg);
353: }
354:
355: if (chan_found[x4]) {
356: sprintf(msg, "duplicate channel #%d\n", x4);
357: fatal(msg);
358: }
359:
360: if (x3 >= MAX_SLOTS) {
361: sprintf(msg, "slot number %d must be less than 16\n", x3);
362: fatal(msg);
363: }
364: a0 = asy0 + x4;
365:
366: #ifdef _I386
367: if (x1 >= 0x10000)
368: fatal("address must be ffff or less");
369: #endif
370: a0->a_port = x1;
371: speed = get_speed(x2);
372: if (speed < 0)
373: fatal("invalid speed");
374: else
375: a0->a_speed = speed;
376:
377: a0->a_outs = outs;
378: a0->a_nms = nms;
379: a0->a_ixc = 0;
380: a0->a_irqno = irq;
381: a0->a_asy_gp = group - 1;
382: asy_gp[group - 1].chan_list[x3] = x4;
383: chan_found[x4] = 1;
384: expect_chan--;
385: }
386:
387: int
388: get_speed(rate)
389: int rate;
390: {
391: int ret;
392:
393: switch (rate) {
394: case 0: ret = B0; break;
395: case 50: ret = B50; break;
396: case 75: ret = B75; break;
397: case 110: ret = B110; break;
398: case 134: ret = B134; break;
399: case 150: ret = B150; break;
400: case 200: ret = B200; break;
401: case 300: ret = B300; break;
402: case 600: ret = B600; break;
403: case 1200: ret = B1200; break;
404: case 1800: ret = B1800; break;
405: case 2400: ret = B2400; break;
406: case 4800: ret = B4800; break;
407: case 9600: ret = B9600; break;
408: case 19200: ret = B19200; break;
409: #ifdef _I386
410: case 38400: ret = B38400; break;
411: #endif
412: default: ret = -1;
413: }
414: return ret;
415: }
416:
417: #ifdef _I386
418: /*
419: * coffp0()
420: *
421: * Given a file name, a symbol name, a buffer, and number of bytes in
422: * the buffer, read or write the buffer into the COFF file at the
423: * symbol specified.
424: *
425: * Read the given file if argument "do_read" is 1, else write to the file.
426: * Return nonzero if success; zero if failure.
427: */
428: int
429: coffp0(fname, sym, data, len, do_read)
430: char *fname, *sym, *data;
431: int len, do_read;
432: {
433: int ret;
434: SYMENT se;
435:
436: /*
437: * put together SYMENT stuff for coffnlist
438: */
439: se._n._n_n._n_zeroes = 0;
440: se._n._n_n._n_offset = sizeof(long);
441: se.n_type = -1;
442: ret = coffnlist(fname, &se, sym, 1);
443:
444: if (ret)
445: ret = coffpatch(fname, &se, sym, data, len, do_read);
446:
447: return ret;
448: }
449: #endif
450:
451: void
452: asydump()
453: {
454: char chan, g;
455: asy0_t *a0;
456: asy_gp_t *gp;
457:
458: /*
459: * Display totals.
460: */
461: printf("Channels = %2d Groups = %d\n", num_chan, group);
462:
463: /*
464: * Display channel table asy0.
465: */
466: printf("Ch port Ir S O Gp X N\n");
467: for (chan = 0; chan < num_chan; chan++) {
468: a0 = asy0 + chan;
469: printf("%2d %4x %2d %1x %1x %2d %1d %1d\n",
470: chan, a0->a_port, a0->a_irqno, a0->a_speed, a0->a_outs,
471: a0->a_asy_gp, a0->a_ixc, a0->a_nms);
472: }
473:
474: /*
475: * Display group table asy_gp.
476: */
477: if (group) {
478: printf("Gp Port T Irq Channels...............\n");
479: for (g = 0; g < group; g++) {
480: int s;
481:
482: gp = asy_gp + g;
483: printf("%2d %4x %1d %2d ",
484: g,gp->stat_port,gp->gp_type,gp->irq);
485: for (s = 0; s < MAX_SLOTS; s++)
486: if (gp->chan_list[s] == NO_CHANNEL)
487: printf(" ", gp->chan_list[s]);
488: else
489: printf(" %2d", gp->chan_list[s]);
490: putchar('\n');
491: }
492: }
493: }
494:
495: /*
496: * asy_ver()
497: *
498: * Fetch the initial value at symbol ASY_VER (ASY_VER_ for 286)
499: * in file "fname".
500: *
501: * Return -1 on failure; otherwise return the value at the symbol.
502: */
503: int
504: asy_ver(fname)
505: char * fname;
506: {
507: int ret = -1;
508: int version;
509:
510: if (MAKEPATCH(fname, "ASY_VER", &version, sizeof(int), 1))
511: ret = version;
512: return ret;
513: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.