|
|
1.1 ! root 1: /* ! 2: * kernel/chr_drv/vt.c ! 3: * ! 4: * (C) 1992 obz under the linux copyright ! 5: */ ! 6: ! 7: #include <errno.h> ! 8: ! 9: #include <sys/types.h> ! 10: #include <sys/kd.h> ! 11: #include <sys/vt.h> ! 12: ! 13: #include <asm/io.h> ! 14: #include <asm/segment.h> ! 15: ! 16: #include <linux/sched.h> ! 17: #include <linux/tty.h> ! 18: #include <linux/kernel.h> ! 19: ! 20: #include "vt_kern.h" ! 21: ! 22: /* ! 23: * console (vt and kd) routines, as defined by usl svr4 manual ! 24: */ ! 25: ! 26: struct vt_cons vt_cons[MAX_CONSOLES]; ! 27: ! 28: extern int NR_CONSOLES; ! 29: extern unsigned char kleds; ! 30: extern unsigned char kraw; ! 31: extern unsigned char ke0; ! 32: ! 33: extern int sys_ioperm(unsigned long from, unsigned long num, int on); ! 34: extern void set_leds(void); ! 35: ! 36: /* ! 37: * these are the valid i/o ports we're allowed to change. they map all the ! 38: * video ports ! 39: */ ! 40: #define GPFIRST 0x3b4 ! 41: #define GPLAST 0x3df ! 42: #define GPNUM (GPLAST - GPFIRST + 1) ! 43: ! 44: /* ! 45: * turns on sound of some freq. 0 turns it off. ! 46: * stolen from console.c, so i'm not sure if its the correct interpretation ! 47: */ ! 48: static int ! 49: kiocsound(unsigned int freq) ! 50: { ! 51: if (freq == 0) { ! 52: /* disable counter 2 */ ! 53: outb(inb_p(0x61)&0xFC, 0x61); ! 54: } ! 55: else { ! 56: /* enable counter 2 */ ! 57: outb_p(inb_p(0x61)|3, 0x61); ! 58: /* set command for counter 2, 2 byte write */ ! 59: outb_p(0xB6, 0x43); ! 60: /* select desired HZ */ ! 61: outb_p(freq & 0xff, 0x42); ! 62: outb((freq >> 8) & 0xff, 0x42); ! 63: } ! 64: return 0; ! 65: } ! 66: ! 67: /* ! 68: * all the vt ioctls affect only consoles, so we reject all other ttys. ! 69: * we also have the capability to modify any console, not just the fg_console. ! 70: */ ! 71: int ! 72: vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg) ! 73: { ! 74: int console = dev ? dev - 1 : fg_console; ! 75: unsigned char ucval; ! 76: ! 77: if (!IS_A_CONSOLE(dev) || console < 0 || console >= NR_CONSOLES) ! 78: return -EINVAL; ! 79: ! 80: switch (cmd) { ! 81: case KIOCSOUND: ! 82: return kiocsound((unsigned int)arg); ! 83: ! 84: case KDGKBTYPE: ! 85: /* ! 86: * this is naive. ! 87: */ ! 88: verify_area((void *) arg, sizeof(unsigned char)); ! 89: put_fs_byte(KB_101, (unsigned char *) arg); ! 90: return 0; ! 91: ! 92: case KDADDIO: ! 93: case KDDELIO: ! 94: /* ! 95: * KDADDIO and KDDELIO may be able to add ports beyond what ! 96: * we reject here, but to be safe... ! 97: */ ! 98: if (arg < GPFIRST || arg > GPLAST) ! 99: return -EINVAL; ! 100: return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; ! 101: ! 102: case KDENABIO: ! 103: case KDDISABIO: ! 104: return sys_ioperm(GPFIRST, GPNUM, ! 105: (cmd == KDENABIO)) ? -ENXIO : 0; ! 106: ! 107: case KDSETMODE: ! 108: /* ! 109: * currently, setting the mode from KD_TEXT to KD_GRAPHICS ! 110: * doesn't do a whole lot. i'm not sure if it should do any ! 111: * restoration of modes or what... ! 112: */ ! 113: switch (arg) { ! 114: case KD_GRAPHICS: ! 115: break; ! 116: case KD_TEXT0: ! 117: case KD_TEXT1: ! 118: arg = KD_TEXT; ! 119: case KD_TEXT: ! 120: break; ! 121: default: ! 122: return -EINVAL; ! 123: } ! 124: vt_cons[console].vt_mode = arg; ! 125: return 0; ! 126: case KDGETMODE: ! 127: verify_area((void *) arg, sizeof(unsigned long)); ! 128: put_fs_long(vt_cons[console].vt_mode, (unsigned long *) arg); ! 129: return 0; ! 130: ! 131: case KDMAPDISP: ! 132: case KDUNMAPDISP: ! 133: /* ! 134: * these work like a combination of mmap and KDENABIO. ! 135: * this could be easily finished. ! 136: */ ! 137: return -EINVAL; ! 138: ! 139: case KDSKBMODE: ! 140: if (arg == K_RAW) { ! 141: if (console == fg_console) { ! 142: kraw = 1; ! 143: ke0 = 0; ! 144: } else { ! 145: vt_cons[console].vc_kbdraw = 1; ! 146: vt_cons[console].vc_kbde0 = 0; ! 147: } ! 148: } ! 149: else if (arg == K_XLATE) { ! 150: if (console == fg_console) ! 151: kraw = 0; ! 152: else ! 153: vt_cons[console].vc_kbdraw = 0; ! 154: } ! 155: else ! 156: return -EINVAL; ! 157: flush(tty->read_q); ! 158: flush(tty->secondary); ! 159: return 0; ! 160: case KDGKBMODE: ! 161: verify_area((void *) arg, sizeof(unsigned long)); ! 162: ucval = (console == fg_console) ? kraw : ! 163: vt_cons[console].vc_kbdraw; ! 164: put_fs_long(ucval ? K_RAW : K_XLATE, (unsigned long *) arg); ! 165: return 0; ! 166: ! 167: case KDGETLED: ! 168: verify_area((void *) arg, sizeof(unsigned char)); ! 169: ucval = (console == fg_console) ? kleds : ! 170: vt_cons[console].vc_kbdleds; ! 171: put_fs_byte((((ucval & 1) ? LED_SCR : 0) | ! 172: ((ucval & 2) ? LED_NUM : 0) | ! 173: ((ucval & 4) ? LED_CAP : 0)), ! 174: (unsigned char *) arg); ! 175: return 0; ! 176: case KDSETLED: ! 177: if (arg & ~7) ! 178: return -EINVAL; ! 179: ucval = (((arg & LED_SCR) ? 1 : 0) | ! 180: ((arg & LED_NUM) ? 2 : 0) | ! 181: ((arg & LED_CAP) ? 4 : 0)); ! 182: if (console == fg_console) { ! 183: kleds = ucval; ! 184: set_leds(); ! 185: } ! 186: else ! 187: vt_cons[console].vc_kbdleds = ucval; ! 188: return 0; ! 189: ! 190: default: ! 191: return -EINVAL; ! 192: } ! 193: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.