Annotation of lucent/sys/src/boot/pc/kbd.c, revision 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.