Annotation of lucent/sys/src/boot/pc/kbd.c, revision 1.1.1.1

1.1       root        1: #include       "u.h"
                      2: #include       "lib.h"
                      3: #include       "mem.h"
                      4: #include       "dat.h"
                      5: #include       "fns.h"
                      6: #include       "io.h"
                      7: 
                      8: #include       <libg.h>
                      9: 
                     10: enum {
                     11:        Data=           0x60,   /* data port */
                     12: 
                     13:        Status=         0x64,   /* status port */
                     14:         Inready=       0x01,   /*  input character ready */
                     15:         Outbusy=       0x02,   /*  output busy */
                     16:         Sysflag=       0x04,   /*  system flag */
                     17:         Cmddata=       0x08,   /*  cmd==0, data==1 */
                     18:         Inhibit=       0x10,   /*  keyboard/mouse inhibited */
                     19:         Minready=      0x20,   /*  mouse character ready */
                     20:         Rtimeout=      0x40,   /*  general timeout */
                     21:         Parity=        0x80,
                     22: 
                     23:        Cmd=            0x64,   /* command port (write only) */
                     24:  
                     25:        Spec=   0x80,
                     26: 
                     27:        PF=     Spec|0x20,      /* num pad function key */
                     28:        View=   Spec|0x00,      /* view (shift window up) */
                     29:        KF=     Spec|0x40,      /* function key */
                     30:        Shift=  Spec|0x60,
                     31:        Break=  Spec|0x61,
                     32:        Ctrl=   Spec|0x62,
                     33:        Latin=  Spec|0x63,
                     34:        Caps=   Spec|0x64,
                     35:        Num=    Spec|0x65,
                     36:        No=     Spec|0x7F,      /* no mapping */
                     37: 
                     38:        Home=   KF|13,
                     39:        Up=     KF|14,
                     40:        Pgup=   KF|15,
                     41:        Print=  KF|16,
                     42:        Left=   View,
                     43:        Right=  View,
                     44:        End=    '\r',
                     45:        Down=   View,
                     46:        Pgdown= View,
                     47:        Ins=    KF|20,
                     48:        Del=    0x7F,
                     49: };
                     50: 
                     51: uchar kbtab[] = 
                     52: {
                     53: [0x00] No,     0x1b,   '1',    '2',    '3',    '4',    '5',    '6',
                     54: [0x08] '7',    '8',    '9',    '0',    '-',    '=',    '\b',   '\t',
                     55: [0x10] 'q',    'w',    'e',    'r',    't',    'y',    'u',    'i',
                     56: [0x18] 'o',    'p',    '[',    ']',    '\n',   Ctrl,   'a',    's',
                     57: [0x20] 'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';',
                     58: [0x28] '\'',   '`',    Shift,  '\\',   'z',    'x',    'c',    'v',
                     59: [0x30] 'b',    'n',    'm',    ',',    '.',    '/',    Shift,  No,
                     60: [0x38] Latin,  ' ',    Caps,   KF|1,   KF|2,   KF|3,   KF|4,   KF|5,
                     61: [0x40] KF|6,   KF|7,   KF|8,   KF|9,   KF|10,  Num,    KF|12,  Home,
                     62: [0x48] No,     No,     No,     No,     No,     No,     No,     No,
                     63: [0x50] No,     No,     No,     No,     No,     No,     No,     KF|11,
                     64: [0x58] KF|12,  No,     No,     No,     No,     No,     No,     No,
                     65: };
                     66: 
                     67: uchar kbtabshift[] =
                     68: {
                     69: [0x00] No,     0x1b,   '!',    '@',    '#',    '$',    '%',    '^',
                     70: [0x08] '&',    '*',    '(',    ')',    '_',    '+',    '\b',   '\t',
                     71: [0x10] 'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I',
                     72: [0x18] 'O',    'P',    '{',    '}',    '\n',   Ctrl,   'A',    'S',
                     73: [0x20] 'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':',
                     74: [0x28] '"',    '~',    Shift,  '|',    'Z',    'X',    'C',    'V',
                     75: [0x30] 'B',    'N',    'M',    '<',    '>',    '?',    Shift,  No,
                     76: [0x38] Latin,  ' ',    Caps,   KF|1,   KF|2,   KF|3,   KF|4,   KF|5,
                     77: [0x40] KF|6,   KF|7,   KF|8,   KF|9,   KF|10,  Num,    KF|12,  Home,
                     78: [0x48] No,     No,     No,     No,     No,     No,     No,     No,
                     79: [0x50] No,     No,     No,     No,     No,     No,     No,     KF|11,
                     80: [0x58] KF|12,  No,     No,     No,     No,     No,     No,     No,
                     81: };
                     82: 
                     83: uchar kbtabesc1[] =
                     84: {
                     85: [0x00] No,     No,     No,     No,     No,     No,     No,     No,
                     86: [0x08] No,     No,     No,     No,     No,     No,     No,     No,
                     87: [0x10] No,     No,     No,     No,     No,     No,     No,     No,
                     88: [0x18] No,     No,     No,     No,     No,     Ctrl,   No,     No,
                     89: [0x20] No,     No,     No,     No,     No,     No,     No,     No,
                     90: [0x28] No,     No,     No,     No,     No,     No,     No,     No,
                     91: [0x30] No,     No,     No,     No,     No,     No,     No,     Print,
                     92: [0x38] Latin,  No,     No,     No,     No,     No,     No,     No,
                     93: [0x40] No,     No,     No,     No,     No,     No,     Break,  Home,
                     94: [0x48] Up,     Pgup,   No,     Down,   No,     Right,  No,     End,
                     95: [0x50] Left,   Pgdown, Ins,    Del,    No,     No,     No,     No,
                     96: [0x58] No,     No,     No,     No,     No,     No,     No,     No,
                     97: };
                     98: 
                     99: struct latin
                    100: {
                    101:        uchar   l;
                    102:        char    c[2];
                    103: }latintab[] = {
                    104:        '¡',   "!!",   /* spanish initial ! */
                    105:        '¢',   "c|",   /* cent */
                    106:        '¢',   "c$",   /* cent */
                    107:        '£',   "l$",   /* pound sterling */
                    108:        '¤',   "g$",   /* general currency */
                    109:        '¥',   "y$",   /* yen */
                    110:        '¥',   "j$",   /* yen */
                    111:        '¦',   "||",   /* broken vertical bar */
                    112:        '§',   "SS",   /* section symbol */
                    113:        '¨',   "\"\"", /* dieresis */
                    114:        '©',   "cr",   /* copyright */
                    115:        '©',   "cO",   /* copyright */
                    116:        'ª',   "sa",   /* super a, feminine ordinal */
                    117:        '«',   "<<",   /* left angle quotation */
                    118:        '¬',   "no",   /* not sign, hooked overbar */
                    119:        '­',   "--",   /* soft hyphen */
                    120:        '®',   "rg",   /* registered trademark */
                    121:        '¯',   "__",   /* macron */
                    122:        '°',   "s0",   /* degree (sup o) */
                    123:        '±',   "+-",   /* plus-minus */
                    124:        '²',   "s2",   /* sup 2 */
                    125:        '³',   "s3",   /* sup 3 */
                    126:        '´',   "''",   /* grave accent */
                    127:        'µ',   "mu",   /* mu */
                    128:        '¶',   "pg",   /* paragraph (pilcrow) */
                    129:        '·',   "..",   /* centered . */
                    130:        '¸',   ",,",   /* cedilla */
                    131:        '¹',   "s1",   /* sup 1 */
                    132:        'º',   "so",   /* sup o */
                    133:        '»',   ">>",   /* right angle quotation */
                    134:        '¼',   "14",   /* 1/4 */
                    135:        '½',   "12",   /* 1/2 */
                    136:        '¾',   "34",   /* 3/4 */
                    137:        '¿',   "??",   /* spanish initial ? */
                    138:        'À',   "A`",   /* A grave */
                    139:        'Á',   "A'",   /* A acute */
                    140:        'Â',   "A^",   /* A circumflex */
                    141:        'Ã',   "A~",   /* A tilde */
                    142:        'Ä',   "A\"",  /* A dieresis */
                    143:        'Ä',   "A:",   /* A dieresis */
                    144:        'Å',   "Ao",   /* A circle */
                    145:        'Å',   "AO",   /* A circle */
                    146:        'Æ',   "Ae",   /* AE ligature */
                    147:        'Æ',   "AE",   /* AE ligature */
                    148:        'Ç',   "C,",   /* C cedilla */
                    149:        'È',   "E`",   /* E grave */
                    150:        'É',   "E'",   /* E acute */
                    151:        'Ê',   "E^",   /* E circumflex */
                    152:        'Ë',   "E\"",  /* E dieresis */
                    153:        'Ë',   "E:",   /* E dieresis */
                    154:        'Ì',   "I`",   /* I grave */
                    155:        'Í',   "I'",   /* I acute */
                    156:        'Î',   "I^",   /* I circumflex */
                    157:        'Ï',   "I\"",  /* I dieresis */
                    158:        'Ï',   "I:",   /* I dieresis */
                    159:        'Ð',   "D-",   /* Eth */
                    160:        'Ñ',   "N~",   /* N tilde */
                    161:        'Ò',   "O`",   /* O grave */
                    162:        'Ó',   "O'",   /* O acute */
                    163:        'Ô',   "O^",   /* O circumflex */
                    164:        'Õ',   "O~",   /* O tilde */
                    165:        'Ö',   "O\"",  /* O dieresis */
                    166:        'Ö',   "O:",   /* O dieresis */
                    167:        'Ö',   "OE",   /* O dieresis */
                    168:        'Ö',   "Oe",   /* O dieresis */
                    169:        '×',   "xx",   /* times sign */
                    170:        'Ø',   "O/",   /* O slash */
                    171:        'Ù',   "U`",   /* U grave */
                    172:        'Ú',   "U'",   /* U acute */
                    173:        'Û',   "U^",   /* U circumflex */
                    174:        'Ü',   "U\"",  /* U dieresis */
                    175:        'Ü',   "U:",   /* U dieresis */
                    176:        'Ü',   "UE",   /* U dieresis */
                    177:        'Ü',   "Ue",   /* U dieresis */
                    178:        'Ý',   "Y'",   /* Y acute */
                    179:        'Þ',   "P|",   /* Thorn */
                    180:        'Þ',   "Th",   /* Thorn */
                    181:        'Þ',   "TH",   /* Thorn */
                    182:        'ß',   "ss",   /* sharp s */
                    183:        'à',   "a`",   /* a grave */
                    184:        'á',   "a'",   /* a acute */
                    185:        'â',   "a^",   /* a circumflex */
                    186:        'ã',   "a~",   /* a tilde */
                    187:        'ä',   "a\"",  /* a dieresis */
                    188:        'ä',   "a:",   /* a dieresis */
                    189:        'å',   "ao",   /* a circle */
                    190:        'æ',   "ae",   /* ae ligature */
                    191:        'ç',   "c,",   /* c cedilla */
                    192:        'è',   "e`",   /* e grave */
                    193:        'é',   "e'",   /* e acute */
                    194:        'ê',   "e^",   /* e circumflex */
                    195:        'ë',   "e\"",  /* e dieresis */
                    196:        'ë',   "e:",   /* e dieresis */
                    197:        'ì',   "i`",   /* i grave */
                    198:        'í',   "i'",   /* i acute */
                    199:        'î',   "i^",   /* i circumflex */
                    200:        'ï',   "i\"",  /* i dieresis */
                    201:        'ï',   "i:",   /* i dieresis */
                    202:        'ð',   "d-",   /* eth */
                    203:        'ñ',   "n~",   /* n tilde */
                    204:        'ò',   "o`",   /* o grave */
                    205:        'ó',   "o'",   /* o acute */
                    206:        'ô',   "o^",   /* o circumflex */
                    207:        'õ',   "o~",   /* o tilde */
                    208:        'ö',   "o\"",  /* o dieresis */
                    209:        'ö',   "o:",   /* o dieresis */
                    210:        'ö',   "oe",   /* o dieresis */
                    211:        '÷',   "-:",   /* divide sign */
                    212:        'ø',   "o/",   /* o slash */
                    213:        'ù',   "u`",   /* u grave */
                    214:        'ú',   "u'",   /* u acute */
                    215:        'û',   "u^",   /* u circumflex */
                    216:        'ü',   "u\"",  /* u dieresis */
                    217:        'ü',   "u:",   /* u dieresis */
                    218:        'ü',   "ue",   /* u dieresis */
                    219:        'ý',   "y'",   /* y acute */
                    220:        'þ',   "th",   /* thorn */
                    221:        'þ',   "p|",   /* thorn */
                    222:        'ÿ',   "y\"",  /* y dieresis */
                    223:        'ÿ',   "y:",   /* y dieresis */
                    224:        0,      0,
                    225: };
                    226: 
                    227: enum
                    228: {
                    229:        /* controller command byte */
                    230:        Cscs1=          (1<<6),         /* scan code set 1 */
                    231:        Cmousedis=      (1<<5),         /* mouse disable */
                    232:        Ckbddis=        (1<<4),         /* kbd disable */
                    233:        Csf=            (1<<2),         /* system flag */
                    234:        Cmouseint=      (1<<1),         /* mouse interrupt enable */
                    235:        Ckbdint=        (1<<0),         /* kbd interrupt enable */
                    236: };
                    237: 
                    238: static uchar ccc;
                    239: 
                    240: int
                    241: latin1(int k1, int k2)
                    242: {
                    243:        struct latin *l;
                    244: 
                    245:        for(l=latintab; l->l; l++)
                    246:                if(k1==l->c[0] && k2==l->c[1])
                    247:                        return l->l;
                    248:        return 0;
                    249: }
                    250: 
                    251: /*
                    252:  *  wait for output no longer busy
                    253:  */
                    254: static int
                    255: outready(void)
                    256: {
                    257:        int tries;
                    258: 
                    259:        for(tries = 0; (inb(Status) & Outbusy); tries++){
                    260:                if(tries > 500)
                    261:                        return -1;
                    262:                delay(2);
                    263:        }
                    264:        return 0;
                    265: }
                    266: 
                    267: /*
                    268:  *  wait for input
                    269:  */
                    270: static int
                    271: inready(void)
                    272: {
                    273:        int tries;
                    274: 
                    275:        for(tries = 0; !(inb(Status) & Inready); tries++){
                    276:                if(tries > 500)
                    277:                        return -1;
                    278:                delay(2);
                    279:        }
                    280:        return 0;
                    281: }
                    282: 
                    283: /*
                    284:  *  ask 8042 to enable the use of address bit 20
                    285:  */
                    286: void
                    287: i8042a20(void)
                    288: {
                    289:        outready();
                    290:        outb(Cmd, 0xD1);
                    291:        outready();
                    292:        outb(Data, 0xDF);
                    293:        outready();
                    294: }
                    295: 
                    296: /*
                    297:  *  ask 8042 to reset the machine
                    298:  */
                    299: void
                    300: i8042reset(void)
                    301: {
                    302:        ushort *s = (ushort*)(KZERO|0x472);
                    303:        int i, x;
                    304: 
                    305:        *s = 0x1234;            /* BIOS warm-boot flag */
                    306: 
                    307:        outready();
                    308:        outb(Cmd, 0xFE);        /* pulse reset line (means resend on AT&T machines) */
                    309:        outready();
                    310: 
                    311:        /*
                    312:         *  Pulse it by hand (old somewhat reliable)
                    313:         */
                    314:        x = 0xDF;
                    315:        for(i = 0; i < 5; i++){
                    316:                x ^= 1;
                    317:                outready();
                    318:                outb(Cmd, 0xD1);
                    319:                outready();
                    320:                outb(Data, x);  /* toggle reset */
                    321:                delay(100);
                    322:        }
                    323: }
                    324: 
                    325: /*
                    326:  *  keyboard interrupt
                    327:  */
                    328: int
                    329: kbdintr0(void)
                    330: {
                    331:        int s, c;
                    332:        static int esc1, esc2;
                    333:        static int shift;
                    334:        static int caps;
                    335:        static int ctl;
                    336:        static int num;
                    337:        static int lstate, k1, k2;
                    338:        int keyup;
                    339: 
                    340:        /*
                    341:         *  get status
                    342:         */
                    343:        s = inb(Status);
                    344:        if(!(s&Inready))
                    345:                return -1;
                    346: 
                    347:        /*
                    348:         *  get the character
                    349:         */
                    350:        c = inb(Data);
                    351: 
                    352:        /*
                    353:         *  e0's is the first of a 2 character sequence
                    354:         */
                    355:        if(c == 0xe0){
                    356:                esc1 = 1;
                    357:                return 0;
                    358:        } else if(c == 0xe1){
                    359:                esc2 = 2;
                    360:                return 0;
                    361:        }
                    362: 
                    363:        keyup = c&0x80;
                    364:        c &= 0x7f;
                    365:        if(c > sizeof kbtab){
                    366:                print("unknown key %ux\n", c|keyup);
                    367:                kbdchar(k1);
                    368:                return 0;
                    369:        }
                    370: 
                    371:        if(esc1){
                    372:                c = kbtabesc1[c];
                    373:                esc1 = 0;
                    374:                kbdchar(c);
                    375:                return 0;
                    376:        } else if(esc2){
                    377:                esc2--;
                    378:                return 0;
                    379:        } else if(shift)
                    380:                c = kbtabshift[c];
                    381:        else
                    382:                c = kbtab[c];
                    383: 
                    384:        if(caps && c<='z' && c>='a')
                    385:                c += 'A' - 'a';
                    386: 
                    387:        /*
                    388:         *  keyup only important for shifts
                    389:         */
                    390:        if(keyup){
                    391:                switch(c){
                    392:                case Shift:
                    393:                        shift = 0;
                    394:                        break;
                    395:                case Ctrl:
                    396:                        ctl = 0;
                    397:                        break;
                    398:                }
                    399:                return 0;
                    400:        }
                    401: 
                    402:        /*
                    403:         *  normal character
                    404:         */
                    405:        if(!(c & Spec)){
                    406:                if(ctl)
                    407:                        c &= 0x1f;
                    408:                switch(lstate){
                    409:                case 1:
                    410:                        k1 = c;
                    411:                        lstate = 2;
                    412:                        return 0;
                    413:                case 2:
                    414:                        k2 = c;
                    415:                        lstate = 0;
                    416:                        c = latin1(k1, k2);
                    417:                        if(c == 0){
                    418:                                kbdchar(k1);
                    419:                                c = k2;
                    420:                        }
                    421:                        /* fall through */
                    422:                default:
                    423:                        break;
                    424:                }
                    425:        } else {
                    426:                switch(c){
                    427:                case Caps:
                    428:                        caps ^= 1;
                    429:                        return 0;
                    430:                case Num:
                    431:                        num ^= 1;
                    432:                        return 0;
                    433:                case Shift:
                    434:                        shift = 1;
                    435:                        return 0;
                    436:                case Latin:
                    437:                        lstate = 1;
                    438:                        return 0;
                    439:                case Ctrl:
                    440:                        ctl = 1;
                    441:                        return 0;
                    442:                }
                    443:        }
                    444:        kbdchar(c);
                    445:        return 0;
                    446: }
                    447: 
                    448: static void
                    449: kbdintr(Ureg*, void*)
                    450: {
                    451:        while(kbdintr0() == 0)
                    452:                ;
                    453: }
                    454: 
                    455: void
                    456: kbdinit(void)
                    457: {
                    458:        int c;
                    459: 
                    460:        /* wait for a quiescent controller */
                    461:        while((c = inb(Status)) & (Outbusy | Inready))
                    462:                if(c & Inready)
                    463:                        inb(Data);
                    464: 
                    465:        /* get current controller command byte */
                    466:        outb(Cmd, 0x20);
                    467:        if(inready() < 0){
                    468:                print("kbdinit: can't read ccc\n");
                    469:                ccc = 0;
                    470:        } else
                    471:                ccc = inb(Data);
                    472: 
                    473:        /* enable kbd xfers and interrupts */
                    474:        ccc &= ~Ckbddis;
                    475:        ccc |= Csf | Ckbdint | Cscs1;
                    476:        if(outready() < 0)
                    477:                print("kbd init failed\n");
                    478:        outb(Cmd, 0x60);
                    479:        if(outready() < 0)
                    480:                print("kbd init failed\n");
                    481:        outb(Data, ccc);
                    482:        if(outready() < 0)
                    483:                print("kbd init failed\n");
                    484: 
                    485:        setvec(Kbdvec, kbdintr, 0);
                    486: }

unix.superglobalmegacorp.com

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