[BACK]Return to pnpinfo.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / pnpinfo

Annotation of src/usr.bin/pnpinfo/pnpinfo.c, Revision 1.1

1.1     ! shawn       1: /*     $OpenBSD$       */
        !             2: /*
        !             3:  * Copyright (c) 1996, Sujal M. Patel
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            16:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            17:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            18:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
        !            19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            21:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            25:  * SUCH DAMAGE.
        !            26:  */
        !            27:
        !            28: #include <sys/time.h>
        !            29:
        !            30: #include <stdio.h>
        !            31: #include <stdlib.h>
        !            32: #include <unistd.h>
        !            33: #include <fcntl.h>
        !            34: #include <string.h>
        !            35:
        !            36: #include <machine/cpufunc.h>
        !            37:
        !            38: #if defined(__OpenBSD__)
        !            39: #include <i386/sysarch.h>
        !            40: #include <machine/pio.h>
        !            41: #endif
        !            42:
        !            43: #include "pnpinfo.h"
        !            44:
        !            45:
        !            46: #define SEND(d, r)     { outb (ADDRESS, d); outb (WRITE_DATA, r); }
        !            47:
        !            48:
        !            49: /* The READ_DATA port that we are using currently */
        !            50: static int rd_port;
        !            51:
        !            52:
        !            53: void DELAY __P((int i));
        !            54: int power __P((int base, int exp));
        !            55: void send_Initiation_LFSR();
        !            56: int get_serial __P((unsigned char *data));
        !            57: int get_resource_info __P((char *buffer, int len));
        !            58: int handle_small_res __P((unsigned char *resinfo, int item, int len));
        !            59: void handle_large_res __P((unsigned char *resinfo, int item, int len));
        !            60: void dump_resdata __P((unsigned char *data, int csn));
        !            61: int isolation_protocol();
        !            62:
        !            63:
        !            64: /*
        !            65:  * DELAY does accurate delaying in user-space.
        !            66:  * This function busy-waits.
        !            67:  */
        !            68: void
        !            69: DELAY (i)
        !            70:        int i;
        !            71: {
        !            72:        struct timeval t;
        !            73:        long start, stop;
        !            74:
        !            75:        gettimeofday (&t, NULL);
        !            76:        start = t.tv_sec * 1000000 + t.tv_usec;
        !            77:        do {
        !            78:                gettimeofday (&t, NULL);
        !            79:                stop = t.tv_sec * 1000000 + t.tv_usec;
        !            80:        } while (start + i > stop);
        !            81: }
        !            82:
        !            83:
        !            84: int
        !            85: power(base, exp)
        !            86:        int base, exp;
        !            87: {
        !            88:        if (exp <= 1)
        !            89:                return base;
        !            90:        else
        !            91:                return base * power(base, exp - 1);
        !            92: }
        !            93:
        !            94:
        !            95: /*
        !            96:  * Send Initiation LFSR as described in "Plug and Play ISA Specification,
        !            97:  * Intel May 94."
        !            98:  */
        !            99: void
        !           100: send_Initiation_LFSR()
        !           101: {
        !           102:        int cur, i;
        !           103:
        !           104:        /* Reset the LSFR */
        !           105:        outb(ADDRESS, 0);
        !           106:        outb(ADDRESS, 0);
        !           107:
        !           108:        cur = 0x6a;
        !           109:        outb(ADDRESS, cur);
        !           110:
        !           111:        for (i = 1; i < 32; i++) {
        !           112:                cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff);
        !           113:                outb(ADDRESS, cur);
        !           114:        }
        !           115: }
        !           116:
        !           117:
        !           118: /*
        !           119:  * Get the device's serial number.  Returns 1 if the serial is valid.
        !           120:  */
        !           121: int
        !           122: get_serial(data)
        !           123:        unsigned char *data;
        !           124: {
        !           125:        int i, bit, valid = 0, sum = 0x6a;
        !           126:
        !           127:        bzero(data, sizeof(char) * 9);
        !           128:
        !           129:        for (i = 0; i < 72; i++) {
        !           130:                bit = inb((rd_port << 2) | 0x3) == 0x55;
        !           131:                DELAY(250);     /* Delay 250 usec */
        !           132:
        !           133:                /* Can't Short Circuit the next evaluation, so 'and' is last */
        !           134:                bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit;
        !           135:                DELAY(250);     /* Delay 250 usec */
        !           136:
        !           137:                valid = valid || bit;
        !           138:
        !           139:                if (i < 64)
        !           140:                        sum = (sum >> 1) |
        !           141:                            (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff);
        !           142:
        !           143:                data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0);
        !           144:        }
        !           145:
        !           146:        valid = valid && (data[8] == sum);
        !           147:
        !           148:        return valid;
        !           149: }
        !           150:
        !           151:
        !           152: /*
        !           153:  * Fill's the buffer with resource info from the device.
        !           154:  * Returns 0 if the device fails to report
        !           155:  */
        !           156: int
        !           157: get_resource_info(buffer, len)
        !           158:        char *buffer;
        !           159:        int len;
        !           160: {
        !           161:        int i, j;
        !           162:
        !           163:        for (i = 0; i < len; i++) {
        !           164:                outb(ADDRESS, STATUS);
        !           165:                for (j = 0; j < 100; j++) {
        !           166:                        if ((inb((rd_port << 2) | 0x3)) & 0x1)
        !           167:                                break;
        !           168:                        DELAY(1);
        !           169:                }
        !           170:                if (j == 100) {
        !           171:                        printf("PnP device failed to report resource data\n");
        !           172:                        return 0;
        !           173:                }
        !           174:                outb(ADDRESS, RESOURCE_DATA);
        !           175:                buffer[i] = inb((rd_port << 2) | 0x3);
        !           176:        }
        !           177:        return 1;
        !           178: }
        !           179:
        !           180:
        !           181: void
        !           182: report_dma_info (x)
        !           183:        int x;
        !           184: {
        !           185:        switch (x & 0x3) {
        !           186:        case 0:
        !           187:                printf ("DMA: 8-bit only\n");
        !           188:                break;
        !           189:        case 1:
        !           190:                printf ("DMA: 8-bit and 16-bit\n");
        !           191:                break;
        !           192:        case 2:
        !           193:                printf ("DMA: 16-bit only\n");
        !           194:                break;
        !           195: #ifdef DIAGNOSTIC
        !           196:        case 3:
        !           197:                printf ("DMA: Reserved\n");
        !           198:                break;
        !           199: #endif
        !           200:        }
        !           201:
        !           202:        if (x & 0x4)
        !           203:                printf ("DMA: Device is a bus master\n");
        !           204:        else
        !           205:                printf ("DMA: Device is not a bus master\n");
        !           206:
        !           207:        if (x & 0x8)
        !           208:                printf ("DMA: May execute in count by byte mode\n");
        !           209:        else
        !           210:                printf ("DMA: May not execute in count by byte mode\n");
        !           211:
        !           212:        if (x & 0x10)
        !           213:                printf ("DMA: May execute in count by word mode\n");
        !           214:        else
        !           215:                printf ("DMA: May not execute in count by word mode\n");
        !           216:
        !           217:        switch ((x & 0x60) >> 5) {
        !           218:        case 0:
        !           219:                printf ("DMA: Compatibility mode\n");
        !           220:                break;
        !           221:        case 1:
        !           222:                printf ("DMA: Type A DMA channel\n");
        !           223:                break;
        !           224:        case 2:
        !           225:                printf ("DMA: Type B DMA channel\n");
        !           226:                break;
        !           227:        case 3:
        !           228:                printf ("DMA: Type F DMA channel\n");
        !           229:                break;
        !           230:        }
        !           231: }
        !           232:
        !           233:
        !           234: void
        !           235: report_memory_info (x)
        !           236:        int x;
        !           237: {
        !           238:        if (x & 0x1)
        !           239:                printf ("Memory Range: Writeable\n");
        !           240:        else
        !           241:                printf ("Memory Range: Not writeable (ROM)\n");
        !           242:
        !           243:        if (x & 0x2)
        !           244:                printf ("Memory Range: Read-cacheable, write-through\n");
        !           245:        else
        !           246:                printf ("Memory Range: Non-cacheable\n");
        !           247:
        !           248:        if (x & 0x4)
        !           249:                printf ("Memory Range: Decode supports high address\n");
        !           250:        else
        !           251:                printf ("Memory Range: Decode supports range length\n");
        !           252:
        !           253:        switch ((x & 0x18) >> 3) {
        !           254:        case 0:
        !           255:                printf ("Memory Range: 8-bit memory only\n");
        !           256:                break;
        !           257:        case 1:
        !           258:                printf ("Memory Range: 16-bit memory only\n");
        !           259:                break;
        !           260:        case 2:
        !           261:                printf ("Memory Range: 8-bit and 16-bit memory supported\n");
        !           262:                break;
        !           263: #ifdef DIAGNOSTIC
        !           264:        case 3:
        !           265:                printf ("Memory Range: Reserved\n");
        !           266:                break;
        !           267: #endif
        !           268:        }
        !           269:
        !           270:        if (x & 0x20)
        !           271:                printf ("Memory Range: Memory is shadowable\n");
        !           272:        else
        !           273:                printf ("Memory Range: Memory is not shadowable\n");
        !           274:
        !           275:        if (x & 0x40)
        !           276:                printf ("Memory Range: Memory is an expansion ROM\n");
        !           277:        else
        !           278:                printf ("Memory Range: Memory is not an expansion ROM\n");
        !           279:
        !           280: #ifdef DIAGNOSTIC
        !           281:        if (x & 0x80)
        !           282:                printf ("Memory Range: Reserved (Device is brain-damaged)\n");
        !           283: #endif
        !           284: }
        !           285:
        !           286:
        !           287: /*
        !           288:  *  Small Resource Tag Handler
        !           289:  *
        !           290:  *  Returns 1 if checksum was valid (and an END_TAG was received).
        !           291:  *  Returns -1 if checksum was invalid (and an END_TAG was received).
        !           292:  *  Returns 0 for other tags.
        !           293:  */
        !           294: int
        !           295: handle_small_res(resinfo, item, len)
        !           296:        int item, len;
        !           297:        unsigned char *resinfo;
        !           298: {
        !           299:        int i;
        !           300:
        !           301:        switch (item) {
        !           302:        case PNP_VERSION:
        !           303:                printf("PnP Version: %d.%d\n",
        !           304:                    resinfo[0] >> 4,
        !           305:                    resinfo[0] & (0xf));
        !           306:                printf("Vendor Version: %d\n", resinfo[1]);
        !           307:                break;
        !           308:        case LOG_DEVICE_ID:
        !           309:                printf("Logical Device ID: %c%c%c%02x%02x (%08x)\n",
        !           310:                    ((resinfo[0] & 0x7c) >> 2) + 64,
        !           311:                    (((resinfo[0] & 0x03) << 3) |
        !           312:                        ((resinfo[1] & 0xe0) >> 5)) + 64,
        !           313:                    (resinfo[1] & 0x1f) + 64,
        !           314:                    resinfo[2], resinfo[3], *(int *)resinfo);
        !           315:
        !           316:                if (resinfo[4] & 0x1)
        !           317:                        printf ("Device powers up active\n");
        !           318:                if (resinfo[4] & 0x2)
        !           319:                        printf ("Device supports I/O Range Check\n");
        !           320:                if (resinfo[4] > 0x3)
        !           321:                        printf ("Reserved register funcs %02x\n",
        !           322:                                resinfo[4]);
        !           323:
        !           324:                if (len == 6)
        !           325:                        printf("Vendor register funcs %02x\n", resinfo[5]);
        !           326:                break;
        !           327:        case COMP_DEVICE_ID:
        !           328:                printf("Compatible Device ID: %c%c%c%02x%02x (%08x)\n",
        !           329:                    ((resinfo[0] & 0x7c) >> 2) + 64,
        !           330:                    (((resinfo[0] & 0x03) << 3) |
        !           331:                        ((resinfo[1] & 0xe0) >> 5)) + 64,
        !           332:                    (resinfo[1] & 0x1f) + 64,
        !           333:                    resinfo[2], resinfo[3], *(int *)resinfo);
        !           334:                break;
        !           335:        case IRQ_FORMAT:
        !           336:                printf("IRQ: ");
        !           337:
        !           338:                for (i = 0; i < 8; i++)
        !           339:                        if (resinfo[0] & (char) (power(2, i)))
        !           340:                                printf("%d ", i);
        !           341:                for (i = 0; i < 8; i++)
        !           342:                        if (resinfo[1] & (char) (power(2, i)))
        !           343:                                printf("%d ", i + 8);
        !           344:                printf("\n");
        !           345:                if (len == 3) {
        !           346:                        if (resinfo[2] & 0x1)
        !           347:                                printf("IRQ: High true edge sensitive\n");
        !           348:                        if (resinfo[2] & 0x2)
        !           349:                                printf("IRQ: Low true edge sensitive\n");
        !           350:                        if (resinfo[2] & 0x4)
        !           351:                                printf("IRQ: High true level sensitive\n");
        !           352:                        if (resinfo[2] & 0x8)
        !           353:                                printf("IRQ: Low true level sensitive\n");
        !           354:                }
        !           355:                break;
        !           356:        case DMA_FORMAT:
        !           357:                printf("DMA: ");
        !           358:                for (i = 0; i < 8; i++)
        !           359:                        if (resinfo[0] & (char) (power(2, i)))
        !           360:                                printf("%d ", i);
        !           361:                printf ("\n");
        !           362:                report_dma_info (resinfo[1]);
        !           363:                break;
        !           364:        case START_DEPEND_FUNC:
        !           365:                printf("Start Dependent Function\n");
        !           366:                if (len == 1) {
        !           367:                        switch (resinfo[0]) {
        !           368:                        case 0:
        !           369:                                printf("Good Configuration\n");
        !           370:                                break;
        !           371:                        case 1:
        !           372:                                printf("Acceptable Configuration\n");
        !           373:                                break;
        !           374:                        case 2:
        !           375:                                printf("Sub-optimal Configuration\n");
        !           376:                                break;
        !           377:                        }
        !           378:                }
        !           379:                break;
        !           380:        case END_DEPEND_FUNC:
        !           381:                printf("End Dependent Function\n");
        !           382:                break;
        !           383:        case IO_PORT_DESC:
        !           384:                if (resinfo[0])
        !           385:                        printf("Device decodes the full 16-bit ISA address\n");
        !           386:                else
        !           387:                        printf("Device does not decode the full 16-bit ISA address\n");
        !           388:                printf("I/O Range maximum address: 0x%x\n",
        !           389:                    resinfo[1] + (resinfo[2] << 8));
        !           390:                printf("I/O Range maximum address: 0x%x\n",
        !           391:                    resinfo[3] + (resinfo[4] << 8));
        !           392:                printf("I/O alignment for minimum: %d\n",
        !           393:                    resinfo[5]);
        !           394:                printf("I/O length: %d\n", resinfo[6]);
        !           395:                break;
        !           396:        case FIXED_IO_PORT_DESC:
        !           397:                printf ("I/O Range base address: 0x%x\n",
        !           398:                    resinfo[1] + (resinfo[2] << 8));
        !           399:                printf("I/O length: %d\n", resinfo[3]);
        !           400:                break;
        !           401: #ifdef DIAGNOSTIC
        !           402:        case SM_RES_RESERVED:
        !           403:                printf("Reserved Tag Detected\n");
        !           404:                break;
        !           405: #endif
        !           406:        case SM_VENDOR_DEFINED:
        !           407:                printf("*** Small Vendor Tag Detected\n");
        !           408:                break;
        !           409:        case END_TAG:
        !           410:                printf("End Tag\n\n");
        !           411:                /* XXX Record and Verify Checksum */
        !           412:                return 1;
        !           413:                break;
        !           414:        }
        !           415:        return 0;
        !           416: }
        !           417:
        !           418:
        !           419: void
        !           420: handle_large_res(resinfo, item, len)
        !           421:        int item, len;
        !           422:        unsigned char *resinfo;
        !           423: {
        !           424:        int i;
        !           425:
        !           426:        switch (item) {
        !           427:        case MEMORY_RANGE_DESC:
        !           428:                report_memory_info(resinfo[0]);
        !           429:                printf("Memory range minimum address: 0x%x\n",
        !           430:                    (resinfo[1] << 8) + (resinfo[2] << 16));
        !           431:                printf("Memory range maximum address: 0x%x\n",
        !           432:                    (resinfo[3] << 8) + (resinfo[4] << 16));
        !           433:                printf("Memory range base alignment: 0x%x\n",
        !           434:                    (i = (resinfo[5] + (resinfo[6] << 8))) ? i : (1 << 16));
        !           435:                printf("Memory range length: 0x%x\n",
        !           436:                    (resinfo[7] + (resinfo[8] << 8)) * 256);
        !           437:                break;
        !           438:        case ID_STRING_ANSI:
        !           439:                printf("Device Description: ");
        !           440:
        !           441:                for (i = 0; i < len; i++) {
        !           442:                        printf("%c", resinfo[i]);
        !           443:                }
        !           444:                printf("\n");
        !           445:                break;
        !           446:        case ID_STRING_UNICODE:
        !           447:                printf("ID String Unicode Detected (Undefined)\n");
        !           448:                break;
        !           449:        case LG_VENDOR_DEFINED:
        !           450:                printf("Large Vendor Defined Detected\n");
        !           451:                break;
        !           452:        case _32BIT_MEM_RANGE_DESC:
        !           453:                printf("32bit Memory Range Desc Unimplemented\n");
        !           454:                break;
        !           455:        case _32BIT_FIXED_LOC_DESC:
        !           456:                printf("32bit Fixed Location Desc Unimplemented\n");
        !           457:                break;
        !           458:        case LG_RES_RESERVED:
        !           459:                printf("Large Reserved Tag Detected\n");
        !           460:                break;
        !           461:        }
        !           462: }
        !           463:
        !           464:
        !           465: /*
        !           466:  * Dump all the information about configurations.
        !           467:  */
        !           468: void
        !           469: dump_resdata(data, csn)
        !           470:        unsigned char *data;
        !           471:        int csn;
        !           472: {
        !           473:        int i, large_len;
        !           474:        unsigned char tag, *resinfo;
        !           475:
        !           476: #ifdef DEBUG
        !           477:        printf("Card assigned CSN #%d\n", csn);
        !           478: #endif
        !           479:        printf("Board Vendor ID: %c%c%c%02x%02x\n",
        !           480:            ((data[0] & 0x7c) >> 2) + 64,
        !           481:            (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64,
        !           482:            (data[1] & 0x1f) + 64, data[2], data[3]);
        !           483:        printf("Board Serial Number: %08x\n", *(int *)&(data[4]));
        !           484:
        !           485:        SEND(SET_CSN, csn); /* Move this out of this function XXX */
        !           486:        outb(ADDRESS, STATUS);
        !           487:
        !           488:        /* Allows up to 1kb of Resource Info,  Should be plenty */
        !           489:        for (i = 0; i < 1024; i++) {
        !           490:                if (!get_resource_info(&tag, 1))
        !           491:                        return;
        !           492:
        !           493: #define TYPE   (tag >> 7)
        !           494: #define        S_ITEM  (tag >> 3)
        !           495: #define S_LEN  (tag & 0x7)
        !           496: #define        L_ITEM  (tag & 0x7f)
        !           497:
        !           498:                if (TYPE == 0) {
        !           499:                        /* Handle small resouce data types */
        !           500:
        !           501:                        resinfo = malloc(S_LEN);
        !           502:                        if (!get_resource_info(resinfo, S_LEN))
        !           503:                                return;
        !           504:
        !           505:                        if (handle_small_res(resinfo, S_ITEM, S_LEN) == 1)
        !           506:                                return;
        !           507:                        free(resinfo);
        !           508:                } else {
        !           509:                        /* Handle large resouce data types */
        !           510:
        !           511:                        if (!get_resource_info((char *) &large_len, 2))
        !           512:                                return;
        !           513:
        !           514:                        resinfo = malloc(large_len);
        !           515:                        if (!get_resource_info(resinfo, large_len))
        !           516:                                return;
        !           517:
        !           518:                        handle_large_res(resinfo, L_ITEM, large_len);
        !           519:                        free(resinfo);
        !           520:                }
        !           521:        }
        !           522: }
        !           523:
        !           524:
        !           525: /*
        !           526:  * Run the isolation protocol. Use rd_port as the READ_DATA port value (caller
        !           527:  * should try multiple READ_DATA locations before giving up). Upon exiting,
        !           528:  * all cards are aware that they should use rd_port as the READ_DATA port;
        !           529:  */
        !           530: int
        !           531: isolation_protocol()
        !           532: {
        !           533:        int csn;
        !           534:        unsigned char data[9];
        !           535:
        !           536:        send_Initiation_LFSR();
        !           537:
        !           538:        /* Reset CSN for All Cards */
        !           539:        SEND(0x02, 0x04);
        !           540:
        !           541:        for (csn = 1; (csn < MAX_CARDS); csn++) {
        !           542:                /* Wake up cards without a CSN */
        !           543:                SEND(WAKE, 0);
        !           544:                SEND(SET_RD_DATA, rd_port);
        !           545:                outb(ADDRESS, SERIAL_ISOLATION);
        !           546:                DELAY(1000);    /* Delay 1 msec */
        !           547:
        !           548:                if (get_serial(data))
        !           549:                        dump_resdata(data, csn);
        !           550:                else
        !           551:                        break;
        !           552:        }
        !           553:        return csn - 1;
        !           554: }
        !           555:
        !           556:
        !           557: void
        !           558: main()
        !           559: {
        !           560:        int num_pnp_devs;
        !           561:
        !           562: #if defined(__OpenBSD__)
        !           563:        if (i386_iopl(1)) {
        !           564:                perror("i386_iopl");
        !           565:                exit(1);
        !           566:        }
        !           567: #endif
        !           568:        printf("Checking for Plug-n-Play devices...\n");
        !           569:
        !           570:        /* Try various READ_DATA ports from 0x203-0x3ff */
        !           571:        for (rd_port = 0x80; (rd_port < 0xff); rd_port += 0x10) {
        !           572: #ifdef DEBUG
        !           573:                printf("Trying Read_Port at %x\n", (rd_port << 2) | 0x3);
        !           574: #endif
        !           575:                num_pnp_devs = isolation_protocol(rd_port);
        !           576:                if (num_pnp_devs)
        !           577:                        break;
        !           578:        }
        !           579:        if (!num_pnp_devs) {
        !           580:                printf("No Plug-n-Play devices were found\n");
        !           581:                return;
        !           582:        }
        !           583: }