|
|
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.