From: Paul M. <le...@us...> - 2002-04-21 20:02:44
|
Update of /cvsroot/linux-mips/linux/drivers/tc In directory usw-pr-cvs1:/tmp/cvs-serv3535/drivers/tc Modified Files: lk201.c lk201.h zs.c Log Message: More OSS syncing.. Index: lk201.c =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/tc/lk201.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- lk201.c 31 Oct 2001 18:53:12 -0000 1.4 +++ lk201.c 21 Apr 2002 20:01:15 -0000 1.5 @@ -4,7 +4,8 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 Maciej W. Rozycki <ma...@ds...> + * Copyright (C) 1999-2002 Harald Koerfgen <hk...@we...> + * Copyright (C) 2001, 2002 Maciej W. Rozycki <ma...@ds...> */ #include <linux/config.h> @@ -20,7 +21,6 @@ #include <linux/vt_kern.h> #include <asm/keyboard.h> -#include <asm/wbflush.h> #include <asm/dec/tc.h> #include <asm/dec/machtype.h> @@ -59,7 +59,6 @@ * This is used during keyboard initialisation */ static unsigned char lk201_reset_string[] = { - LK_CMD_LEDS_ON, LK_PARAM_LED_MASK(0xf), /* show we are resetting */ LK_CMD_SET_DEFAULTS, LK_CMD_MODE(LK_MODE_RPT_DOWN, 1), LK_CMD_MODE(LK_MODE_RPT_DOWN, 2), @@ -75,27 +74,85 @@ LK_CMD_MODE(LK_MODE_RPT_DOWN, 12), LK_CMD_MODE(LK_MODE_DOWN, 13), LK_CMD_MODE(LK_MODE_RPT_DOWN, 14), - LK_CMD_ENB_RPT, LK_CMD_DIS_KEYCLK, - LK_CMD_RESUME, LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4), - LK_CMD_LEDS_OFF, LK_PARAM_LED_MASK(0xf) }; static struct dec_serial* lk201kbd_info; -static int __init lk201_reset(struct dec_serial *info) +static int lk201_send(struct dec_serial *info, unsigned char ch) { - int i; - - for (i = 0; i < sizeof(lk201_reset_string); i++) - if (info->hook->poll_tx_char(info, lk201_reset_string[i])) { - printk(__FUNCTION__" transmit timeout\n"); + if (info->hook->poll_tx_char(info, ch)) { + printk(KERN_ERR "lk201: transmit timeout\n"); return -EIO; } return 0; } +static inline int lk201_get_id(struct dec_serial *info) +{ + return lk201_send(info, LK_CMD_REQ_ID); +} + +static int lk201_reset(struct dec_serial *info) +{ + int i, r; + + for (i = 0; i < sizeof(lk201_reset_string); i++) { + r = lk201_send(info, lk201_reset_string[i]); + if (r < 0) + return r; + } + return 0; +} + +static void lk201_report(unsigned char id[6]) +{ + char *report = "lk201: keyboard attached, "; + + switch (id[2]) { + case LK_STAT_PWRUP_OK: + printk(KERN_INFO "%sself-test OK\n", report); + break; + case LK_STAT_PWRUP_KDOWN: + /* The keyboard will resend the power-up ID + after all keys are released, so we don't + bother handling the error specially. Still + there may be a short-circuit inside. + */ + printk(KERN_ERR "%skey down (stuck?), code: 0x%02x\n", + report, id[3]); + break; + case LK_STAT_PWRUP_ERROR: + printk(KERN_ERR "%sself-test failure\n", report); + break; + default: + printk(KERN_ERR "%sunknown error: 0x%02x\n", + report, id[2]); + } +} + +static void lk201_id(unsigned char id[6]) +{ + /* + * Report whether there is an LK201 or an LK401 + * The LK401 has ALT keys... + */ + switch (id[4]) { + case 1: + printk(KERN_INFO "lk201: LK201 detected\n"); + break; + case 2: + printk(KERN_INFO "lk201: LK401 detected\n"); + break; + default: + printk(KERN_WARNING + "lk201: unknown keyboard detected, ID %d\n", id[4]); + printk(KERN_WARNING "lk201: ... please report to " + "<lin...@os...>\n"); + } +} + #define DEFAULT_KEYB_REP_DELAY (250/5) /* [5ms] */ #define DEFAULT_KEYB_REP_RATE 30 /* [cps] */ @@ -231,11 +288,49 @@ static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat) { + static unsigned char id[6]; + static int id_i; + static int shift_state = 0; static int prev_scancode; unsigned char c = scancodeRemap[ch]; - if (!stat || stat == 4) { + if (stat && stat != 4) { + printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n", + stat); + return; + } + + /* Assume this is a power-up ID. */ + if (ch == LK_STAT_PWRUP_ID && !id_i) { + id[id_i++] = ch; + return; + } + + /* Handle the power-up sequence. */ + if (id_i) { + id[id_i++] = ch; + if (id_i == 4) { + /* OK, the power-up concluded. */ + lk201_report(id); + if (id[2] == LK_STAT_PWRUP_OK) + lk201_get_id(lk201kbd_info); + else { + id_i = 0; + printk(KERN_ERR "lk201: keyboard power-up " + "error, skipping initialization\n"); + } + } else if (id_i == 6) { + /* We got the ID; report it and start an operation. */ + id_i = 0; + lk201_id(id); + lk201_reset(lk201kbd_info); + } + return; + } + + /* Everything else is a scancode/status response. */ + id_i = 0; switch (ch) { case LK_STAT_RESUME_ERR: case LK_STAT_ERROR: @@ -279,8 +374,6 @@ handle_scancode(c, 1); break; } - } else - printk("Error reading LKx01 keyboard: 0x%02x\n", stat); tasklet_schedule(&keyboard_tasklet); } @@ -290,45 +383,16 @@ static int __init lk201_init(struct dec_serial *info) { - unsigned int ch, id = 0; - int result; - - printk("DECstation LK keyboard driver v0.04... "); - - result = lk201_reset(info); - if (result) - return result; - mdelay(10); - - /* - * Detect whether there is an LK201 or an LK401 - * The LK401 has ALT keys... - */ - info->hook->poll_tx_char(info, LK_CMD_REQ_ID); - while ((ch = info->hook->poll_rx_char(info)) > 0) - id = ch; - - switch (id) { - case 1: - printk("LK201 detected\n"); - break; - case 2: - printk("LK401 detected\n"); - break; - default: - printk("unknown keyboard, ID %d,\n", id); - printk("... please report to <lin...@os...>\n"); - } - - /* - * now we're ready - */ - info->hook->rx_char = lk201_kbd_rx_char; - + /* First install handlers. */ lk201kbd_info = info; kbd_rate = lk201kbd_rate; kd_mksound = lk201kd_mksound; + info->hook->rx_char = lk201_kbd_rx_char; + + /* Then just issue a reset -- the handlers will do the rest. */ + lk201_send(info, LK_CMD_POWER_UP); + return 0; } @@ -337,26 +401,29 @@ extern int register_zs_hook(unsigned int, struct zs_hook *); extern int unregister_zs_hook(unsigned int); + /* Maxine uses LK501 at the Access.Bus. */ + if (mips_machtype == MACH_DS5000_XX) + return; + + printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n"); + if (TURBOCHANNEL) { - if (mips_machtype != MACH_DS5000_XX) { /* - * This is not a MAXINE, so: - * * kbd_init_hw() is being called before * rs_init() so just register the kbd hook * and let zs_init do the rest :-) */ if (mips_machtype == MACH_DS5000_200) - printk("LK201 Support for DS5000/200 not yet ready ...\n"); + printk(KERN_ERR "lk201: support for DS5000/200 " + "not yet ready.\n"); else if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook)) unregister_zs_hook(KEYB_LINE); - } } else { /* * TODO: modify dz.c to allow similar hooks * for LK201 handling on DS2100, DS3100, and DS5000/200 */ - printk("LK201 Support for DS3100 not yet ready ...\n"); + printk(KERN_ERR "lk201: support for DS3100 not yet ready.\n"); } } Index: lk201.h =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/tc/lk201.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- lk201.h 31 Oct 2001 18:53:12 -0000 1.2 +++ lk201.h 21 Apr 2002 20:01:15 -0000 1.3 @@ -20,7 +20,7 @@ #define LK_CMD_ENB_BELL 0x23 /* enable the bell */ /* 1st param: volume */ #define LK_CMD_BELL 0xa7 /* emit a bell */ -#define LK_CMD_TMP_NORPT 0xc1 /* disable typematic */ +#define LK_CMD_TMP_NORPT 0xd1 /* disable typematic */ /* for the currently pressed key */ #define LK_CMD_ENB_RPT 0xe3 /* enable typematic */ /* for RPT_DOWN groups */ @@ -33,15 +33,15 @@ #define LK_CMD_TEST_EXIT 0x80 /* exit the factory test mode */ #define LK_CMD_SET_DEFAULTS 0xd3 /* set power-up defaults */ -#define LK_CMD_MODE(m,div) (LK_PARAM|(((div)&0xf)<<3)|m) +#define LK_CMD_MODE(m,div) (LK_PARAM|(((div)&0xf)<<3)|(((m)&0x3)<<1)) /* select the repeat mode */ /* for the selected key group */ -#define LK_CMD_MODE_AR(m,div) ((((div)&0xf)<<3)|m) +#define LK_CMD_MODE_AR(m,div) ((((div)&0xf)<<3)|(((m)&0x3)<<1)) /* select the repeat mode */ /* and the repeat register */ /* for the selected key group */ /* 1st param: register number */ -#define LK_CMD_RPT_RATE(r) (0x04|((((r)&0x3)<<1))) +#define LK_CMD_RPT_RATE(r) (0x78|(((r)&0x3)<<1)) /* set the delay and repeat rate */ /* for the selected repeat register */ /* 1st param: initial delay */ @@ -59,8 +59,8 @@ /* mode set command details, div is a key group number */ #define LK_MODE_DOWN 0x0 /* make only */ -#define LK_MODE_RPT_DOWN 0x2 /* make and typematic */ -#define LK_MODE_DOWN_UP 0x6 /* make and release */ +#define LK_MODE_RPT_DOWN 0x1 /* make and typematic */ +#define LK_MODE_DOWN_UP 0x3 /* make and release */ /* there are 4 repeat registers */ #define LK_PARAM_AR(r) (LK_PARAM|((v)&0x3)) @@ -115,6 +115,7 @@ /* the keycode follows */ #define LK_STAT_MODE_ACK 0xba /* the mode command succeeded */ +#define LK_STAT_PWRUP_ID 0x01 /* the power-up response start mark */ #define LK_STAT_PWRUP_OK 0x00 /* the power-up self test OK */ #define LK_STAT_PWRUP_KDOWN 0x3d /* a key was down during the test */ #define LK_STAT_PWRUP_ERROR 0x3e /* keyboard self test failure */ Index: zs.c =================================================================== RCS file: /cvsroot/linux-mips/linux/drivers/tc/zs.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- zs.c 14 Feb 2002 20:36:59 -0000 1.4 +++ zs.c 21 Apr 2002 20:01:15 -0000 1.5 @@ -6,7 +6,7 @@ * * DECstation changes * Copyright (C) 1998-2000 Harald Koerfgen - * Copyright (C) 2000,2001 Maciej W. Rozycki <ma...@ds...> + * Copyright (C) 2000, 2001, 2002 Maciej W. Rozycki <ma...@ds...> * * For the rest of the code the original Copyright applies: * Copyright (C) 1996 Paul Mackerras (Pau...@cs...) @@ -107,7 +107,8 @@ unsigned long scc1; int channel_a_offset; int channel_b_offset; - int irq; + int irq0; + int irq1; int clock; }; @@ -119,7 +120,8 @@ scc1 : SCC1, channel_a_offset : 1, channel_b_offset : 9, - irq : SERIAL, + irq0 : -1, + irq1 : -1, clock : ZS_CLOCK }; #endif @@ -129,7 +131,8 @@ scc1 : UNI_SCC1, channel_a_offset : 9, channel_b_offset : 1, - irq : BAGET_SCC_IRQ, + irq0 : BAGET_SCC_IRQ, + irq1 : BAGET_SCC_IRQ, clock : 14745000 }; #endif @@ -409,7 +412,7 @@ stat = read_zsreg(info->zs_channel, R1); ch = read_zsdata(info->zs_channel); - if (!tty && !info->hook && !info->hook->rx_char) + if (!tty && (!info->hook || !info->hook->rx_char)) continue; if (tty_break) { @@ -471,7 +474,9 @@ *tty->flip.flag_buf_ptr++ = flag; *tty->flip.char_buf_ptr++ = ch; +#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) ignore_char: +#endif } if (tty) tty_flip_buffer_push(tty); @@ -522,9 +527,9 @@ if (info->zs_channel != info->zs_chan_a) { - /* FIXEM: Check for DCD transitions */ - if (((stat ^ info->read_reg_zero) & DCD) != 0 - && info->tty && !C_CLOCAL(info->tty)) { + /* Check for DCD transitions */ + if (info->tty && !C_CLOCAL(info->tty) && + ((stat ^ info->read_reg_zero) & DCD) != 0 ) { if (stat & DCD) { wake_up_interruptible(&info->open_wait); } else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) { @@ -1719,7 +1724,7 @@ static void __init show_serial_version(void) { - printk("DECstation Z8530 serial driver version 0.05\n"); + printk("DECstation Z8530 serial driver version 0.07\n"); } /* Initialize Z8530s zs_channels @@ -1749,16 +1754,21 @@ system_base = 0xbf800000; n_chips = 2; zs_parms = &ds_parms; + zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; + zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1]; break; case MACH_DS5000_1XX: system_base = 0xbc000000; n_chips = 2; zs_parms = &ds_parms; + zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; + zs_parms->irq1 = dec_interrupt[DEC_IRQ_SCC1]; break; case MACH_DS5000_XX: system_base = 0xbc000000; n_chips = 1; zs_parms = &ds_parms; + zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; break; #endif #ifdef CONFIG_BAGET_MIPS @@ -1807,7 +1817,11 @@ ZS_CHAN_IO_SIZE, "SCC"); #endif zs_soft[n_channels].zs_channel = &zs_channels[n_channels]; - zs_soft[n_channels].irq = zs_parms->irq; + /* HACK alert! */ + if (!(chip & 1)) + zs_soft[n_channels].irq = zs_parms->irq0; + else + zs_soft[n_channels].irq = zs_parms->irq1; /* * Identification of channel A. Location of channel A @@ -1932,34 +1946,30 @@ save_flags(flags); cli(); for (channel = 0; channel < zs_channels_found; ++channel) { - if (zs_soft[channel].hook && - zs_soft[channel].hook->init_channel) - (*zs_soft[channel].hook->init_channel) - (&zs_soft[channel]); + if (request_irq(zs_soft[channel].irq, rs_interrupt, SA_SHIRQ, + "scc", &zs_soft[channel])) + printk(KERN_ERR "decserial: can't get irq %d\n", + zs_soft[channel].irq); zs_soft[channel].clk_divisor = 16; zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - - if (request_irq(zs_parms->irq, rs_interrupt, SA_SHIRQ, - "SCC", &zs_soft[channel])) - printk(KERN_ERR "decserial: can't get irq %d\n", - zs_parms->irq); } - for (info = zs_chain, i = 0; info; info = info->zs_next, i++) - { - if (info->hook && info->hook->init_info) { - (*info->hook->init_info)(info); + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) { + + /* Needed before interrupts are enabled. */ + info->tty = 0; + info->x_char = 0; + + if (info->hook && info->hook->init_info) continue; - } + info->magic = SERIAL_MAGIC; info->port = (int) info->zs_channel->control; info->line = i; - info->tty = 0; info->custom_divisor = 16; info->close_delay = 50; info->closing_wait = 3000; - info->x_char = 0; info->event = 0; info->count = 0; info->blocked_open = 0; @@ -1981,6 +1991,18 @@ restore_flags(flags); + for (channel = 0; channel < zs_channels_found; ++channel) { + if (zs_soft[channel].hook && + zs_soft[channel].hook->init_channel) + (*zs_soft[channel].hook->init_channel) + (&zs_soft[channel]); + } + + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) { + if (info->hook && info->hook->init_info) + (*info->hook->init_info)(info); + } + return 0; } @@ -2010,31 +2032,18 @@ if(chan) { int loops = 10000; -// int nine = read_zsreg(chan, R9); - - RECOVERY_DELAY; -// write_zsreg(chan, R9, nine & ~MIE); - wbflush(); - RECOVERY_DELAY; - while (!(*(chan->control) & Tx_BUF_EMP) && --loops) - RECOVERY_DELAY; + while (loops && !(read_zsreg(chan, 0) & Tx_BUF_EMP)) + loops--; if (loops) { + write_zsdata(chan, ch); ret = 0; - *(chan->data) = ch; - wbflush(); - RECOVERY_DELAY; } else ret = -EAGAIN; -// write_zsreg(chan, R9, nine); - wbflush(); - RECOVERY_DELAY; - return ret; - } - + } else return -ENODEV; } @@ -2047,7 +2056,7 @@ if(chan) { int loops = 10000; - while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) + while (loops && !(read_zsreg(chan, 0) & Rx_CH_AV)) loops--; if (loops) |