Annotation of coherent/b/kernel/tools/asypatch.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.