diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-13 16:29:25 +0000 |
commit | db7d4daea91e105e3859cf461d7e53b9b77454b2 (patch) | |
tree | 9bb65b95440af09e8aca63abe56970dd3360cc57 /drivers/sbus/char | |
parent | 9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff) |
Merge with Linux 2.2.8.
Diffstat (limited to 'drivers/sbus/char')
-rw-r--r-- | drivers/sbus/char/bpp.c | 24 | ||||
-rw-r--r-- | drivers/sbus/char/flash.c | 4 | ||||
-rw-r--r-- | drivers/sbus/char/pcikbd.c | 36 | ||||
-rw-r--r-- | drivers/sbus/char/sab82532.c | 10 | ||||
-rw-r--r-- | drivers/sbus/char/su.c | 46 | ||||
-rw-r--r-- | drivers/sbus/char/sunkbd.c | 9 | ||||
-rw-r--r-- | drivers/sbus/char/sunmouse.c | 32 | ||||
-rw-r--r-- | drivers/sbus/char/sunserial.c | 8 | ||||
-rw-r--r-- | drivers/sbus/char/vfc_dev.c | 2 | ||||
-rw-r--r-- | drivers/sbus/char/zs.c | 178 |
10 files changed, 220 insertions, 129 deletions
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c index 0121a03e7..de9321d40 100644 --- a/drivers/sbus/char/bpp.c +++ b/drivers/sbus/char/bpp.c @@ -337,7 +337,7 @@ static int wait_for(unsigned short set, unsigned short clr, * responds real good. The first while loop guesses an expire * time accounting for possible wraparound of jiffies. */ - while (time_after_eq(jiffies, extime) extime = jiffies + 1; + while (time_after_eq(jiffies, extime)) extime = jiffies + 1; while ( (time_before(jiffies, extime)) && (((pins & set) != set) || ((pins & clr) != 0)) ) { pins = get_pins(minor); @@ -470,13 +470,14 @@ static int bpp_open(struct inode *inode, struct file *f) * mode as this is a reasonable place to clean up from messes made by * ioctls, or other mayhem. */ -static void bpp_release(struct inode *inode, struct file *f) +static int bpp_release(struct inode *inode, struct file *f) { unsigned minor = MINOR(inode->i_rdev); instances[minor].opened = 0; if (instances[minor].mode != COMPATIBILITY) terminate(minor); + return 0; } static long read_nibble(unsigned minor, char *c, unsigned long cnt) @@ -624,11 +625,10 @@ static long read_ecp(unsigned minor, char *c, unsigned long cnt) return cnt - remaining; } -static long bpp_read(struct inode *inode, struct file *f, - char *c, unsigned long cnt) +static ssize_t bpp_read(struct file *f, char *c, size_t cnt, loff_t * ppos) { long rc; - const unsigned minor = MINOR(inode->i_rdev); + const unsigned minor = MINOR(f->f_dentry->d_inode->i_rdev); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; @@ -694,10 +694,12 @@ static long write_compat(unsigned minor, const char *c, unsigned long cnt) unsigned long remaining = cnt; + while (remaining > 0) { unsigned char byte; - c += 1; + get_user_ret(byte, c, -EFAULT); + c += 1; rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); if (rc == -1) return -ETIMEDOUT; @@ -774,11 +776,10 @@ static long write_ecp(unsigned minor, const char *c, unsigned long cnt) * that. Otherwise, terminate and do my writing in compat mode. This * is the safest course as any device can handle it. */ -static long bpp_write(struct inode *inode, struct file *f, - const char *c, unsigned long cnt) +static ssize_t bpp_write(struct file *f, const char *c, size_t cnt, loff_t * ppos) { long errno = 0; - unsigned minor = MINOR(inode->i_rdev); + const unsigned minor = MINOR(f->f_dentry->d_inode->i_rdev); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; @@ -861,6 +862,11 @@ static struct file_operations bpp_fops = { bpp_open, NULL, /* flush */ bpp_release, + NULL, /* fsync */ + NULL, /* fasync */ + NULL, /* check media change */ + NULL, /* revalidate */ + NULL, /* lock */ }; #if defined(__i386__) diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index cea0c5131..6bd2eabfb 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -1,4 +1,4 @@ -/* $Id: flash.c,v 1.10 1998/08/26 10:29:41 davem Exp $ +/* $Id: flash.c,v 1.11 1999/03/09 14:06:45 davem Exp $ * flash.c: Allow mmap access to the OBP Flash, for OBP updates. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -72,8 +72,6 @@ flash_mmap(struct file *file, struct vm_area_struct *vma) if (remap_page_range(vma->vm_start, addr, size, vma->vm_page_prot)) return -EAGAIN; - vma->vm_file = file; - file->f_count++; return 0; } diff --git a/drivers/sbus/char/pcikbd.c b/drivers/sbus/char/pcikbd.c index 297b8f9ae..ef19f74b9 100644 --- a/drivers/sbus/char/pcikbd.c +++ b/drivers/sbus/char/pcikbd.c @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.24 1998/11/08 11:15:24 davem Exp $ +/* $Id: pcikbd.c,v 1.27 1999/05/09 06:40:47 ecd Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -228,8 +228,6 @@ unsigned char pcikbd_sysrq_xlate[128] = "\r\000/"; /* 0x60 - 0x6f */ #endif -static unsigned int prev_scancode = 0; - int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode) { if(scancode < SC_LIM || scancode > 255 || keycode > 127) @@ -262,29 +260,23 @@ int do_acknowledge(unsigned char scancode) return 0; } } - if(scancode == 0) { - prev_scancode = 0; - return 0; - } return 1; } -int pcikbd_pretranslate(unsigned char scancode, char raw_mode) +int pcikbd_translate(unsigned char scancode, unsigned char *keycode, + char raw_mode) { - if(scancode == 0xff) { - prev_scancode = 0; + static int prev_scancode = 0; + + if (scancode == 0xe0 || scancode == 0xe1) { + prev_scancode = scancode; return 0; } - if(scancode == 0xe0 || scancode == 0xe1) { - prev_scancode = scancode; + if (scancode == 0x00 || scancode == 0xff) { + prev_scancode = 0; return 0; } - return 1; -} - -int pcikbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode) -{ + scancode &= 0x7f; if(prev_scancode) { if(prev_scancode != 0xe0) { if(prev_scancode == 0xe1 && scancode == 0x1d) { @@ -338,7 +330,7 @@ pcikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) break; scancode = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG); if((status & KBD_STAT_OBF) && do_acknowledge(scancode)) - handle_scancode(scancode); + handle_scancode(scancode, !(scancode & 0x80)); status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG); } while(status & KBD_STAT_OBF); mark_bh(KEYBOARD_BH); @@ -985,9 +977,11 @@ found: } queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); + if (!queue) { + printk("pcimouse_init: kmalloc(aux_queue) failed.\n"); + return -ENOMEM; + } memset(queue, 0, sizeof(*queue)); - queue->head = queue->tail = 0; - queue->proc_list = NULL; if (request_irq(pcimouse_irq, &pcimouse_interrupt, SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) { diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c index 1ea317726..bbbd7c670 100644 --- a/drivers/sbus/char/sab82532.c +++ b/drivers/sbus/char/sab82532.c @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.27 1998/11/08 11:15:25 davem Exp $ +/* $Id: sab82532.c,v 1.30 1999/03/24 11:34:52 davem Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -2136,7 +2136,7 @@ sab82532_kgdb_hook(int line)) __initfunc(static inline void show_serial_version(void)) { - char *revision = "$Revision: 1.27 $"; + char *revision = "$Revision: 1.30 $"; char *version, *p; version = strchr(revision, ' '); @@ -2359,8 +2359,10 @@ void cleanup_module(void) restore_flags(flags); for (i = 0; i < NR_PORTS; i++) { - if (sab82532_table[i].type != PORT_UNKNOWN) - release_region(sab82532_table[i].port, 8); + struct sab82532 *info = (struct sab82532 *)sab82532_table[i]->driver_data; + if (info->type != PORT_UNKNOWN) + release_region((unsigned long)info->regs, + sizeof(union sab82532_async_regs)); } if (tmp_buf) { free_page((unsigned long) tmp_buf); diff --git a/drivers/sbus/char/su.c b/drivers/sbus/char/su.c index b4ab6693f..70e4f3657 100644 --- a/drivers/sbus/char/su.c +++ b/drivers/sbus/char/su.c @@ -1,4 +1,4 @@ -/* $Id: su.c,v 1.16 1998/11/14 23:02:54 ecd Exp $ +/* $Id: su.c,v 1.18 1999/01/02 16:47:37 davem Exp $ * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -157,7 +157,7 @@ static int serial_refcount; #define WAKEUP_CHARS 256 static void autoconfig(struct su_struct *info); -static void change_speed(struct su_struct *info); +static void change_speed(struct su_struct *info, struct termios *old); static void su_wait_until_sent(struct tty_struct *tty, int timeout); /* @@ -845,7 +845,7 @@ startup(struct su_struct *info) /* * and set the speed of the serial port */ - change_speed(info); + change_speed(info, 0); info->flags |= ASYNC_INITIALIZED; restore_flags(flags); @@ -948,7 +948,8 @@ su_get_baud_rate(struct su_struct *info) * the specified baud rate for a serial port. */ static void -change_speed(struct su_struct *info) +change_speed(struct su_struct *info, + struct termios *old_termios) { int quot = 0, baud; unsigned int cval, fcr = 0; @@ -999,7 +1000,25 @@ change_speed(struct su_struct *info) else if (baud) quot = info->baud_base / baud; } - /* If the quotient is ever zero, default to 9600 bps */ + /* If the quotient is zero refuse the change */ + if (!quot && old_termios) { + info->tty->termios->c_cflag &= ~CBAUD; + info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); + baud = tty_get_baud_rate(info->tty); + if (!baud) + baud = 9600; + if (baud == 38400 && + ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) + quot = info->custom_divisor; + else { + if (baud == 134) + /* Special case since 134 is really 134.5 */ + quot = (2*info->baud_base / 269); + else if (baud) + quot = info->baud_base / baud; + } + } + /* As a last resort, if the quotient is zero, default to 9600 bps */ if (!quot) quot = info->baud_base / 9600; info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / info->baud_base); @@ -1157,7 +1176,7 @@ su_change_mouse_baud(int baud) info->cflag |= 1200; break; } - change_speed(info); + change_speed(info, 0); } static void @@ -1303,6 +1322,9 @@ su_send_xchar(struct tty_struct *tty, char ch) if (serial_paranoia_check(info, tty->device, "su_send_char")) return; + if (!(info->flags & ASYNC_INITIALIZED)) + return; + info->x_char = ch; if (ch) { /* Make sure transmit interrupts are on */ @@ -1618,7 +1640,7 @@ su_set_termios(struct tty_struct *tty, struct termios *old_termios) == RELEVANT_IFLAG(old_termios->c_iflag))) return; - change_speed(info); + change_speed(info, old_termios); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && @@ -2067,13 +2089,13 @@ su_open(struct tty_struct *tty, struct file * filp) *tty->termios = info->normal_termios; else *tty->termios = info->callout_termios; - change_speed(info); + change_speed(info, 0); } #ifdef CONFIG_SERIAL_CONSOLE if (sercons.cflag && sercons.index == line) { tty->termios->c_cflag = sercons.cflag; sercons.cflag = 0; - change_speed(info); + change_speed(info, 0); } #endif info->session = current->session; @@ -2193,7 +2215,7 @@ done: */ __initfunc(static __inline__ void show_su_version(void)) { - char *revision = "$Revision: 1.16 $"; + char *revision = "$Revision: 1.18 $"; char *version, *p; version = strchr(revision, ' '); @@ -2207,8 +2229,8 @@ __initfunc(static __inline__ void show_su_version(void)) * This routine is called by su_init() to initialize a specific serial * port. It determines what type of UART chip this serial port is * using: 8250, 16450, 16550, 16550A. The important question is - * whether or not this UART is a 16550A or not, since this will - * determine whether or not we can use its FIFO features or not. + * whether or not this UART is a 16550A, since this will determine + * whether or not we can use its FIFO features. */ static void autoconfig(struct su_struct *info) diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c index b720afbec..41ffe9159 100644 --- a/drivers/sbus/char/sunkbd.c +++ b/drivers/sbus/char/sunkbd.c @@ -514,8 +514,13 @@ void sunkbd_inchar(unsigned char ch, struct pt_regs *regs) mark_bh(CONSOLE_BH); add_keyboard_randomness(keycode); + tty = ttytab? ttytab[fg_console]: NULL; + if (tty && (!tty->driver_data)) { + /* This is to workaround ugly bug in tty_io.c, which + does not do locking when it should */ + tty = NULL; + } kbd = kbd_table + fg_console; - tty = ttytab[fg_console]; if((raw_mode = (kbd->kbdmode == VC_RAW))) { if (kbd_redirected == fg_console+1) push_kbd (keycode); @@ -1474,7 +1479,7 @@ kbd_close (struct inode *i, struct file *f) return 0; if (kbd_redirected) - kbd_table [kbd_opened-1].kbdmode = VC_XLATE; + kbd_table [kbd_redirected-1].kbdmode = VC_XLATE; kbd_redirected = 0; kbd_opened = 0; diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c index 1c000b661..8547e47dd 100644 --- a/drivers/sbus/char/sunmouse.c +++ b/drivers/sbus/char/sunmouse.c @@ -94,7 +94,7 @@ extern void mouse_put_char(char ch); #undef SMOUSE_DEBUG -static void +static int push_event (Firm_event *ev) { int next = (sunmouse.head + 1) % EV_SIZE; @@ -102,7 +102,9 @@ push_event (Firm_event *ev) if (next != sunmouse.tail){ sunmouse.queue.ev [sunmouse.head] = *ev; sunmouse.head = next; + return 1; } + return 0; } static int @@ -150,7 +152,11 @@ void sun_mouse_change_baud(void) extern void rs_change_mouse_baud(int newbaud); if(mouse_baud == 1200) + mouse_baud = 2400; + else if(mouse_baud == 2400) mouse_baud = 4800; + else if(mouse_baud == 4800) + mouse_baud = 9600; else mouse_baud = 1200; @@ -196,7 +202,7 @@ void sun_mouse_inbyte(unsigned char byte) { signed char mvalue; - int d; + int d, pushed = 0; Firm_event ev; add_mouse_randomness (byte); @@ -290,29 +296,31 @@ sun_mouse_inbyte(unsigned char byte) } ev.time = xtime; ev.value = ev.value ? VKEY_DOWN : VKEY_UP; - push_event (&ev); + pushed += push_event (&ev); } if (sunmouse.delta_x){ ev.id = LOC_X_DELTA; ev.time = xtime; ev.value = sunmouse.delta_x; - push_event (&ev); + pushed += push_event (&ev); sunmouse.delta_x = 0; } if (sunmouse.delta_y){ ev.id = LOC_Y_DELTA; ev.time = xtime; ev.value = sunmouse.delta_y; - push_event (&ev); + pushed += push_event (&ev); } - /* We just completed a transaction, wake up whoever is awaiting - * this event. - */ - sunmouse.ready = 1; - if (sunmouse.fasync) - kill_fasync (sunmouse.fasync, SIGIO); - wake_up_interruptible(&sunmouse.proc_list); + if(pushed != 0) { + /* We just completed a transaction, wake up whoever is awaiting + * this event. + */ + sunmouse.ready = 1; + if (sunmouse.fasync) + kill_fasync (sunmouse.fasync, SIGIO); + wake_up_interruptible(&sunmouse.proc_list); + } return; } diff --git a/drivers/sbus/char/sunserial.c b/drivers/sbus/char/sunserial.c index 30ff83e4f..075062cf1 100644 --- a/drivers/sbus/char/sunserial.c +++ b/drivers/sbus/char/sunserial.c @@ -1,4 +1,4 @@ -/* $Id: sunserial.c,v 1.67 1998/10/25 03:22:46 jj Exp $ +/* $Id: sunserial.c,v 1.68 1998/12/09 18:53:51 davem Exp $ * serial.c: Serial port driver infrastructure for the Sparc. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -401,10 +401,10 @@ sun_serial_setup(unsigned long memory_start)) return memory_start; #ifdef __sparc_v9__ - ret = prom_finddevice("/ssp-serial"); - if (ret && ret != -1) { + { extern int this_is_starfire; /* Hello, Starfire. Pleased to meet you :) */ - return memory_start; + if(this_is_starfire != 0) + return memory_start; } #endif diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 48661f34b..9ebc20c71 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -582,8 +582,6 @@ static int vfc_mmap(struct inode *inode, struct file *file, if(ret) return -EAGAIN; - vma->vm_file = file; - file->f_count++; return 0; } diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c index 67aa3c574..9195f5a0e 100644 --- a/drivers/sbus/char/zs.c +++ b/drivers/sbus/char/zs.c @@ -1,4 +1,4 @@ -/* $Id: zs.c,v 1.32 1998/11/08 11:15:29 davem Exp $ +/* $Id: zs.c,v 1.41 1999/04/16 16:22:27 jj Exp $ * zs.c: Zilog serial port driver for the Sparc. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -53,6 +53,22 @@ static int num_serial = 2; /* sun4/sun4c/sun4m - Two chips on board. */ #define KEYBOARD_LINE 0x2 #define MOUSE_LINE 0x3 +/* On 32-bit sparcs we need to delay after register accesses + * to accomodate sun4 systems, but we do not need to flush writes. + * On 64-bit sparc we only need to flush single writes to ensure + * completion. + */ +#ifndef __sparc_v9__ +#define ZSDELAY() udelay(5) +#define ZSDELAY_LONG() udelay(20) +#define ZS_WSYNC(channel) do { } while(0) +#else +#define ZSDELAY() +#define ZSDELAY_LONG() +#define ZS_WSYNC(channel) \ + ((void) *((volatile unsigned char *)(&((channel)->control)))) +#endif + struct sun_zslayout **zs_chips; struct sun_zschannel **zs_channels; struct sun_zschannel *zs_mousechan; @@ -200,9 +216,9 @@ static inline unsigned char read_zsreg(struct sun_zschannel *channel, unsigned char retval; channel->control = reg; - udelay(5); + ZSDELAY(); retval = channel->control; - udelay(5); + ZSDELAY(); return retval; } @@ -210,9 +226,9 @@ static inline void write_zsreg(struct sun_zschannel *channel, unsigned char reg, unsigned char value) { channel->control = reg; - udelay(5); + ZSDELAY(); channel->control = value; - udelay(5); + ZSDELAY(); } static inline void load_zsregs(struct sun_serial *info, unsigned char *regs) @@ -239,7 +255,7 @@ static inline void load_zsregs(struct sun_serial *info, unsigned char *regs) write_zsreg(channel, R9, CHRA); else write_zsreg(channel, R9, CHRB); - udelay(20); /* wait for some old sun4's */ + ZSDELAY_LONG(); write_zsreg(channel, R4, regs[R4]); write_zsreg(channel, R3, regs[R3] & ~RxENAB); write_zsreg(channel, R5, regs[R5] & ~TxENAB); @@ -267,10 +283,16 @@ static inline void zs_put_char(struct sun_zschannel *channel, char ch) { int loops = ZS_PUT_CHAR_MAX_DELAY; + /* Do not change this to use ZSDELAY as this is + * a timed polling loop and on sparc64 ZSDELAY + * is a nop. -DaveM + */ while((channel->control & Tx_BUF_EMP) == 0 && --loops) udelay(5); + channel->data = ch; - udelay(5); + ZSDELAY(); + ZS_WSYNC(channel); } /* Sets or clears DTR/RTS on the requested line */ @@ -420,7 +442,7 @@ static _INLINE_ void receive_chars(struct sun_serial *info, struct pt_regs *regs do { ch = (info->zs_channel->data) & info->parity_mask; - udelay(5); + ZSDELAY(); /* If this is the console keyboard, we need to handle * L1-A's here. @@ -482,7 +504,7 @@ static _INLINE_ void receive_chars(struct sun_serial *info, struct pt_regs *regs /* Check if we have another character... */ stat = info->zs_channel->control; - udelay(5); + ZSDELAY(); if (!(stat & Rx_CH_AV)) break; @@ -507,7 +529,8 @@ static _INLINE_ void transmit_chars(struct sun_serial *info) if((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) { /* That's peculiar... */ info->zs_channel->control = RES_Tx_P; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); return; } @@ -521,7 +544,8 @@ static _INLINE_ void transmit_chars(struct sun_serial *info) if(info->xmit_cnt <= 0) { info->zs_channel->control = RES_Tx_P; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); } } @@ -531,10 +555,11 @@ static _INLINE_ void status_handle(struct sun_serial *info) /* Get status from Read Register 0 */ status = info->zs_channel->control; - udelay(5); + ZSDELAY(); /* Clear status condition... */ info->zs_channel->control = RES_EXT_INT; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); #if 0 if(status & DCD) { @@ -571,7 +596,7 @@ static _INLINE_ void special_receive(struct sun_serial *info) stat = read_zsreg(info->zs_channel, R1); if (stat & (PAR_ERR | Rx_OVR | CRC_ERR)) { ch = info->zs_channel->data; - udelay(5); + ZSDELAY(); } if (!tty) @@ -592,7 +617,8 @@ done: queue_task(&tty->flip.tqueue, &tq_timer); clear: info->zs_channel->control = ERR_RES; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); } @@ -772,9 +798,12 @@ static int startup(struct sun_serial * info) * Clear the interrupt registers. */ info->zs_channel->control = ERR_RES; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); + info->zs_channel->control = RES_H_IUS; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); /* * Now, initialize the Zilog @@ -798,9 +827,12 @@ static int startup(struct sun_serial * info) * And clear the interrupt registers again for luck. */ info->zs_channel->control = ERR_RES; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); + info->zs_channel->control = RES_H_IUS; - udelay(5); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); @@ -1006,6 +1038,7 @@ void putDebugChar(char kgdb_char) while((chan->control & Tx_BUF_EMP)==0) udelay(5); chan->data = kgdb_char; + ZS_WSYNC(chan); } char getDebugChar(void) @@ -1013,7 +1046,7 @@ char getDebugChar(void) struct sun_zschannel *chan = zs_kgdbchan; while((chan->control & Rx_CH_AV)==0) - barrier(); + udelay(5); return chan->data; } @@ -1254,6 +1287,9 @@ static int set_serial_info(struct sun_serial * info, goto check_and_exit; } + if(new_serial.baud_base < 9600) + return -EINVAL; + if (info->count > 1) return -EBUSY; @@ -1291,6 +1327,7 @@ static int get_lsr_info(struct sun_serial * info, unsigned int *value) cli(); status = info->zs_channel->control; + ZSDELAY(); sti(); put_user_ret(status,value, -EFAULT); return 0; @@ -1303,6 +1340,7 @@ static int get_modem_info(struct sun_serial * info, unsigned int *value) cli(); status = info->zs_channel->control; + ZSDELAY(); sti(); result = ((info->curregs[5] & RTS) ? TIOCM_RTS : 0) | ((info->curregs[5] & DTR) ? TIOCM_DTR : 0) @@ -1806,7 +1844,7 @@ int zs_open(struct tty_struct *tty, struct file * filp) static void show_serial_version(void) { - char *revision = "$Revision: 1.32 $"; + char *revision = "$Revision: 1.41 $"; char *version, *p; version = strchr(revision, ' '); @@ -1853,8 +1891,8 @@ get_zs(int chip)) int len = prom_getproperty(zsnode, "address", (void *) vaddr, sizeof(vaddr)); - if(len == -1) { - struct linux_sbus *sbus; + if(len == -1 || central_bus != NULL) { + struct linux_sbus *sbus = NULL; struct linux_sbus_device *sdev = NULL; /* "address" property is not guarenteed, @@ -1862,20 +1900,40 @@ get_zs(int chip)) * anyways by our clever TLB miss handling * scheme, so don't fail here. -DaveM */ - for_each_sbus(sbus) { - for_each_sbusdev(sdev, sbus) { - if (sdev->prom_node == zsnode) - goto found; + if (central_bus == NULL) { + for_each_sbus(sbus) { + for_each_sbusdev(sdev, sbus) { + if (sdev->prom_node == zsnode) + goto found; + } } } found: - if (sdev == NULL) + if (sdev == NULL && central_bus == NULL) prom_halt(); - prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev); - mapped_addr = (unsigned long) - sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, - PAGE_SIZE, "Zilog Registers", - sdev->reg_addrs[0].which_io, 0x0); + if (central_bus == NULL) { + prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev); + mapped_addr = (unsigned long) + sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, + PAGE_SIZE, "Zilog Registers", + sdev->reg_addrs[0].which_io, 0x0); + } else { + struct linux_prom_registers zsregs[1]; + int err; + + err = prom_getproperty(zsnode, "reg", + (char *)&zsregs[0], + sizeof(zsregs)); + if (err == -1) { + prom_printf("ZS: Cannot map Zilog regs.\n"); + prom_halt(); + } + prom_apply_fhc_ranges(central_bus->child, &zsregs[0], 1); + prom_apply_central_ranges(central_bus, &zsregs[0], 1); + mapped_addr = (unsigned long) + __va((((unsigned long)zsregs[0].which_io)<<32) | + (((unsigned long)zsregs[0].phys_addr))); + } } else if(len % sizeof(unsigned int)) { prom_printf("WHOOPS: proplen for %s " "was %d, need multiple of " @@ -1954,25 +2012,27 @@ get_zs(int chip)) /* Can use the prom for other machine types */ zsnode = prom_getchild(prom_root_node); if (sparc_cpu_model == sun4d) { - int board, node; + int node; + int no = 0; tmpnode = zsnode; + zsnode = 0; + bbnode = 0; while (tmpnode && (tmpnode = prom_searchsiblings(tmpnode, "cpu-unit"))) { - board = prom_getintdefault (tmpnode, "board#", -1); - if (board == (chip >> 1)) { - node = prom_getchild(tmpnode); - if (node && (node = prom_searchsiblings(node, "bootbus"))) { + bbnode = prom_getchild(tmpnode); + if (bbnode && (bbnode = prom_searchsiblings(bbnode, "bootbus"))) { + if (no == (chip >> 1)) { cpunode = tmpnode; - bbnode = node; - zsnode = prom_getchild(node); + zsnode = prom_getchild(bbnode); chipid = (chip & 1); break; } + no++; } tmpnode = prom_getsibling(tmpnode); } if (!tmpnode) - panic ("get_zs: couldn't find board%d's bootbus\n", chip >> 1); + panic ("get_zs: couldn't find %dth bootbus\n", chip >> 1); } else { tmpnode = prom_searchsiblings(zsnode, "obio"); if(tmpnode) @@ -2066,13 +2126,12 @@ __initfunc(int zs_probe (unsigned long *memory_start)) node = prom_getchild(prom_root_node); if (sparc_cpu_model == sun4d) { - node = prom_searchsiblings(node, "boards"); - if (!node) - panic ("Cannot find out count of boards"); - else - node = prom_getchild(node); - while (node && (node = prom_searchsiblings(node, "bif"))) { - NUM_SERIAL += 2; + int bbnode; + + while (node && (node = prom_searchsiblings(node, "cpu-unit"))) { + bbnode = prom_getchild(node); + if (bbnode && prom_searchsiblings(bbnode, "bootbus")) + NUM_SERIAL += 2; node = prom_getsibling(node); } goto no_probe; @@ -2082,7 +2141,7 @@ __initfunc(int zs_probe (unsigned long *memory_start)) int central_node; /* Central bus zilogs must be checked for first, - * since Enterprise boxes have SBUS as well. + * since Enterprise boxes might have SBUSes as well. */ central_node = prom_finddevice("/central"); if(central_node != 0 && central_node != -1) @@ -2219,11 +2278,6 @@ __initfunc(int zs_init(void)) return 0; #endif -#ifdef CONFIG_PCI - if (pci_present()) - return 0; -#endif - /* Setup base handler, and timer table. */ init_bh(SERIAL_BH, do_serial_bh); timer_table[RS_TIMER].fn = zs_timer; @@ -2290,13 +2344,21 @@ __initfunc(int zs_init(void)) /* Initialize Softinfo */ zs_prepare(); + /* Grab IRQ line before poking the chips so we do + * not lose any interrupts. + */ + if (request_irq(zilog_irq, zs_interrupt, + (SA_INTERRUPT | SA_STATIC_ALLOC), + "Zilog8530", zs_chain)) + panic("Unable to attach zs intr\n"); + /* Initialize Hardware */ for(channel = 0; channel < NUM_CHANNELS; channel++) { /* Hardware reset each chip */ if (!(channel & 1)) { write_zsreg(zs_soft[channel].zs_channel, R9, FHWRES); - udelay(20); /* wait for some old sun4's */ + ZSDELAY_LONG(); dummy = read_zsreg(zs_soft[channel].zs_channel, R0); } @@ -2462,10 +2524,6 @@ __initfunc(int zs_init(void)) printk(" is a Zilog8530\n"); } - if (request_irq(zilog_irq, zs_interrupt, - (SA_INTERRUPT | SA_STATIC_ALLOC), - "Zilog8530", zs_chain)) - panic("Unable to attach zs intr\n"); restore_flags(flags); keyboard_zsinit(kbd_put_char); @@ -2549,7 +2607,7 @@ static void zs_fair_output(struct sun_serial *info) /* Last character is being transmitted now (hopefully). */ info->zs_channel->control = RES_Tx_P; - udelay(5); + ZSDELAY(); restore_flags(flags); return; |