Annotation of coherent/d/kernel/USRSRC/i8086/drv/dg.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * dg - device driver for Digiboard PC/Xe intelligent multiport controller
                      3:  *
                      4:  * $Header: /usr/src/sys/i8086/drv/RCS/dg.c,v 1.3 91/03/05 12:23:42 root Exp $
                      5:  *
                      6:  * $Log:       /usr/src/sys/i8086/drv/RCS/dg.c,v $
                      7:  * Revision 1.3        91/03/05  12:23:42      root
                      8:  * Fix cast on dg_ram_base
                      9:  * 
                     10:  */
                     11:  
                     12: /*
                     13:  * Various notes:
                     14:  *
                     15:  *     FEP = front-end-processor (the 80186 on the Digiboard)
                     16:  *
                     17:  *     At port DG_IOB:
                     18:  *             the 2's bit is 1 to enable DPRAM, 0 to disable
                     19:  *             the 4's bit is 1 to reset FEP, 0 to clear reset 
                     20:  *
                     21:  *     There is a bug in the current ldlib.a version of setivec and clrivec:
                     22:  *     they only work during xxload() and xxunload() due to use of "ucs"
                     23:  *     instead of "getcs()" to determine the CS for the interrupt routine.
                     24:  */
                     25: 
                     26: /*
                     27:  * Definitions.
                     28:  *
                     29:  */
                     30: #define        DG_RAM_LENGTH   0x10000L
                     31: #define DG_MEMORY_SEG  0xF000          /* dual-port ram base on FEP side */
                     32: #define DG_BIOS_ADDR   0xF800
                     33: #define DG_FEPOS_ADDR  0x2000
                     34: #define DG_BIOS_LOADER 0x80            /* minor number to write to BIOS */
                     35: #define DG_FEPOS_LOADER        0x40            /* minor number to write to FEPOS */
                     36: #define DG_BIOS_LENGTH 0x800           /* PC/Xe BIOS is 2k bytes */
                     37: #define DG_BIOS_CONFIRM        0x0C00          /* look for "GD" here */
                     38: #define DG_FEP_CONFIRM 0x0D20          /* look for "OS" here */
                     39: #define DG_BIOS_REQ    0x0C40          /* Start FEP BIOS requests here */
                     40: #define BIOS_GOOD      ('G' + ('D'<<8))        /* "GD" */
                     41: #define FEPOS_GOOD     ('O' + ('S'<<8))        /* "OS" */
                     42: 
                     43: #define CSTART         0x400           /* start addr of command queue */
                     44: #define NPORT          0x0C22          /* addr of # of ports */
                     45: #define CIN            0x0D10          /* addr for command in pointer */
                     46: #define COUT           0x0D12          /* addr for command out pointer */
                     47: #define ISTART         0x800           /* start addr of event queue */
                     48: #define EIN            0x0D18          /* addr for event in pointer */
                     49: #define EOUT           0x0D1A          /* addr for event out pointer */
                     50: #define INTERVAL       0x0E04          /* addr for ticks between irpts */
                     51: #define EVENT_LEN      4               /* bytes per FEP event */
                     52: #define COMMAND_LEN    4               /* bytes per FEP command */
                     53: 
                     54: /*
                     55:  * Includes.
                     56:  */
                     57: #include "coherent.h" 
                     58: #include <sys/io.h>            /* IO */
                     59: #include <sys/sched.h>         /* [CIS]VPAUSE */
                     60: #include <sys/uproc.h>         /* u.u_error */
                     61: #include <sys/proc.h>          /* wakeup();
                     62:                                   includes sys/types.h - faddr_t, paddr_t
                     63:                                   and sys/timeout.h - TIM
                     64:                                   needs coherent.h for KERNEL */
                     65: #include <sys/con.h>           /* CON */
                     66: #include <sys/stat.h>          /* minor(dev) */
                     67: #include <devices.h>           /* device major numbers, including PE_MAJOR */
                     68: #include <errno.h>
                     69: 
                     70: /*
                     71:  * Export Functions.
                     72:  */
                     73: 
                     74: /*
                     75:  * Export variables - these may be patched in order to configure the driver.
                     76:  */
                     77: long   DG_RAM = 0xF0000L;      /* segment for 64k of dual-port RAM */
                     78: int    DG_IOB = 0x200;         /* address of i/o byte for controller */
                     79: int    DG_INT = 15;            /* IRQ number for board's interrupt */
                     80: 
                     81: /*
                     82:  * Import Functions
                     83:  */
                     84: int    nulldev();
                     85: int    nonedev();
                     86: 
                     87: /*
                     88:  * Local functions.
                     89:  */
                     90: static dgload();
                     91: static dgunload();
                     92: static dgopen();
                     93: static dgclose();
                     94: static dgread();
                     95: static dgwrite();
                     96: static void dgdelay();
                     97: static dg_start_timing();
                     98: static dg_stop_timing();
                     99: static int dginit2();
                    100: static int dginit3();
                    101: static void dgintr();
                    102:  
                    103: /*
                    104:  * Local variables.
                    105:  */
                    106: static faddr_t dg_ram_fp;      /* (far *) to access screen */
                    107: static paddr_t dg_ram_base;    /* physical address of screen base */
                    108: static TIM     delay_tim;      /* needed for calls to timeout() */
                    109: static TIM     timeout_tim;    /* needed for calls to timeout() */
                    110: static int     dg_expired;     /* TRUE after local timeout */
                    111: static int     bios_loading;   /* TRUE if minor device for BIOS load open */
                    112: static int     fepos_loading;  /* TRUE if minor device for FEPOS load open */
                    113: static int     load_byte_ct;   /* place-holder for BIOS/FEPOS load */
                    114: static int     board_ready;    /* TRUE when all board initialization done */
                    115: static int     dg_bios_wait;   /* TRUE if waiting for BIOS to be loaded */
                    116: static int     dg_fepos_wait;  /* TRUE if waiting for FEPOS to be loaded */
                    117: static int     nport;          /* number of ports on the Digiboard */
                    118: static int     test_irq;       /* TRUE during startup */
                    119: 
                    120: /*
                    121:  * Configuration table - another export variable.
                    122:  */
                    123: CON dgcon ={
                    124:        DFCHR,                          /* Flags */
                    125:        PE_MAJOR,                       /* Major index */
                    126:        dgopen,                         /* Open */
                    127:        dgclose,                        /* Close */
                    128:        nulldev,                        /* Block */
                    129:        dgread,                         /* Read */
                    130:        dgwrite,                        /* Write */
                    131:        nulldev,                        /* Ioctl */
                    132:        nulldev,                        /* Powerfail */
                    133:        nulldev,                        /* Timeout */
                    134:        dgload,                         /* Load */
                    135:        dgunload,                       /* Unload */
                    136:        nulldev                         /* Poll */
                    137: };
                    138: 
                    139: /*
                    140:  * Load Routine.
                    141:  */
                    142: static dgload()
                    143: {
                    144:        char v;
                    145: 
                    146:        setivec(DG_INT, dgintr);
                    147:        /*
                    148:         * Allocate a selector to map onto the dual-port RAM.  ptov() will
                    149:         * return the first available selector of the 8,192 possible.
                    150:         */
                    151:        dg_ram_base = (paddr_t)((long)(unsigned)DG_RAM << 4);
                    152:        dg_ram_fp = ptov(dg_ram_base, (fsize_t)DG_RAM_LENGTH);
                    153:        
                    154:        /*
                    155:         * Reset the board and wait.
                    156:         * Actual delay is a tick = 0.01 sec; only need 1msec.
                    157:         */
                    158:        outb(DG_IOB, 0x04);
                    159:        dgdelay(1);
                    160:        
                    161:        /*
                    162:         * Read board ID.
                    163:         */
                    164:        v = inb(DG_IOB);
                    165:        if ((v & 0x01) == 0x01) {
                    166:                printf("Error - board type is PC/Xi\n");
                    167:                return;
                    168:        } else {
                    169:                outb(DG_IOB, 0x05);     /* hold FEP reset */
                    170:                v = inb(DG_IOB);
                    171:                if ((v & 0x01) == 0x01) {
                    172:                        printf("Error - board type is PC/Xm\n");
                    173:                        return;
                    174:                } else
                    175:                        printf("PC/Xe ID found\n");
                    176:        }
                    177:        
                    178:        /*
                    179:         * Board Reset.
                    180:         */
                    181:        outb(DG_IOB, 0x04);     /* reset board */
                    182:        dg_start_timing(100);   /* start 1-second timer */
                    183:        while ((inb(DG_IOB) & 0x0E) != 0x04) {
                    184:                if (dg_expired) {
                    185:                        printf("Error - PC/Xe failed to reset\n");
                    186:                        return;
                    187:                }
                    188:                dgdelay(10);
                    189:        }
                    190:        outb(DG_IOB, 0x06);     /* enable memory */
                    191:        printf("PC/Xe passed reset\n");
                    192: 
                    193:        /*
                    194:         * Minimal test of PC/Xe's 64k of dual-ported RAM.
                    195:         */
                    196:        sfword(dg_ram_fp, 0xA55A);              /* store a "far" word */
                    197:        sfword(dg_ram_fp + 2, 0x3CC3);
                    198:        sfword(dg_ram_fp + 0xFFFC, 0xA55A);
                    199:        sfword(dg_ram_fp + 0xFFFE, 0x3CC3);
                    200:        if (ffword(dg_ram_fp) != 0xA55A         /* fetch a "far" word */
                    201:        ||  ffword(dg_ram_fp + 2) != 0x3CC3
                    202:        ||  ffword(dg_ram_fp + 0xFFFC) != 0xA55A
                    203:        ||  ffword(dg_ram_fp + 0xFFFE) != 0x3CC3) {
                    204:                printf("Error - PC/Xe failed memory test\n");
                    205:                return;
                    206:        } else
                    207:                printf("PC/Xe passed memory test\n");
                    208:                
                    209:        /*
                    210:         * Load and execute the PC/Xe BIOS
                    211:         */
                    212:        outb(DG_IOB, 0x06);     /* enable memory */
                    213:        dg_bios_wait = 1;
                    214:        printf("PC/Xe waiting for BIOS load\n");
                    215: }
                    216: 
                    217: static dgunload()
                    218: {
                    219:        if (board_ready) {
                    220:                board_ready = 0;
                    221:        }
                    222:        
                    223:        /*
                    224:         * Turn off and unhook interrupts from FEPOS
                    225:         */
                    226:        sfword(dg_ram_fp+INTERVAL, 0);  /* stop host interrupts */
                    227:        outb(DG_IOB, 0x04);             /* Disable DPRAM and hold FEP reset */
                    228:        clrivec(DG_INT);
                    229: 
                    230:        /*
                    231:         * We have to free up the selector now that we're done using it.
                    232:         */
                    233:        vrelse(dg_ram_fp);
                    234: }
                    235: 
                    236: /*
                    237:  * Open Routine.
                    238:  */
                    239: static dgopen( dev, mode )
                    240: dev_t dev;
                    241: {
                    242:        /*
                    243:         * If minor number has 128's bit set to 1, this is an attempt to
                    244:         * transfer the BIOS to the FEP.
                    245:         */
                    246:        if (minor(dev) & DG_BIOS_LOADER) {
                    247:                if (bios_loading) {
                    248:                        u.u_error = EDBUSY;
                    249:                        return;
                    250:                } else {
                    251:                        /*
                    252:                         * Only allow BIOS xfer if we are waiting for it.
                    253:                         */
                    254:                        if (dg_bios_wait) {
                    255:                                bios_loading = 1;
                    256:                                load_byte_ct = 0;
                    257:                        } else {
                    258:                                u.u_error = EIO;
                    259:                                return;
                    260:                        }
                    261:                }
                    262:        /*
                    263:         * If minor number has 64's bit set to 1, this is an attempt to
                    264:         * transfer the FEPOS to the FEP.
                    265:         */
                    266:        } else if (minor(dev) & DG_FEPOS_LOADER) {
                    267:                if (fepos_loading) {
                    268:                        u.u_error = EDBUSY;
                    269:                        return;
                    270:                } else {
                    271:                        /*
                    272:                         * Only allow FEPOS xfer if we are waiting for it.
                    273:                         */
                    274:                        if (dg_fepos_wait) {
                    275:                                fepos_loading = 1;
                    276:                                load_byte_ct = 0;
                    277:                        } else {
                    278:                                u.u_error = EIO;
                    279:                                return;
                    280:                        }
                    281:                }
                    282:        } else {
                    283:        }
                    284: }
                    285: 
                    286: /*
                    287:  * Close Routine.
                    288:  */
                    289: static dgclose( dev )
                    290: dev_t dev;
                    291: {
                    292:        /*
                    293:         * If minor number has 128's bit set to 1, this is an attempt to
                    294:         * transfer the BIOS to the FEP.
                    295:         */
                    296:        if (minor(dev) & DG_BIOS_LOADER) {
                    297:                bios_loading = 0;
                    298:                /*
                    299:                 * Only set dg_fepos_wait if enough bytes got written.
                    300:                 */
                    301:                if (load_byte_ct == DG_BIOS_LENGTH) {
                    302:                        /*
                    303:                         * After BIOS is xferred, try to finish
                    304:                         * PC/Xe initialization.
                    305:                         */
                    306:                        if (dginit2()) {
                    307:                                dg_bios_wait = 0;
                    308:                                dg_fepos_wait = 1;
                    309:                                printf("PC/Xe waiting for FEPOS load\n");
                    310:                        }
                    311:                }
                    312:        /*
                    313:         * If minor number has 64's bit set to 1, this is an attempt to
                    314:         * transfer the FEPOS to the FEP.
                    315:         */
                    316:        } else if (minor(dev) & DG_FEPOS_LOADER) {
                    317:                fepos_loading = 0;
                    318:                /*
                    319:                 * After BIOS is xferred, try to finish
                    320:                 * PC/Xe initialization.
                    321:                 */
                    322:                if (dginit3()) {
                    323:                        dg_fepos_wait = 0;
                    324:                        board_ready = 1;
                    325:                        printf("PC/Xe ready for use\n");
                    326:                }
                    327:        } else {
                    328:        }
                    329: }
                    330: 
                    331: /*
                    332:  * Read Routine.
                    333:  */
                    334: static dgread( dev, iop )
                    335: dev_t dev;
                    336: register IO * iop;
                    337: {
                    338: #if 0
                    339:        static int offset;
                    340:        int c;
                    341:        /*
                    342:         * Read a character code from video RAM
                    343:         * Start reading RAM just after where previous read ended
                    344:         *
                    345:         * Note that "offset" is the value of the displacement into
                    346:         * the screen RAM. Any expression which results in a value
                    347:         * which is less than DG_RAM_LENGTH is OK here.
                    348:         */
                    349:        while(iop->io_ioc) {
                    350:                c = ffbyte(dg_ram_fp + offset); /* fetch a "far" byte */
                    351:                if(ioputc(c, iop) == -1)
                    352:                        break;
                    353:                offset += 2;
                    354:                offset %= DG_RAM_LENGTH;
                    355:        }
                    356: #endif 
                    357: }
                    358: 
                    359: /*
                    360:  * Write Routine.
                    361:  */
                    362: static dgwrite( dev, iop )
                    363: dev_t dev;
                    364: register IO * iop;
                    365: {
                    366:        /*
                    367:         * If minor number has 128's bit set to 1, this is an attempt to
                    368:         * transfer the BIOS to the FEP.
                    369:         */
                    370:        if (minor(dev) & DG_BIOS_LOADER) {
                    371:                int c;
                    372: 
                    373:                while ((c = iogetc(iop)) >= 0 && load_byte_ct < DG_BIOS_LENGTH) {
                    374:                        sfbyte(dg_ram_fp + DG_BIOS_ADDR + load_byte_ct, c);
                    375:                        load_byte_ct++;
                    376:                }
                    377:        /*
                    378:         * If minor number has 64's bit set to 1, this is an attempt to
                    379:         * transfer the FEPOS to the FEP.
                    380:         */
                    381:        } else if (minor(dev) & DG_FEPOS_LOADER) {
                    382:                int c;
                    383: 
                    384:                while ((c = iogetc(iop)) >= 0) {
                    385:                        sfbyte(dg_ram_fp + DG_FEPOS_ADDR + load_byte_ct, c);
                    386:                        load_byte_ct++;
                    387:                }
                    388:        } else {
                    389:        }
                    390: }
                    391: 
                    392: /*
                    393:  * Delay for some number of clock ticks.
                    394:  * 286/386 kernel ticks are at 100Hz
                    395:  * Use kernel function sleep(), which is NOT the system call by that name.
                    396:  */
                    397: static void dgdelay(ticks)
                    398: int ticks;
                    399: {
                    400:        timeout(&delay_tim, ticks, wakeup, (int)&delay_tim);
                    401:        sleep((char *)&delay_tim, CVPAUSE, IVPAUSE, SVPAUSE);
                    402: }
                    403: 
                    404: /*
                    405:  * Start a timeout for some number of ticks.
                    406:  * Caller knows timer has expired when "dg_expired" goes to 1.
                    407:  *
                    408:  * Sample invocation:
                    409:  *     dg_start_timing(n);
                    410:  *     while (check for desired event fails) {
                    411:  *             if (dg_expired) {
                    412:  *                     ...failure stuff..
                    413:  *                     break;
                    414:  *             }
                    415:  *             dgdelay(m); <= needed to allow kernel to update timers
                    416:  *     }
                    417:  */
                    418: static dg_start_timing(ticks)
                    419: int ticks;
                    420: {
                    421:        dg_expired = 0;
                    422:        timeout(&timeout_tim, ticks, dg_stop_timing, 1);
                    423: }
                    424: 
                    425: /*
                    426:  * Stub function called only by dg_start_timing()
                    427:  */
                    428: static dg_stop_timing(flagval)
                    429: int flagval;
                    430: {
                    431:        dg_expired = flagval;
                    432: }
                    433: 
                    434: /*
                    435:  * Second part of PC/Xe initialization - done after the BIOS has been
                    436:  * written to dual-ported RAM.
                    437:  */
                    438: static int dginit2()
                    439: {
                    440:        /*
                    441:         * Execute FEP BIOS
                    442:         */
                    443:        sfword(dg_ram_fp + DG_BIOS_CONFIRM, 0); /* clear confirm word */
                    444:        outb(DG_IOB, 0x02);                     /* Release reset */
                    445:        dg_start_timing(1000);                  /* start 10-second timer */
                    446: 
                    447:        while (ffword(dg_ram_fp + DG_BIOS_CONFIRM) != BIOS_GOOD) {
                    448:                if (dg_expired) {
                    449:                        printf("Error - PC/Xe BIOS won't start\n");
                    450:                        return 0;
                    451:                }
                    452:                dgdelay(10);
                    453:        }
                    454:        printf("PC/Xe BIOS started\n");
                    455: 
                    456:        return 1;
                    457: }
                    458: 
                    459: /*
                    460:  * Third part of PC/Xe initialization - done after the FEPOS has been
                    461:  * written to dual-ported RAM.
                    462:  */
                    463: static int dginit3()
                    464: {
                    465:        int cmd;
                    466: 
                    467:        /*
                    468:         * Ask FEP BIOS to move FEPOS into host memory.
                    469:         */
                    470:        sfword(dg_ram_fp + DG_BIOS_REQ, 0x0002);
                    471:        sfword(dg_ram_fp + DG_BIOS_REQ+2, DG_MEMORY_SEG+0x200);
                    472:        sfword(dg_ram_fp + DG_BIOS_REQ+4, 0x0000);
                    473:        sfword(dg_ram_fp + DG_BIOS_REQ+6, 0x0200);
                    474:        sfword(dg_ram_fp + DG_BIOS_REQ+8, 0x0000);
                    475:        sfword(dg_ram_fp + DG_BIOS_REQ+0xA, 0x2000);
                    476:        outb(DG_IOB, 0x0A);                     /* Toggle interrupt */
                    477:        outb(DG_IOB, 0x02);
                    478:        dg_start_timing(100);                   /* start 1-second timer */
                    479:        while (ffword(dg_ram_fp + DG_BIOS_REQ) != 0) {
                    480:                if (dg_expired) {
                    481:                        printf("Error - PC/Xe FEPOS move failed\n");
                    482:                        return;
                    483:                }
                    484:                dgdelay(10);
                    485:        }
                    486:        printf("PC/Xe FEPOS relocated to host RAM\n");
                    487: 
                    488:        /*
                    489:         * Execute FEPOS
                    490:         */
                    491:        sfword(dg_ram_fp + DG_BIOS_REQ, 0x0001);
                    492:        sfword(dg_ram_fp + DG_BIOS_REQ+2, 0x0200);
                    493:        sfword(dg_ram_fp + DG_BIOS_REQ+4, 0x0004);
                    494:        sfword(dg_ram_fp + DG_FEP_CONFIRM, 0);  /* clear confirm word */
                    495:        outb(DG_IOB, 0x0A);                     /* Toggle interrupt */
                    496:        outb(DG_IOB, 0x02);
                    497:        dg_start_timing(500);                   /* start 5-second timer */
                    498:        while (ffword(dg_ram_fp + DG_FEP_CONFIRM) != FEPOS_GOOD) {
                    499:                if (dg_expired) {
                    500:                        printf("Error - PC/Xe FEPOS won't start\n");
                    501:                        printf("Failure code (%x)\n",
                    502:                                ffword(dg_ram_fp + DG_BIOS_REQ));
                    503:                        return 0;
                    504:                }
                    505:                dgdelay(10);
                    506:        }
                    507:        printf("PC/Xe FEPOS started\n");
                    508:        nport = ffbyte(dg_ram_fp+NPORT);
                    509: 
                    510:        /*
                    511:         * Enable and test interrupts from FEP
                    512:         */
                    513:        sfword(dg_ram_fp+INTERVAL, 1);          /* request host interrupts */
                    514:        cmd = ffword(dg_ram_fp+CIN);            /* get command pointer */
                    515:        sfword(dg_ram_fp+CSTART+cmd, 0xA1FF);   /* send an invalid command */
                    516:        sfword(dg_ram_fp+CSTART+cmd+2, 0xC3B2);
                    517:        sfword(dg_ram_fp+CIN, (cmd+4)&0x3ff);   /* update command pointer */
                    518:        dg_start_timing(100);                   /* start 1-second timer */
                    519:        test_irq = 1;
                    520:        while (test_irq) {
                    521:                if (dg_expired) {
                    522:                        printf("Error - PC/Xe no FEPOS interrupts\n");
                    523:                        return 0;
                    524:                }
                    525:                dgdelay(10);
                    526:        }
                    527:        printf("PC/Xe interrupts working\n");
                    528:        
                    529:        return 1;
                    530: }
                    531: 
                    532: /*
                    533:  * Interrupt handler.
                    534:  *
                    535:  * No specific action is needed to clear the interrupt
                    536:  * as it was a pulse sent from the FEPOS to host's IRQ line.
                    537:  */
                    538: static void dgintr()
                    539: {
                    540:        int cin, cout, ein, eout;
                    541:        unsigned char event[EVENT_LEN];
                    542:        int i;
                    543: 
                    544:        cin = ffword(dg_ram_fp+CIN);
                    545:        cout = ffword(dg_ram_fp+COUT);
                    546:        ein = ffword(dg_ram_fp+EIN);
                    547:        eout = ffword(dg_ram_fp+EOUT);
                    548: 
                    549:        if (board_ready) {
                    550:                /*
                    551:                 * Remove all packets from event queue.
                    552:                 */
                    553:                while (ffword(dg_ram_fp+EIN) != ffword(dg_ram_fp+EOUT)) {
                    554:                        eout = ffword(dg_ram_fp+EOUT);
                    555:                        for (i = 0; i < EVENT_LEN; i++)
                    556:                                event[i] = ffbyte(dg_ram_fp+ISTART+eout+i);
                    557:                        printf("%x %x %x %x\n", event[0],event[1],event[2],event[3]);   
                    558:                        sfword(dg_ram_fp+EOUT, (eout+4)&0x3ff);
                    559:                }
                    560:        } else {        /* e.g., if test_irq is TRUE */
                    561:                test_irq = 0;
                    562:                /*
                    563:                 * Attempt to clear the IRQ condition in the FEP.
                    564:                 */
                    565:                sfword(dg_ram_fp+EOUT, ffword(dg_ram_fp+EIN));
                    566:        }
                    567: }

unix.superglobalmegacorp.com

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