From: Ralf Baechle Update Turbochannel code. Right now the code is basically still at the state of 2.3; with this patch applied it'll roughly on the level of the TC code in early 2.4 with a bunch of 2.6 fixes on top. Not great but will bring the code closer into touch with reality until Maciej has a chance to finally tackle things. Signed-off-by: Andrew Morton --- 25-akpm/drivers/tc/lk201.c | 443 ++++++++++++++++++++++--------- 25-akpm/drivers/tc/lk201.h | 144 +++++++--- 25-akpm/drivers/tc/tc.c | 179 ++++++------ 25-akpm/drivers/tc/zs.c | 639 +++++++++++++++++++++------------------------ 25-akpm/drivers/tc/zs.h | 68 ++-- 5 files changed, 862 insertions(+), 611 deletions(-) diff -puN drivers/tc/lk201.c~mips-decstation-turbochannel-updates drivers/tc/lk201.c --- 25/drivers/tc/lk201.c~mips-decstation-turbochannel-updates 2005-01-29 11:26:05.128968200 -0800 +++ 25-akpm/drivers/tc/lk201.c 2005-01-29 11:26:05.151964704 -0800 @@ -4,20 +4,44 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * + * Copyright (C) 1999-2002 Harald Koerfgen + * Copyright (C) 2001, 2002, 2003, 2004 Maciej W. Rozycki */ + +#include + #include +#include #include #include #include #include #include -#include +#include +#include + +#include #include #include +#include -#include "zs.h" #include "lk201.h" +/* + * Only handle DECstations that have an LK201 interface. + * Maxine uses LK501 at the Access.Bus and various DECsystems + * have no keyboard interface at all. + */ +#define LK_IFACE (mips_machtype == MACH_DS23100 || \ + mips_machtype == MACH_DS5000_200 || \ + mips_machtype == MACH_DS5000_1XX || \ + mips_machtype == MACH_DS5000_2X0) +/* + * These use the Z8530 SCC. Others use the DZ11. + */ +#define LK_IFACE_ZS (mips_machtype == MACH_DS5000_1XX || \ + mips_machtype == MACH_DS5000_2X0) + /* Simple translation table for the SysRq keys */ #ifdef CONFIG_MAGIC_SYSRQ @@ -27,25 +51,29 @@ */ unsigned char lk201_sysrq_xlate[128]; unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate; + +unsigned char kbd_sysrq_key = -1; #endif #define KEYB_LINE 3 -static int __init lk201_init(struct dec_serial *); -static void __init lk201_info(struct dec_serial *); -static void lk201_kbd_rx_char(unsigned char, unsigned char); - -struct zs_hook lk201_kbdhook = { - .init_channel = lk201_init, - .init_info = lk201_info, - .cflags = B4800 | CS8 | CSTOPB | CLOCAL +static int __init lk201_init(void *); +static void __init lk201_info(void *); +static void lk201_rx_char(unsigned char, unsigned char); + +static struct dec_serial_hook lk201_hook = { + .init_channel = lk201_init, + .init_info = lk201_info, + .rx_char = NULL, + .poll_rx_char = NULL, + .poll_tx_char = NULL, + .cflags = B4800 | CS8 | CSTOPB | CLOCAL, }; /* * 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), @@ -61,28 +89,199 @@ static unsigned char lk201_reset_string[ 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 int __init lk201_reset(struct dec_serial *info) +static void *lk201_handle; + +static int lk201_send(unsigned char ch) +{ + if (lk201_hook.poll_tx_char(lk201_handle, ch)) { + printk(KERN_ERR "lk201: transmit timeout\n"); + return -EIO; + } + return 0; +} + +static inline int lk201_get_id(void) +{ + return lk201_send(LK_CMD_REQ_ID); +} + +static int lk201_reset(void) +{ + int i, r; + + for (i = 0; i < sizeof(lk201_reset_string); i++) { + r = lk201_send(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; + case 3: + printk(KERN_INFO "lk201: LK443 detected\n"); + break; + case 4: + printk(KERN_INFO "lk201: LK421 detected\n"); + break; + default: + printk(KERN_WARNING + "lk201: unknown keyboard detected, ID %d\n", id[4]); + printk(KERN_WARNING "lk201: ... please report to " + "\n"); + } +} + +#define DEFAULT_KEYB_REP_DELAY (250/5) /* [5ms] */ +#define DEFAULT_KEYB_REP_RATE 30 /* [cps] */ + +static struct kbd_repeat kbdrate = { + DEFAULT_KEYB_REP_DELAY, + DEFAULT_KEYB_REP_RATE +}; + +static void parse_kbd_rate(struct kbd_repeat *r) { + if (r->delay <= 0) + r->delay = kbdrate.delay; + if (r->rate <= 0) + r->rate = kbdrate.rate; + + if (r->delay < 5) + r->delay = 5; + if (r->delay > 630) + r->delay = 630; + if (r->rate < 12) + r->rate = 12; + if (r->rate > 127) + r->rate = 127; + if (r->rate == 125) + r->rate = 124; +} + +static int write_kbd_rate(struct kbd_repeat *rep) +{ + int delay, rate; int i; - for (i = 0; i < sizeof(lk201_reset_string); i++) - if (info->hook->poll_tx_char(info, lk201_reset_string[i])) { - printk("%s transmit timeout\n", __FUNCTION__); - return -EIO; - } + delay = rep->delay / 5; + rate = rep->rate; + for (i = 0; i < 4; i++) { + if (lk201_hook.poll_tx_char(lk201_handle, + LK_CMD_RPT_RATE(i))) + return 1; + if (lk201_hook.poll_tx_char(lk201_handle, + LK_PARAM_DELAY(delay))) + return 1; + if (lk201_hook.poll_tx_char(lk201_handle, + LK_PARAM_RATE(rate))) + return 1; + } return 0; } +static int lk201_kbd_rate(struct kbd_repeat *rep) +{ + if (rep == NULL) + return -EINVAL; + + parse_kbd_rate(rep); + + if (write_kbd_rate(rep)) { + memcpy(rep, &kbdrate, sizeof(struct kbd_repeat)); + return -EIO; + } + + memcpy(&kbdrate, rep, sizeof(struct kbd_repeat)); + + return 0; +} + +static void lk201_kd_mksound(unsigned int hz, unsigned int ticks) +{ + if (!ticks) + return; + + /* + * Can't set frequency and we "approximate" + * duration by volume. ;-) + */ + ticks /= HZ / 32; + if (ticks > 7) + ticks = 7; + ticks = 7 - ticks; + + if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_ENB_BELL)) + return; + if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_VOLUME(ticks))) + return; + if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_BELL)) + return; +} + void kbd_leds(unsigned char leds) { - return; + unsigned char l = 0; + + if (!lk201_handle) /* FIXME */ + return; + + /* FIXME -- Only Hold and Lock LEDs for now. --macro */ + if (leds & LED_SCR) + l |= LK_LED_HOLD; + if (leds & LED_CAP) + l |= LK_LED_LOCK; + + if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_ON)) + return; + if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(l))) + return; + if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_OFF)) + return; + if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(~l))) + return; } int kbd_setkeycode(unsigned int scancode, unsigned int keycode) @@ -107,128 +306,136 @@ char kbd_unexpected_up(unsigned char key return 0x80; } -static void lk201_kbd_rx_char(unsigned char ch, unsigned char stat) +static void lk201_rx_char(unsigned char ch, unsigned char fl) { + 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) { - switch (ch) { - case LK_KEY_ACK: - break; - case LK_KEY_LOCK: - shift_state ^= LK_LOCK; - handle_scancode(c, shift_state && LK_LOCK ? 1 : 0); - break; - case LK_KEY_SHIFT: - shift_state ^= LK_SHIFT; - handle_scancode(c, shift_state && LK_SHIFT ? 1 : 0); - break; - case LK_KEY_CTRL: - shift_state ^= LK_CTRL; - handle_scancode(c, shift_state && LK_CTRL ? 1 : 0); - break; - case LK_KEY_COMP: - shift_state ^= LK_COMP; - handle_scancode(c, shift_state && LK_COMP ? 1 : 0); - break; - case LK_KEY_RELEASE: - if (shift_state & LK_SHIFT) - handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0); - if (shift_state & LK_CTRL) - handle_scancode(scancodeRemap[LK_KEY_CTRL], 0); - if (shift_state & LK_COMP) - handle_scancode(scancodeRemap[LK_KEY_COMP], 0); - if (shift_state & LK_LOCK) - handle_scancode(scancodeRemap[LK_KEY_LOCK], 0); - shift_state = 0; - break; - case LK_KEY_REPEAT: - handle_scancode(prev_scancode, 1); - break; - default: - prev_scancode = c; - handle_scancode(c, 1); - break; + if (fl != TTY_NORMAL && fl != TTY_OVERRUN) { + printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n", fl); + 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(); + 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 operation. */ + id_i = 0; + lk201_id(id); + lk201_reset(); } - } else - printk("Error reading LKx01 keyboard: 0x%02x\n", stat); + return; + } + + /* Everything else is a scancode/status response. */ + id_i = 0; + switch (ch) { + case LK_STAT_RESUME_ERR: + case LK_STAT_ERROR: + case LK_STAT_INHIBIT_ACK: + case LK_STAT_TEST_ACK: + case LK_STAT_MODE_KEYDOWN: + case LK_STAT_MODE_ACK: + break; + case LK_KEY_LOCK: + shift_state ^= LK_LOCK; + handle_scancode(c, (shift_state & LK_LOCK) ? 1 : 0); + break; + case LK_KEY_SHIFT: + shift_state ^= LK_SHIFT; + handle_scancode(c, (shift_state & LK_SHIFT) ? 1 : 0); + break; + case LK_KEY_CTRL: + shift_state ^= LK_CTRL; + handle_scancode(c, (shift_state & LK_CTRL) ? 1 : 0); + break; + case LK_KEY_COMP: + shift_state ^= LK_COMP; + handle_scancode(c, (shift_state & LK_COMP) ? 1 : 0); + break; + case LK_KEY_RELEASE: + if (shift_state & LK_SHIFT) + handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0); + if (shift_state & LK_CTRL) + handle_scancode(scancodeRemap[LK_KEY_CTRL], 0); + if (shift_state & LK_COMP) + handle_scancode(scancodeRemap[LK_KEY_COMP], 0); + if (shift_state & LK_LOCK) + handle_scancode(scancodeRemap[LK_KEY_LOCK], 0); + shift_state = 0; + break; + case LK_KEY_REPEAT: + handle_scancode(prev_scancode, 1); + break; + default: + prev_scancode = c; + handle_scancode(c, 1); + break; + } + tasklet_schedule(&keyboard_tasklet); } -static void __init lk201_info(struct dec_serial *info) +static void __init lk201_info(void *handle) { } -static int __init lk201_init(struct dec_serial *info) +static int __init lk201_init(void *handle) { - unsigned int ch, id = 0; - int result; - - printk("DECstation LK keyboard driver v0.04... "); + /* First install handlers. */ + lk201_handle = handle; + kbd_rate = lk201_kbd_rate; + kd_mksound = lk201_kd_mksound; - 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 \n"); - } + lk201_hook.rx_char = lk201_rx_char; - /* - * now we're ready - */ - info->hook->rx_char = lk201_kbd_rx_char; + /* Then just issue a reset -- the handlers will do the rest. */ + lk201_send(LK_CMD_POWER_UP); return 0; } void __init kbd_init_hw(void) { - 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 (!LK_IFACE) + return; - 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"); - else - if(!register_zs_hook(KEYB_LINE, &lk201_kbdhook)) - unregister_zs_hook(KEYB_LINE); - } + printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n"); + + if (LK_IFACE_ZS) { + /* + * kbd_init_hw() is being called before + * rs_init() so just register the kbd hook + * and let zs_init do the rest :-) + */ + if (!register_dec_serial_hook(KEYB_LINE, &lk201_hook)) + unregister_dec_serial_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 DZ11 not yet ready.\n"); } } - - - - diff -puN drivers/tc/lk201.h~mips-decstation-turbochannel-updates drivers/tc/lk201.h --- 25/drivers/tc/lk201.h~mips-decstation-turbochannel-updates 2005-01-29 11:26:05.130967896 -0800 +++ 25-akpm/drivers/tc/lk201.h 2005-01-29 11:26:05.146965464 -0800 @@ -2,52 +2,124 @@ * Commands to the keyboard processor */ -#define LK_PARAM 0x80 /* start/end parameter list */ +#define LK_PARAM 0x80 /* start/end parameter list */ -#define LK_CMD_RESUME 0x8b -#define LK_CMD_INHIBIT 0xb9 -#define LK_CMD_LEDS_ON 0x13 /* 1 param: led bitmask */ -#define LK_CMD_LEDS_OFF 0x11 /* 1 param: led bitmask */ -#define LK_CMD_DIS_KEYCLK 0x99 -#define LK_CMD_ENB_KEYCLK 0x1b /* 1 param: volume */ -#define LK_CMD_DIS_CTLCLK 0xb9 -#define LK_CMD_ENB_CTLCLK 0xbb -#define LK_CMD_SOUND_CLK 0x9f -#define LK_CMD_DIS_BELL 0xa1 -#define LK_CMD_ENB_BELL 0x23 /* 1 param: volume */ -#define LK_CMD_BELL 0xa7 -#define LK_CMD_TMP_NORPT 0xc1 -#define LK_CMD_ENB_RPT 0xe3 -#define LK_CMD_DIS_RPT 0xe1 -#define LK_CMD_RPT_TO_DOWN 0xd9 -#define LK_CMD_REQ_ID 0xab -#define LK_CMD_POWER_UP 0xfd -#define LK_CMD_TEST_MODE 0xcb -#define LK_CMD_SET_DEFAULTS 0xd3 +#define LK_CMD_RESUME 0x8b /* resume transmission to the host */ +#define LK_CMD_INHIBIT 0x89 /* stop transmission to the host */ +#define LK_CMD_LEDS_ON 0x13 /* light LEDs */ + /* 1st param: led bitmask */ +#define LK_CMD_LEDS_OFF 0x11 /* turn off LEDs */ + /* 1st param: led bitmask */ +#define LK_CMD_DIS_KEYCLK 0x99 /* disable the keyclick */ +#define LK_CMD_ENB_KEYCLK 0x1b /* enable the keyclick */ + /* 1st param: volume */ +#define LK_CMD_DIS_CTLCLK 0xb9 /* disable the Ctrl keyclick */ +#define LK_CMD_ENB_CTLCLK 0xbb /* enable the Ctrl keyclick */ +#define LK_CMD_SOUND_CLK 0x9f /* emit a keyclick */ +#define LK_CMD_DIS_BELL 0xa1 /* disable the bell */ +#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 0xd1 /* disable typematic */ + /* for the currently pressed key */ +#define LK_CMD_ENB_RPT 0xe3 /* enable typematic */ + /* for RPT_DOWN groups */ +#define LK_CMD_DIS_RPT 0xe1 /* disable typematic */ + /* for RPT_DOWN groups */ +#define LK_CMD_RPT_TO_DOWN 0xd9 /* set RPT_DOWN groups to DOWN */ +#define LK_CMD_REQ_ID 0xab /* request the keyboard ID */ +#define LK_CMD_POWER_UP 0xfd /* init power-up sequence */ +#define LK_CMD_TEST_MODE 0xcb /* enter the factory test mode */ +#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)&0x3)<<1)) + /* select the repeat mode */ + /* for the selected key group */ +#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) (0x78|(((r)&0x3)<<1)) + /* set the delay and repeat rate */ + /* for the selected repeat register */ + /* 1st param: initial delay */ + /* 2nd param: repeat rate */ /* there are 4 leds, represent them in the low 4 bits of a byte */ -#define LK_PARAM_LED_MASK(ledbmap) (LK_PARAM|(ledbmap)) +#define LK_PARAM_LED_MASK(ledbmap) (LK_PARAM|((ledbmap)&0xf)) +#define LK_LED_WAIT 0x1 /* Wait LED */ +#define LK_LED_COMP 0x2 /* Compose LED */ +#define LK_LED_LOCK 0x4 /* Lock LED */ +#define LK_LED_HOLD 0x8 /* Hold Screen LED */ /* max volume is 0, lowest is 0x7 */ -#define LK_PARAM_VOLUME(v) (LK_PARAM|((v)&0x7)) +#define LK_PARAM_VOLUME(v) (LK_PARAM|((v)&0x7)) -/* mode set command(s) details */ -#define LK_MODE_DOWN 0x0 -#define LK_MODE_RPT_DOWN 0x2 -#define LK_MODE_DOWN_UP 0x6 -#define LK_CMD_MODE(m,div) (LK_PARAM|(div<<3)|m) +/* mode set command details, div is a key group number */ +#define LK_MODE_DOWN 0x0 /* make only */ +#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)) + +/* + * Mappings between key groups and keycodes are as follows: + * + * 1: 0xbf - 0xff -- alphanumeric, + * 2: 0x91 - 0xa5 -- numeric keypad, + * 3: 0xbc -- Backspace, + * 4: 0xbd - 0xbe -- Tab, Return, + * 5: 0xb0 - 0xb2 -- Lock, Compose Character, + * 6: 0xad - 0xaf -- Ctrl, Shift, + * 7: 0xa6 - 0xa8 -- Left Arrow, Right Arrow, + * 8: 0xa9 - 0xac -- Up Arrow, Down Arrow, Right Shift, + * 9: 0x88 - 0x90 -- editor keypad, + * 10: 0x56 - 0x62 -- F1 - F5, + * 11: 0x63 - 0x6e -- F6 - F10, + * 12: 0x6f - 0x7a -- F11 - F14, + * 13: 0x7b - 0x7d -- Help, Do, + * 14: 0x7e - 0x87 -- F17 - F20. + * + * Notes: + * 1. Codes in the 0x00 - 0x40 range are reserved. + * 2. The assignment of the 0x41 - 0x55 range is undiscovered, probably 10. + */ + +/* delay is 5 - 630 ms; 0x00 and 0x7f are reserved */ +#define LK_PARAM_DELAY(t) ((t)&0x7f) + +/* rate is 12 - 127 Hz; 0x00 - 0x0b and 0x7d (power-up!) are reserved */ +#define LK_PARAM_RATE(r) (LK_PARAM|((r)&0x7f)) #define LK_SHIFT 1<<0 #define LK_CTRL 1<<1 #define LK_LOCK 1<<2 #define LK_COMP 1<<3 -#define LK_KEY_SHIFT 174 -#define LK_KEY_CTRL 175 -#define LK_KEY_LOCK 176 -#define LK_KEY_COMP 177 -#define LK_KEY_RELEASE 179 -#define LK_KEY_REPEAT 180 -#define LK_KEY_ACK 186 +#define LK_KEY_SHIFT 0xae +#define LK_KEY_CTRL 0xaf +#define LK_KEY_LOCK 0xb0 +#define LK_KEY_COMP 0xb1 + +#define LK_KEY_RELEASE 0xb3 /* all keys released */ +#define LK_KEY_REPEAT 0xb4 /* repeat the last key */ + +/* status responses */ +#define LK_STAT_RESUME_ERR 0xb5 /* keystrokes lost while inhibited */ +#define LK_STAT_ERROR 0xb6 /* an invalid command received */ +#define LK_STAT_INHIBIT_ACK 0xb7 /* transmission inhibited */ +#define LK_STAT_TEST_ACK 0xb8 /* the factory test mode entered */ +#define LK_STAT_MODE_KEYDOWN 0xb9 /* a key is down on a change */ + /* to the DOWN_UP mode; */ + /* 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 */ -extern unsigned char scancodeRemap[256]; \ No newline at end of file +extern unsigned char scancodeRemap[256]; diff -puN drivers/tc/tc.c~mips-decstation-turbochannel-updates drivers/tc/tc.c --- 25/drivers/tc/tc.c~mips-decstation-turbochannel-updates 2005-01-29 11:26:05.131967744 -0800 +++ 25-akpm/drivers/tc/tc.c 2005-01-29 11:26:05.149965008 -0800 @@ -8,46 +8,46 @@ * for more details. * * Copyright (c) Harald Koerfgen, 1998 + * Copyright (c) 2001, 2003 Maciej W. Rozycki */ #include #include #include +#include +#include + #include #include #include +#include #include #include #include - +#include #include -#include -#include #define TC_DEBUG MODULE_LICENSE("GPL"); slot_info tc_bus[MAX_SLOT]; -static int max_tcslot; +static int num_tcslots; static tcinfo *info; unsigned long system_base; -extern void (*dbe_board_handler)(struct pt_regs *regs); -extern unsigned long *(*rex_slot_address)(int); -extern void *(*rex_gettcinfo)(void); - /* * Interface to the world. Read comment in include/asm-mips/tc.h. */ -int search_tc_card(char *name) +int search_tc_card(const char *name) { int slot; slot_info *sip; - for (slot = 0; slot <= max_tcslot; slot++) { + for (slot = 0; slot < num_tcslots; slot++) { sip = &tc_bus[slot]; - if ((sip->flags & FREE) && (strncmp(sip->name, name, strlen(name)) == 0)) { + if ((sip->flags & FREE) && + (strncmp(sip->name, name, strlen(name)) == 0)) { return slot; } } @@ -68,7 +68,8 @@ void claim_tc_card(int slot) void release_tc_card(int slot) { if (tc_bus[slot].flags & FREE) { - printk("release_tc_card: attempting to release a card already free\n"); + printk("release_tc_card: " + "attempting to release a card already free\n"); return; } tc_bus[slot].flags &= ~IN_USE; @@ -93,73 +94,84 @@ unsigned long get_tc_speed(void) /* * Probing for TURBOchannel modules */ -static void __init my_dbe_handler(struct pt_regs *regs) +static void __init tc_probe(unsigned long startaddr, unsigned long size, + int slots) { - regs->cp0_epc += 4; -} - -static void __init tc_probe(unsigned long startaddr, unsigned long size, int max_slot) -{ - int i, slot; + int i, slot, err; long offset; + unsigned char pattern[4]; unsigned char *module; - void (*old_be_handler)(struct pt_regs *regs); - - /* Install our exception handler temporarily */ - old_be_handler = dbe_board_handler; - dbe_board_handler = my_dbe_handler; - for (slot = 0; slot <= max_slot; slot++) { + for (slot = 0; slot < slots; slot++) { module = (char *)(startaddr + slot * size); - offset = -1; - if (module[OLDCARD + TC_PATTERN0] == 0x55 && module[OLDCARD + TC_PATTERN1] == 0x00 - && module[OLDCARD + TC_PATTERN2] == 0xaa && module[OLDCARD + TC_PATTERN3] == 0xff) - offset = OLDCARD; - if (module[TC_PATTERN0] == 0x55 && module[TC_PATTERN1] == 0x00 - && module[TC_PATTERN2] == 0xaa && module[TC_PATTERN3] == 0xff) - offset = 0; - - if (offset != -1) { - tc_bus[slot].base_addr = (unsigned long)module; - for(i = 0; i < 8; i++) { - tc_bus[slot].firmware[i] = module[TC_FIRM_VER + offset + 4 * i]; - tc_bus[slot].vendor[i] = module[TC_VENDOR + offset + 4 * i]; - tc_bus[slot].name[i] = module[TC_MODULE + offset + 4 * i]; - } - tc_bus[slot].firmware[8] = 0; - tc_bus[slot].vendor[8] = 0; - tc_bus[slot].name[8] = 0; - /* - * Looks unneccesary, but we may change - * TC? in the future - */ - switch (slot) { - case 0: - tc_bus[slot].interrupt = TC0; - break; - case 1: - tc_bus[slot].interrupt = TC1; - break; - case 2: - tc_bus[slot].interrupt = TC2; - break; - /* - * Yuck! DS5000/200 onboard devices - */ - case 5: - tc_bus[slot].interrupt = SCSI_INT; - break; - case 6: - tc_bus[slot].interrupt = ETHER; - break; - default: - tc_bus[slot].interrupt = -1; - break; - } + + offset = OLDCARD; + + err = 0; + err |= get_dbe(pattern[0], module + OLDCARD + TC_PATTERN0); + err |= get_dbe(pattern[1], module + OLDCARD + TC_PATTERN1); + err |= get_dbe(pattern[2], module + OLDCARD + TC_PATTERN2); + err |= get_dbe(pattern[3], module + OLDCARD + TC_PATTERN3); + if (err) + continue; + + if (pattern[0] != 0x55 || pattern[1] != 0x00 || + pattern[2] != 0xaa || pattern[3] != 0xff) { + offset = NEWCARD; + + err = 0; + err |= get_dbe(pattern[0], module + TC_PATTERN0); + err |= get_dbe(pattern[1], module + TC_PATTERN1); + err |= get_dbe(pattern[2], module + TC_PATTERN2); + err |= get_dbe(pattern[3], module + TC_PATTERN3); + if (err) + continue; } - } - dbe_board_handler = old_be_handler; + if (pattern[0] != 0x55 || pattern[1] != 0x00 || + pattern[2] != 0xaa || pattern[3] != 0xff) + continue; + + tc_bus[slot].base_addr = (unsigned long)module; + for(i = 0; i < 8; i++) { + tc_bus[slot].firmware[i] = + module[TC_FIRM_VER + offset + 4 * i]; + tc_bus[slot].vendor[i] = + module[TC_VENDOR + offset + 4 * i]; + tc_bus[slot].name[i] = + module[TC_MODULE + offset + 4 * i]; + } + tc_bus[slot].firmware[8] = 0; + tc_bus[slot].vendor[8] = 0; + tc_bus[slot].name[8] = 0; + /* + * Looks unneccesary, but we may change + * TC? in the future + */ + switch (slot) { + case 0: + tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC0]; + break; + case 1: + tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC1]; + break; + case 2: + tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC2]; + break; + /* + * Yuck! DS5000/200 onboard devices + */ + case 5: + tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC5]; + break; + case 6: + tc_bus[slot].interrupt = dec_interrupt[DEC_IRQ_TC6]; + break; + default: + tc_bus[slot].interrupt = -1; + break; + } + } } /* @@ -189,15 +201,16 @@ void __init tc_init(void) switch (mips_machtype) { case MACH_DS5000_200: - max_tcslot = 6; + num_tcslots = 7; break; case MACH_DS5000_1XX: case MACH_DS5000_2X0: - max_tcslot = 2; + case MACH_DS5900: + num_tcslots = 3; break; case MACH_DS5000_XX: default: - max_tcslot = 1; + num_tcslots = 2; break; } @@ -210,22 +223,22 @@ void __init tc_init(void) slot_size = info->slot_size << 20; - tc_probe(slot0addr, slot_size, max_tcslot); + tc_probe(slot0addr, slot_size, num_tcslots); /* * All TURBOchannel DECstations have the onboard devices - * where the (max_tcslot + 1 or 2 on DS5k/xx) Option Module + * where the (num_tcslots + 0 or 1 on DS5k/xx) Option Module * would be. */ if(mips_machtype == MACH_DS5000_XX) - i = 2; - else i = 1; - - system_base = slot0addr + slot_size * (max_tcslot + i); + else + i = 0; + + system_base = slot0addr + slot_size * (num_tcslots + i); #ifdef TC_DEBUG - for (i = 0; i <= max_tcslot; i++) + for (i = 0; i < num_tcslots; i++) if (tc_bus[i].base_addr) { printk(" slot %d: ", i); printk("%s %s %s\n", tc_bus[i].vendor, @@ -244,4 +257,4 @@ EXPORT_SYMBOL(release_tc_card); EXPORT_SYMBOL(get_tc_base_addr); EXPORT_SYMBOL(get_tc_irq_nr); EXPORT_SYMBOL(get_tc_speed); - +EXPORT_SYMBOL(system_base); diff -puN drivers/tc/zs.c~mips-decstation-turbochannel-updates drivers/tc/zs.c --- 25/drivers/tc/zs.c~mips-decstation-turbochannel-updates 2005-01-29 11:26:05.133967440 -0800 +++ 25-akpm/drivers/tc/zs.c 2005-01-29 11:26:05.145965616 -0800 @@ -6,7 +6,7 @@ * * DECstation changes * Copyright (C) 1998-2000 Harald Koerfgen - * Copyright (C) 2000,2001 Maciej W. Rozycki + * Copyright (C) 2000, 2001, 2002, 2003, 2004 Maciej W. Rozycki * * For the rest of the code the original Copyright applies: * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) @@ -55,8 +55,7 @@ #include #include #include -#include -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_SERIAL_DEC_CONSOLE #include #endif @@ -65,18 +64,15 @@ #include #include #include -#include #include +#include + #ifdef CONFIG_MACH_DECSTATION #include #include #include #include #endif -#ifdef CONFIG_BAGET_MIPS -#include -unsigned long system_base; -#endif #ifdef CONFIG_KGDB #include #endif @@ -94,7 +90,7 @@ unsigned long system_base; #define NUM_SERIAL 2 /* Max number of ZS chips supported */ #define NUM_CHANNELS (NUM_SERIAL * 2) /* 2 channels per chip */ #define CHANNEL_A_NR (zs_parms->channel_a_offset > zs_parms->channel_b_offset) - /* Number of channel A in the chip */ + /* Number of channel A in the chip */ #define ZS_CHAN_IO_SIZE 8 #define ZS_CLOCK 7372800 /* Z8530 RTxC input clock rate */ @@ -105,7 +101,8 @@ struct zs_parms { unsigned long scc1; int channel_a_offset; int channel_b_offset; - int irq; + int irq0; + int irq1; int clock; }; @@ -113,24 +110,15 @@ static struct zs_parms *zs_parms; #ifdef CONFIG_MACH_DECSTATION static struct zs_parms ds_parms = { - scc0 : SCC0, - scc1 : SCC1, + scc0 : IOASIC_SCC0, + scc1 : IOASIC_SCC1, channel_a_offset : 1, channel_b_offset : 9, - irq : SERIAL, + irq0 : -1, + irq1 : -1, clock : ZS_CLOCK }; #endif -#ifdef CONFIG_BAGET_MIPS -static struct zs_parms baget_parms = { - scc0 : UNI_SCC0, - scc1 : UNI_SCC1, - channel_a_offset : 9, - channel_b_offset : 1, - irq : BAGET_SCC_IRQ, - clock : 14745000 -}; -#endif #ifdef CONFIG_MACH_DECSTATION #define DS_BUS_PRESENT (IOASIC) @@ -138,13 +126,7 @@ static struct zs_parms baget_parms = { #define DS_BUS_PRESENT 0 #endif -#ifdef CONFIG_BAGET_MIPS -#define BAGET_BUS_PRESENT (mips_machtype == MACH_BAGET202) -#else -#define BAGET_BUS_PRESENT 0 -#endif - -#define BUS_PRESENT (DS_BUS_PRESENT || BAGET_BUS_PRESENT) +#define BUS_PRESENT (DS_BUS_PRESENT) struct dec_zschannel zs_channels[NUM_CHANNELS]; struct dec_serial zs_soft[NUM_CHANNELS]; @@ -153,28 +135,28 @@ struct dec_serial *zs_chain; /* list of struct tty_struct zs_ttys[NUM_CHANNELS]; -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_SERIAL_DEC_CONSOLE static struct console sercons; #endif -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) \ - && !defined(MODULE) +#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \ + !defined(MODULE) static unsigned long break_pressed; /* break, really ... */ #endif static unsigned char zs_init_regs[16] __initdata = { - 0, /* write 0 */ - 0, /* write 1 */ - 0xf0, /* write 2 */ - (Rx8), /* write 3 */ - (X16CLK | SB1), /* write 4 */ - (Tx8), /* write 5 */ - 0, 0, 0, /* write 6, 7, 8 */ - (VIS), /* write 9 */ - (NRZ), /* write 10 */ - (TCBR | RCBR), /* write 11 */ - 0, 0, /* BRG time constant, write 12 + 13 */ - (BRSRC | BRENABL), /* write 14 */ - 0 /* write 15 */ + 0, /* write 0 */ + 0, /* write 1 */ + 0, /* write 2 */ + 0, /* write 3 */ + (X16CLK), /* write 4 */ + 0, /* write 5 */ + 0, 0, 0, /* write 6, 7, 8 */ + (MIE | DLC | NV), /* write 9 */ + (NRZ), /* write 10 */ + (TCBR | RCBR), /* write 11 */ + 0, 0, /* BRG time constant, write 12 + 13 */ + (BRSRC | BRENABL), /* write 14 */ + 0 /* write 15 */ }; DECLARE_TASK_QUEUE(tq_zs_serial); @@ -190,7 +172,6 @@ static struct tty_driver *serial_driver; /* * Debugging. */ -#undef SERIAL_DEBUG_INTR #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_FLOW #undef SERIAL_DEBUG_THROTTLE @@ -251,7 +232,7 @@ static int baud_table[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 0 }; -/* +/* * Reading and writing Z8530 registers. */ static inline unsigned char read_zsreg(struct dec_zschannel *channel, @@ -261,7 +242,7 @@ static inline unsigned char read_zsreg(s if (reg != 0) { *channel->control = reg & 0xf; - wbflush(); RECOVERY_DELAY; + fast_iob(); RECOVERY_DELAY; } retval = *channel->control; RECOVERY_DELAY; @@ -273,10 +254,10 @@ static inline void write_zsreg(struct de { if (reg != 0) { *channel->control = reg & 0xf; - wbflush(); RECOVERY_DELAY; + fast_iob(); RECOVERY_DELAY; } *channel->control = value; - wbflush(); RECOVERY_DELAY; + fast_iob(); RECOVERY_DELAY; return; } @@ -293,7 +274,7 @@ static inline void write_zsdata(struct d unsigned char value) { *channel->data = value; - wbflush(); RECOVERY_DELAY; + fast_iob(); RECOVERY_DELAY; return; } @@ -303,9 +284,9 @@ static inline void load_zsregs(struct de /* ZS_CLEARERR(channel); ZS_CLEARFIFO(channel); */ /* Load 'em up */ - write_zsreg(channel, R4, regs[R4]); write_zsreg(channel, R3, regs[R3] & ~RxENABLE); write_zsreg(channel, R5, regs[R5] & ~TxENAB); + write_zsreg(channel, R4, regs[R4]); write_zsreg(channel, R9, regs[R9]); write_zsreg(channel, R1, regs[R1]); write_zsreg(channel, R2, regs[R2]); @@ -372,8 +353,6 @@ static inline void rs_recv_clear(struct * ----------------------------------------------------------------------- */ -static int tty_break; /* Set whenever BREAK condition is detected. */ - /* * This routine is used by the interrupt handler to schedule * processing in the software interrupt portion of the driver. @@ -397,23 +376,18 @@ static _INLINE_ void receive_chars(struc 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) { - tty_break = 0; -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) - if (info->line == sercons.index) { - if (!break_pressed) { - break_pressed = jiffies; - goto ignore_char; - } - break_pressed = 0; - } -#endif + flag = TTY_NORMAL; + if (info->tty_break) { + info->tty_break = 0; flag = TTY_BREAK; if (info->flags & ZILOG_SAK) do_SAK(tty); + /* Ignore the null char got when BREAK is removed. */ + if (ch == 0) + continue; } else { if (stat & Rx_OVR) { flag = TTY_OVERRUN; @@ -421,20 +395,22 @@ static _INLINE_ void receive_chars(struc flag = TTY_FRAME; } else if (stat & PAR_ERR) { flag = TTY_PARITY; - } else - flag = 0; - if (flag) + } + if (flag != TTY_NORMAL) /* reset the error indication */ write_zsreg(info->zs_channel, R0, ERR_RES); } -#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE) +#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \ + !defined(MODULE) if (break_pressed && info->line == sercons.index) { - if (ch != 0 && - time_before(jiffies, break_pressed + HZ*5)) { + /* Ignore the null char got when BREAK is removed. */ + if (ch == 0) + continue; + if (time_before(jiffies, break_pressed + HZ * 5)) { handle_sysrq(ch, regs, NULL); break_pressed = 0; - goto ignore_char; + continue; } break_pressed = 0; } @@ -444,22 +420,8 @@ static _INLINE_ void receive_chars(struc (*info->hook->rx_char)(ch, flag); return; } - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) { - static int flip_buf_ovf; - ++flip_buf_ovf; - continue; - } - tty->flip.count++; - { - static int flip_max_cnt; - if (flip_max_cnt < tty->flip.count) - flip_max_cnt = tty->flip.count; - } - *tty->flip.flag_buf_ptr++ = flag; - *tty->flip.char_buf_ptr++ = ch; - ignore_char: + tty_insert_flip_char(tty, ch, flag); } if (tty) tty_flip_buffer_push(tty); @@ -501,18 +463,22 @@ static _INLINE_ void status_handle(struc /* Get status from Read Register 0 */ stat = read_zsreg(info->zs_channel, R0); - if (stat & BRK_ABRT) { -#ifdef SERIAL_DEBUG_INTR - printk("handling break...."); + if ((stat & BRK_ABRT) && !(info->read_reg_zero & BRK_ABRT)) { +#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \ + !defined(MODULE) + if (info->line == sercons.index) { + if (!break_pressed) + break_pressed = jiffies; + } else #endif - tty_break = 1; + info->tty_break = 1; } 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 { @@ -563,7 +529,7 @@ void rs_interrupt(int irq, void *dev_id, shift = 0; /* Channel B */ for (;;) { - zs_intreg = read_zsreg(info->zs_chan_a, R3) >> shift; + zs_intreg = read_zsreg(info->zs_chan_a, R3) >> shift; if ((zs_intreg & CHAN_IRQMASK) == 0) break; @@ -577,7 +543,7 @@ void rs_interrupt(int irq, void *dev_id, status_handle(info); } } - + /* Why do we need this ? */ write_zsreg(info->zs_channel, 0, RES_H_IUS); } @@ -586,14 +552,14 @@ void rs_interrupt(int irq, void *dev_id, void zs_dump (void) { int i, j; for (i = 0; i < zs_channels_found; i++) { - struct dec_zschannel *ch = &zs_channels[i]; + struct dec_zschannel *ch = &zs_channels[i]; if ((long)ch->control == UNI_IO_BASE+UNI_SCC1A_CTRL) { for (j = 0; j < 15; j++) { - printk("W%d = 0x%x\t", + printk("W%d = 0x%x\t", j, (int)ch->curregs[j]); } for (j = 0; j < 15; j++) { - printk("R%d = 0x%x\t", + printk("R%d = 0x%x\t", j, (int)read_zsreg(ch,j)); } printk("\n\n"); @@ -622,7 +588,7 @@ static void rs_stop(struct tty_struct *t if (serial_paranoia_check(info, tty->name, "rs_stop")) return; - + #if 1 save_flags(flags); cli(); if (info->zs_channel->curregs[5] & TxENAB) { @@ -637,10 +603,10 @@ static void rs_start(struct tty_struct * { struct dec_serial *info = (struct dec_serial *)tty->driver_data; unsigned long flags; - + if (serial_paranoia_check(info, tty->name, "rs_start")) return; - + save_flags(flags); cli(); #if 1 if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) { @@ -673,7 +639,7 @@ static void do_softint(void *private_) { struct dec_serial *info = (struct dec_serial *) private_; struct tty_struct *tty; - + tty = info->tty; if (!tty) return; @@ -711,8 +677,13 @@ int zs_startup(struct dec_serial * info) /* * Clear the interrupt registers. */ - write_zsreg(info->zs_channel, 0, ERR_RES); - write_zsreg(info->zs_channel, 0, RES_H_IUS); + write_zsreg(info->zs_channel, R0, ERR_RES); + write_zsreg(info->zs_channel, R0, RES_H_IUS); + + /* + * Set the speed of the serial port + */ + change_speed(info); /* * Turn on RTS and DTR. @@ -722,35 +693,30 @@ int zs_startup(struct dec_serial * info) /* * Finally, enable sequencing and interrupts */ - info->zs_channel->curregs[1] = (info->zs_channel->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB); - info->zs_channel->curregs[3] |= (RxENABLE | Rx8); - info->zs_channel->curregs[5] |= (TxENAB | Tx8); - info->zs_channel->curregs[15] |= (DCDIE | CTSIE | TxUIE | BRKIE); - info->zs_channel->curregs[9] |= (VIS | MIE); - write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]); - write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); - write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); - write_zsreg(info->zs_channel, 15, info->zs_channel->curregs[15]); - write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]); + info->zs_channel->curregs[R1] &= ~RxINT_MASK; + info->zs_channel->curregs[R1] |= (RxINT_ALL | TxINT_ENAB | + EXT_INT_ENAB); + info->zs_channel->curregs[R3] |= RxENABLE; + info->zs_channel->curregs[R5] |= TxENAB; + info->zs_channel->curregs[R15] |= (DCDIE | CTSIE | TxUIE | BRKIE); + write_zsreg(info->zs_channel, R1, info->zs_channel->curregs[R1]); + write_zsreg(info->zs_channel, R3, info->zs_channel->curregs[R3]); + write_zsreg(info->zs_channel, R5, info->zs_channel->curregs[R5]); + write_zsreg(info->zs_channel, R15, info->zs_channel->curregs[R15]); /* * And clear the interrupt registers again for luck. */ - write_zsreg(info->zs_channel, 0, ERR_RES); - write_zsreg(info->zs_channel, 0, RES_H_IUS); + write_zsreg(info->zs_channel, R0, ERR_RES); + write_zsreg(info->zs_channel, R0, RES_H_IUS); + + /* Save the current value of RR0 */ + info->read_reg_zero = read_zsreg(info->zs_channel, R0); if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - /* - * Set the speed of the serial port - */ - change_speed(info); - - /* Save the current value of RR0 */ - info->read_reg_zero = read_zsreg(info->zs_channel, 0); - info->flags |= ZILOG_INITIALIZED; restore_flags(flags); return 0; @@ -771,9 +737,9 @@ static void shutdown(struct dec_serial * printk("Shutting down serial port %d (irq %d)....", info->line, info->irq); #endif - + save_flags(flags); cli(); /* Disable interrupts */ - + if (info->xmit_buf) { free_page((unsigned long) info->xmit_buf); info->xmit_buf = 0; @@ -833,13 +799,11 @@ static void change_speed(struct dec_seri save_flags(flags); cli(); info->zs_baud = baud_table[i]; - info->clk_divisor = 16; if (info->zs_baud) { - info->zs_channel->curregs[4] = X16CLK; brg = BPS_TO_BRG(info->zs_baud, zs_parms->clock/info->clk_divisor); info->zs_channel->curregs[12] = (brg & 255); info->zs_channel->curregs[13] = ((brg >> 8) & 255); - zs_rtsdtr(info, DTR, 1); + zs_rtsdtr(info, DTR, 1); } else { zs_rtsdtr(info, RTS | DTR, 0); return; @@ -942,13 +906,21 @@ static int rs_write(struct tty_struct * save_flags(flags); while (1) { - cli(); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); + cli(); + c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); if (c <= 0) break; - memcpy(info->xmit_buf + info->xmit_head, buf, c); + if (from_user) { + down(&tmp_buf_sem); + copy_from_user(tmp_buf, buf, c); + c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + up(&tmp_buf_sem); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); info->xmit_cnt += c; restore_flags(flags); @@ -968,7 +940,7 @@ static int rs_write_room(struct tty_stru { struct dec_serial *info = (struct dec_serial *)tty->driver_data; int ret; - + if (serial_paranoia_check(info, tty->name, "rs_write_room")) return 0; ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; @@ -980,7 +952,7 @@ static int rs_write_room(struct tty_stru static int rs_chars_in_buffer(struct tty_struct *tty) { struct dec_serial *info = (struct dec_serial *)tty->driver_data; - + if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) return 0; return info->xmit_cnt; @@ -989,7 +961,7 @@ static int rs_chars_in_buffer(struct tty static void rs_flush_buffer(struct tty_struct *tty) { struct dec_serial *info = (struct dec_serial *)tty->driver_data; - + if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) return; cli(); @@ -1001,7 +973,7 @@ static void rs_flush_buffer(struct tty_s /* * ------------------------------------------------------------ * rs_throttle() - * + * * This routine is called by the upper-layer tty layer to signal that * incoming characters should be throttled. * ------------------------------------------------------------ @@ -1013,14 +985,14 @@ static void rs_throttle(struct tty_struc #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - + printk("throttle %s: %d....\n", _tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_throttle")) return; - + if (I_IXOFF(tty)) { save_flags(flags); cli(); info->x_char = STOP_CHAR(tty); @@ -1041,14 +1013,14 @@ static void rs_unthrottle(struct tty_str #ifdef SERIAL_DEBUG_THROTTLE char buf[64]; - + printk("unthrottle %s: %d....\n", _tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) return; - + if (I_IXOFF(tty)) { save_flags(flags); cli(); if (info->x_char) @@ -1145,7 +1117,7 @@ check_and_exit: * release the bus after transmitting. This must be done when * the transmit shift register is empty, not be done when the * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. + * allows an RS485 driver to be written in user space. */ static int get_lsr_info(struct dec_serial * info, unsigned int *value) { @@ -1192,7 +1164,7 @@ static int rs_tiocmget(struct tty_struct } static int rs_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) + unsigned int set, unsigned int clear) { struct dec_serial * info = (struct dec_serial *)tty->driver_data; int error; @@ -1210,6 +1182,7 @@ static int rs_tiocmset(struct tty_struct if (info->zs_channel == info->zs_chan_a) return 0; + get_user(arg, value); cli(); if (set & TIOCM_RTS) info->zs_chan_a->curregs[5] |= RTS; @@ -1264,38 +1237,38 @@ static int rs_ioctl(struct tty_struct *t if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } - + switch (cmd) { - case TIOCGSERIAL: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct)); - if (error) - return error; - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERGETLSR: /* Get line status register */ - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; - else - return get_lsr_info(info, (unsigned int *) arg); + case TIOCGSERIAL: + error = verify_area(VERIFY_WRITE, (void *)arg, + sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info(info, (struct serial_struct *)arg); + + case TIOCSSERIAL: + return set_serial_info(info, (struct serial_struct *)arg); + + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *)arg, + sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info(info, (unsigned int *)arg); + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *)arg, + sizeof(struct dec_serial)); + if (error) + return error; + copy_from_user((struct dec_serial *)arg, info, + sizeof(struct dec_serial)); + return 0; - case TIOCSERGSTRUCT: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(struct dec_serial)); - if (error) - return error; - copy_from_user((struct dec_serial *) arg, - info, sizeof(struct dec_serial)); - return 0; - - default: - return -ENOIOCTLCMD; - } + default: + return -ENOIOCTLCMD; + } return 0; } @@ -1317,7 +1290,7 @@ static void rs_set_termios(struct tty_st /* * ------------------------------------------------------------ * rs_close() - * + * * This routine is called when the serial port gets closed. * Wait for the last remaining data to be sent. * ------------------------------------------------------------ @@ -1329,14 +1302,14 @@ static void rs_close(struct tty_struct * if (!info || serial_paranoia_check(info, tty->name, "rs_close")) return; - + save_flags(flags); cli(); - + if (tty_hung_up_p(filp)) { restore_flags(flags); return; } - + #ifdef SERIAL_DEBUG_OPEN printk("rs_close ttyS%d, count = %d\n", info->line, info->count); #endif @@ -1363,7 +1336,7 @@ static void rs_close(struct tty_struct * } info->flags |= ZILOG_CLOSING; /* - * Now we wait for the transmit buffer to clear; and we notify + * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; @@ -1411,7 +1384,8 @@ static void rs_close(struct tty_struct * static void rs_wait_until_sent(struct tty_struct *tty, int timeout) { struct dec_serial *info = (struct dec_serial *) tty->driver_data; - unsigned long orig_jiffies, char_time; + unsigned long orig_jiffies; + int char_time; if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) return; @@ -1427,7 +1401,7 @@ static void rs_wait_until_sent(struct tt if (char_time == 0) char_time = 1; if (timeout) - char_time = min_t(unsigned long, char_time, timeout); + char_time = min(char_time, timeout); while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(char_time); @@ -1485,11 +1459,6 @@ static int block_til_ready(struct tty_st } /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - - /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. */ @@ -1516,7 +1485,7 @@ static int block_til_ready(struct tty_st info->line, info->count); #endif cli(); - if (!tty_hung_up_p(filp)) + if (!tty_hung_up_p(filp)) info->count--; sti(); info->blocked_open++; @@ -1532,7 +1501,7 @@ static int block_til_ready(struct tty_st if (info->flags & ZILOG_HUP_NOTIFY) retval = -EAGAIN; else - retval = -ERESTARTSYS; + retval = -ERESTARTSYS; #else retval = -EAGAIN; #endif @@ -1564,7 +1533,7 @@ static int block_til_ready(struct tty_st return retval; info->flags |= ZILOG_NORMAL_ACTIVE; return 0; -} +} /* * This routine is called whenever a serial port is opened. It @@ -1626,7 +1595,7 @@ int rs_open(struct tty_struct *tty, stru return retval; } -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_SERIAL_DEC_CONSOLE if (sercons.cflag && sercons.index == line) { tty->termios->c_cflag = sercons.cflag; sercons.cflag = 0; @@ -1645,7 +1614,7 @@ int rs_open(struct tty_struct *tty, stru static void __init show_serial_version(void) { - printk("DECstation Z8530 serial driver version 0.05\n"); + printk("DECstation Z8530 serial driver version 0.09\n"); } /* Initialize Z8530s zs_channels @@ -1655,6 +1624,7 @@ static void __init probe_sccs(void) { struct dec_serial **pp; int i, n, n_chips = 0, n_channels, chip, channel; + unsigned long flags; /* * did we get here by accident? @@ -1663,7 +1633,7 @@ static void __init probe_sccs(void) printk("Not on JUNKIO machine, skipping probe_sccs\n"); return; } - + /* * When serial console is activated, tc_init has not been called yet * and system_base is undefined. Unfortunately we have to hardcode @@ -1672,27 +1642,25 @@ static void __init probe_sccs(void) switch(mips_machtype) { #ifdef CONFIG_MACH_DECSTATION case MACH_DS5000_2X0: - system_base = 0xbf800000; + case MACH_DS5900: + system_base = KSEG1ADDR(0x1f800000); 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; + system_base = KSEG1ADDR(0x1c000000); 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; + system_base = KSEG1ADDR(0x1c000000); n_chips = 1; zs_parms = &ds_parms; - break; -#endif -#ifdef CONFIG_BAGET_MIPS - case MACH_BAGET202: - system_base = UNI_IO_BASE; - n_chips = 2; - zs_parms = &baget_parms; - zs_init_regs[2] = 0x8; + zs_parms->irq0 = dec_interrupt[DEC_IRQ_SCC0]; break; #endif default: @@ -1710,15 +1678,15 @@ static void __init probe_sccs(void) /* * The sccs reside on the high byte of the 16 bit IOBUS */ - zs_channels[n_channels].control = - (volatile unsigned char *)system_base + - (0 == chip ? zs_parms->scc0 : zs_parms->scc1) + - (0 == channel ? zs_parms->channel_a_offset : + zs_channels[n_channels].control = + (volatile unsigned char *)system_base + + (0 == chip ? zs_parms->scc0 : zs_parms->scc1) + + (0 == channel ? zs_parms->channel_a_offset : zs_parms->channel_b_offset); - zs_channels[n_channels].data = + zs_channels[n_channels].data = zs_channels[n_channels].control + 4; -#ifndef CONFIG_SERIAL_CONSOLE +#ifndef CONFIG_SERIAL_DEC_CONSOLE /* * We're called early and memory managment isn't up, yet. * Thus check_region would fail. @@ -1729,20 +1697,24 @@ static void __init probe_sccs(void) panic("SCC I/O region is not free"); #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 * inside chip depends on mapping of internal address * the chip decodes channels by. - * CHANNEL_A_NR returns either 0 (in case of + * CHANNEL_A_NR returns either 0 (in case of * DECstations) or 1 (in case of Baget). */ if (CHANNEL_A_NR == channel) - zs_soft[n_channels].zs_chan_a = + zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1-2*CHANNEL_A_NR]; else - zs_soft[n_channels].zs_chan_a = + zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels]; *pp = &zs_soft[n_channels]; @@ -1760,16 +1732,17 @@ static void __init probe_sccs(void) } } -/* save_and_cli(flags); + save_and_cli(flags); for (n = 0; n < zs_channels_found; n++) { - if (((int)zs_channels[n].control & 0xf) == 1) { + if (n % 2 == 0) { write_zsreg(zs_soft[n].zs_chan_a, R9, FHWRES); - mdelay(10); + udelay(10); write_zsreg(zs_soft[n].zs_chan_a, R9, 0); } - load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs); - } - restore_flags(flags); */ + load_zsregs(zs_soft[n].zs_channel, + zs_soft[n].zs_channel->curregs); + } + restore_flags(flags); } static struct tty_operations serial_ops = { @@ -1797,7 +1770,6 @@ static struct tty_operations serial_ops int __init zs_init(void) { int channel, i; - unsigned long flags; struct dec_serial *info; if(!BUS_PRESENT) @@ -1809,7 +1781,6 @@ int __init zs_init(void) /* Find out how many Z8530 SCCs we have */ if (zs_chain == 0) probe_sccs(); - serial_driver = alloc_tty_driver(zs_channels_found); if (!serial_driver) return -ENOMEM; @@ -1833,39 +1804,25 @@ int __init zs_init(void) tty_set_operations(serial_driver, &serial_ops); if (tty_register_driver(serial_driver)) - panic("Couldn't register serial driver\n"); - - 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]); + panic("Couldn't register serial driver"); - zs_soft[channel].clk_divisor = 16; - zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); + for (info = zs_chain, i = 0; info; info = info->zs_next, i++) { - 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); - } + /* Needed before interrupts are enabled. */ + info->tty = 0; + info->x_char = 0; - for (info = zs_chain, i = 0; info; info = info->zs_next, i++) - { if (info->hook && info->hook->init_info) { (*info->hook->init_info)(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; @@ -1873,94 +1830,83 @@ int __init zs_init(void) info->tqueue.data = info; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - printk("ttyS%d at 0x%08x (irq = %d)", info->line, - info->port, info->irq); - printk(" is a Z85C30 SCC\n"); + printk("ttyS%02d at 0x%08x (irq = %d) is a Z85C30 SCC\n", + info->line, info->port, info->irq); tty_register_device(serial_driver, info->line, NULL); + } - restore_flags(flags); + for (channel = 0; channel < zs_channels_found; ++channel) { + zs_soft[channel].clk_divisor = 16; + zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); - return 0; -} + 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); -/* - * register_serial and unregister_serial allows for serial ports to be - * configured at run-time, to support PCMCIA modems. - */ -/* PowerMac: Unused at this time, just here to make things link. */ -int register_serial(struct serial_struct *req) -{ - return -1; -} + if (zs_soft[channel].hook) { + zs_startup(&zs_soft[channel]); + if (zs_soft[channel].hook->init_channel) + (*zs_soft[channel].hook->init_channel) + (&zs_soft[channel]); + } + } -void unregister_serial(int line) -{ - return; + return 0; } /* * polling I/O routines */ static int -zs_poll_tx_char(struct dec_serial *info, unsigned char ch) +zs_poll_tx_char(void *handle, unsigned char ch) { + struct dec_serial *info = handle; struct dec_zschannel *chan = info->zs_channel; int ret; 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; - - if (loops) { - ret = 0; - *(chan->data) = ch; - wbflush(); - RECOVERY_DELAY; - } else - ret = -EAGAIN; -// write_zsreg(chan, R9, nine); - wbflush(); - RECOVERY_DELAY; + while (loops && !(read_zsreg(chan, 0) & Tx_BUF_EMP)) + loops--; - return ret; - } + if (loops) { + write_zsdata(chan, ch); + ret = 0; + } else + ret = -EAGAIN; - return -ENODEV; + return ret; + } else + return -ENODEV; } static int -zs_poll_rx_char(struct dec_serial *info) +zs_poll_rx_char(void *handle) { + struct dec_serial *info = handle; struct dec_zschannel *chan = info->zs_channel; int ret; if(chan) { int loops = 10000; - while((read_zsreg(chan, 0) & Rx_CH_AV) == 0) - loops--; + while (loops && !(read_zsreg(chan, 0) & Rx_CH_AV)) + loops--; if (loops) ret = read_zsdata(chan); else ret = -EAGAIN; - return ret; - } else - return -ENODEV; + return ret; + } else + return -ENODEV; } -unsigned int register_zs_hook(unsigned int channel, struct zs_hook *hook) +int register_zs_hook(unsigned int channel, struct dec_serial_hook *hook) { struct dec_serial *info = &zs_soft[channel]; @@ -1970,22 +1916,15 @@ unsigned int register_zs_hook(unsigned i return 0; } else { - info->hook = hook; - - if (zs_chain == 0) - probe_sccs(); - - if (!(info->flags & ZILOG_INITIALIZED)) - zs_startup(info); - hook->poll_rx_char = zs_poll_rx_char; hook->poll_tx_char = zs_poll_tx_char; + info->hook = hook; return 1; } } -unsigned int unregister_zs_hook(unsigned int channel) +int unregister_zs_hook(unsigned int channel) { struct dec_serial *info = &zs_soft[channel]; @@ -2004,7 +1943,7 @@ unsigned int unregister_zs_hook(unsigned * Serial console driver * ------------------------------------------------------------ */ -#ifdef CONFIG_SERIAL_CONSOLE +#ifdef CONFIG_SERIAL_DEC_CONSOLE /* @@ -2041,11 +1980,13 @@ static struct tty_driver *serial_console static int __init serial_console_setup(struct console *co, char *options) { struct dec_serial *info; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - char *s; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int cflag = CREAD | HUPCL | CLOCAL; + int clk_divisor = 16; + int brg; + char *s; unsigned long flags; if(!BUS_PRESENT) @@ -2097,6 +2038,10 @@ static int __init serial_console_setup(s case 9600: default: cflag |= B9600; + /* + * Set this to a sane value to prevent a divide error. + */ + baud = 9600; break; } switch(bits) { @@ -2117,43 +2062,64 @@ static int __init serial_console_setup(s break; } co->cflag = cflag; -#if 1 + save_and_cli(flags); /* + * Set up the baud rate generator. + */ + brg = BPS_TO_BRG(baud, zs_parms->clock / clk_divisor); + info->zs_channel->curregs[R12] = (brg & 255); + info->zs_channel->curregs[R13] = ((brg >> 8) & 255); + + /* + * Set byte size and parity. + */ + if (bits == 7) { + info->zs_channel->curregs[R3] |= Rx7; + info->zs_channel->curregs[R5] |= Tx7; + } else { + info->zs_channel->curregs[R3] |= Rx8; + info->zs_channel->curregs[R5] |= Tx8; + } + if (cflag & PARENB) { + info->zs_channel->curregs[R4] |= PAR_ENA; + } + if (!(cflag & PARODD)) { + info->zs_channel->curregs[R4] |= PAR_EVEN; + } + info->zs_channel->curregs[R4] |= SB1; + + /* * Turn on RTS and DTR. */ zs_rtsdtr(info, RTS | DTR, 1); /* - * Finally, enable sequencing + * Finally, enable sequencing. */ - info->zs_channel->curregs[3] |= (RxENABLE | Rx8); - info->zs_channel->curregs[5] |= (TxENAB | Tx8); - info->zs_channel->curregs[9] |= (VIS); - write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]); - write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]); - write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]); + info->zs_channel->curregs[R3] |= RxENABLE; + info->zs_channel->curregs[R5] |= TxENAB; /* * Clear the interrupt registers. */ - write_zsreg(info->zs_channel, 0, ERR_RES); - write_zsreg(info->zs_channel, 0, RES_H_IUS); + write_zsreg(info->zs_channel, R0, ERR_RES); + write_zsreg(info->zs_channel, R0, RES_H_IUS); /* - * Set the speed of the serial port + * Load up the new values. */ - change_speed(info); + load_zsregs(info->zs_channel, info->zs_channel->curregs); /* Save the current value of RR0 */ - info->read_reg_zero = read_zsreg(info->zs_channel, 0); + info->read_reg_zero = read_zsreg(info->zs_channel, R0); - zs_soft[co->index].clk_divisor = 16; + zs_soft[co->index].clk_divisor = clk_divisor; zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]); restore_flags(flags); -#endif + return 0; } @@ -2173,7 +2139,7 @@ void __init zs_serial_console_init(void) { register_console(&sercons); } -#endif /* ifdef CONFIG_SERIAL_CONSOLE */ +#endif /* ifdef CONFIG_SERIAL_DEC_CONSOLE */ #ifdef CONFIG_KGDB struct dec_zschannel *zs_kgdbchan; @@ -2211,7 +2177,7 @@ void kgdb_interruptible(int yes) int one, nine; nine = read_zsreg(chan, 9); if (yes == 1) { - one = EXT_INT_ENAB|INT_ALL_Rx; + one = EXT_INT_ENAB|RxINT_ALL; nine |= MIE; printk("turning serial ints on\n"); } else { @@ -2223,22 +2189,23 @@ void kgdb_interruptible(int yes) write_zsreg(chan, 9, nine); } -static int kgdbhook_init_channel(struct dec_serial* info) +static int kgdbhook_init_channel(void *handle) { return 0; } -static void kgdbhook_init_info(struct dec_serial* info) +static void kgdbhook_init_info(void *handle) { } -static void kgdbhook_rx_char(struct dec_serial* info, - unsigned char ch, unsigned char stat) +static void kgdbhook_rx_char(void *handle, unsigned char ch, unsigned char fl) { + struct dec_serial *info = handle; + + if (fl != TTY_NORMAL) + return; if (ch == 0x03 || ch == '$') breakpoint(); - if (stat & (Rx_OVR|FRM_ERR|PAR_ERR)) - write_zsreg(info->zs_channel, 0, ERR_RES); } /* This sets up the serial port we're using, and turns on @@ -2264,11 +2231,11 @@ static inline void kgdb_chaninit(struct * for /dev/ttyb which is determined in setup_arch() from the * boot command line flags. */ -struct zs_hook zs_kgdbhook = { - init_channel : kgdbhook_init_channel, - init_info : kgdbhook_init_info, - cflags : B38400|CS8|CLOCAL, - rx_char : kgdbhook_rx_char, +struct dec_serial_hook zs_kgdbhook = { + .init_channel = kgdbhook_init_channel, + .init_info = kgdbhook_init_info, + .rx_char = kgdbhook_rx_char, + .cflags = B38400 | CS8 | CLOCAL, } void __init zs_kgdb_hook(int tty_num) diff -puN drivers/tc/zs.h~mips-decstation-turbochannel-updates drivers/tc/zs.h --- 25/drivers/tc/zs.h~mips-decstation-turbochannel-updates 2005-01-29 11:26:05.134967288 -0800 +++ 25-akpm/drivers/tc/zs.h 2005-01-29 11:26:05.147965312 -0800 @@ -1,14 +1,18 @@ /* - * macserial.h: Definitions for the Macintosh Z8530 serial driver. + * drivers/tc/zs.h: Definitions for the DECstation Z85C30 serial driver. * * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras. + * Adapted from drivers/macintosh/macserial.h by Harald Koerfgen. * * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2004 Maciej W. Rozycki */ #ifndef _DECSERIAL_H #define _DECSERIAL_H +#include + #define NUM_ZSREGS 16 struct serial_struct { @@ -89,61 +93,48 @@ struct dec_zschannel { unsigned char curregs[NUM_ZSREGS]; }; -struct dec_serial; - -struct zs_hook { - int (*init_channel)(struct dec_serial* info); - void (*init_info)(struct dec_serial* info); - void (*rx_char)(unsigned char ch, unsigned char stat); - int (*poll_rx_char)(struct dec_serial* info); - int (*poll_tx_char)(struct dec_serial* info, - unsigned char ch); - unsigned cflags; -}; - struct dec_serial { - struct dec_serial *zs_next; /* For IRQ servicing chain */ - struct dec_zschannel *zs_channel; /* Channel registers */ - struct dec_zschannel *zs_chan_a; /* A side registers */ - unsigned char read_reg_zero; - - char soft_carrier; /* Use soft carrier on this channel */ - char break_abort; /* Is serial console in, so process brk/abrt */ - struct zs_hook *hook; /* Hook on this channel */ - char is_cons; /* Is this our console. */ - unsigned char tx_active; /* character is being xmitted */ - unsigned char tx_stopped; /* output is suspended */ - - /* We need to know the current clock divisor - * to read the bps rate the chip has currently - * loaded. + struct dec_serial *zs_next; /* For IRQ servicing chain. */ + struct dec_zschannel *zs_channel; /* Channel registers. */ + struct dec_zschannel *zs_chan_a; /* A side registers. */ + unsigned char read_reg_zero; + + struct dec_serial_hook *hook; /* Hook on this channel. */ + int tty_break; /* Set on BREAK condition. */ + int is_cons; /* Is this our console. */ + int tx_active; /* Char is being xmitted. */ + int tx_stopped; /* Output is suspended. */ + + /* + * We need to know the current clock divisor + * to read the bps rate the chip has currently loaded. */ - unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ - int zs_baud; + int clk_divisor; /* May be 1, 16, 32, or 64. */ + int zs_baud; - char change_needed; + char change_needed; int magic; int baud_base; int port; int irq; - int flags; /* defined in tty.h */ - int type; /* UART type */ + int flags; /* Defined in tty.h. */ + int type; /* UART type. */ struct tty_struct *tty; int read_status_mask; int ignore_status_mask; int timeout; int xmit_fifo_size; int custom_divisor; - int x_char; /* xon/xoff character */ + int x_char; /* XON/XOFF character. */ int close_delay; unsigned short closing_wait; unsigned short closing_wait2; unsigned long event; unsigned long last_active; int line; - int count; /* # of fd on device */ - int blocked_open; /* # of blocked opens */ + int count; /* # of fds on device. */ + int blocked_open; /* # of blocked opens. */ unsigned char *xmit_buf; int xmit_head; int xmit_tail; @@ -219,8 +210,9 @@ struct dec_serial { #define RxINT_DISAB 0 /* Rx Int Disable */ #define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ -#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ -#define INT_ERR_Rx 0x18 /* Int on error only */ +#define RxINT_ALL 0x10 /* Int on all Rx Characters or error */ +#define RxINT_ERR 0x18 /* Int on error only */ +#define RxINT_MASK 0x18 #define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ #define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ _