summaryrefslogtreecommitdiffstats
path: root/drivers/sbus/char
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
commit27cfca1ec98e91261b1a5355d10a8996464b63af (patch)
tree8e895a53e372fa682b4c0a585b9377d67ed70d0e /drivers/sbus/char
parent6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff)
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too o Upgrade to 2.1.89. Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'drivers/sbus/char')
-rw-r--r--drivers/sbus/char/.cvsignore1
-rw-r--r--drivers/sbus/char/Config.in6
-rw-r--r--drivers/sbus/char/Makefile34
-rw-r--r--drivers/sbus/char/creator.c4
-rw-r--r--drivers/sbus/char/flash.c232
-rw-r--r--drivers/sbus/char/mach64.c149
-rw-r--r--drivers/sbus/char/mach64.h8
-rw-r--r--drivers/sbus/char/openprom.c3
-rw-r--r--drivers/sbus/char/pcicons.c69
-rw-r--r--drivers/sbus/char/pcikbd.c296
-rw-r--r--drivers/sbus/char/pcikbd.h4
-rw-r--r--drivers/sbus/char/rtc.c5
-rw-r--r--drivers/sbus/char/sab82532.c522
-rw-r--r--drivers/sbus/char/sbuscons.c25
-rw-r--r--drivers/sbus/char/su.c26
-rw-r--r--drivers/sbus/char/suncons.c15
-rw-r--r--drivers/sbus/char/sunfb.c12
-rw-r--r--drivers/sbus/char/sunkbd.c74
-rw-r--r--drivers/sbus/char/sunkbd.h26
-rw-r--r--drivers/sbus/char/sunkbdmap.c33
-rw-r--r--drivers/sbus/char/sunmouse.c32
-rw-r--r--drivers/sbus/char/sunserial.c326
-rw-r--r--drivers/sbus/char/sunserial.h61
-rw-r--r--drivers/sbus/char/vfc_dev.c3
-rw-r--r--drivers/sbus/char/zs.c835
25 files changed, 1886 insertions, 915 deletions
diff --git a/drivers/sbus/char/.cvsignore b/drivers/sbus/char/.cvsignore
index 4671378ae..857dd22e9 100644
--- a/drivers/sbus/char/.cvsignore
+++ b/drivers/sbus/char/.cvsignore
@@ -1 +1,2 @@
.depend
+.*.flags
diff --git a/drivers/sbus/char/Config.in b/drivers/sbus/char/Config.in
index 90ecfc49a..4a8832678 100644
--- a/drivers/sbus/char/Config.in
+++ b/drivers/sbus/char/Config.in
@@ -19,6 +19,7 @@ if [ "$CONFIG_SUN_FB_DISPLAY" = "n" ]; then
fbs=$fbs$SUN_FB_CGFOURTEEN
fbs=$fbs$SUN_FB_LEO
fbs=$fbs$TADPOLE_FB_WEITEK
+ fbs=$fbs$SUN_FB_CREATOR
if [ "$fbs" = "nnnnnnnn" ]; then
echo "Warning: You have excluded ALL FB Support"
echo "Notice: Enabling Generic AutoResolution"
@@ -41,7 +42,10 @@ fi
comment 'Misc Linux/SPARC drivers'
tristate '/dev/openprom device support' CONFIG_SUN_OPENPROMIO
tristate 'Mostek real time clock support' CONFIG_SUN_MOSTEK_RTC
-tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532
+if [ "$ARCH" = "sparc64" ]; then
+ tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532
+ tristate 'OBP Flash Device support' CONFIG_OBP_FLASH
+fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Bidirectional parallel port support (EXPERIMENTAL)' CONFIG_SUN_BPP
diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile
index dfcc7afe3..5251d5090 100644
--- a/drivers/sbus/char/Makefile
+++ b/drivers/sbus/char/Makefile
@@ -51,13 +51,35 @@ endif
O_TARGET := sunchar.o
O_OBJ := ${FB_OBJS} suncons.o sbuscons.o pcicons.o sunfb.o
-O_OBJS := ${O_OBJ} sunkbd.o sunkeymap.o sunmouse.o sunserial.o zs.o
+O_OBJS := ${O_OBJ} sunkbd.o sunkbdmap.o sunmouse.o sunserial.o zs.o
M_OBJS :=
ifeq ($(ARCH),sparc64)
+
+ifeq ($(CONFIG_PCI),y)
+
O_OBJS += su.o pcikbd.o
+
+ifeq ($(CONFIG_SAB82532),y)
+O_OBJS += sab82532.o
+else
+ ifeq ($(CONFIG_SAB82532),m)
+ M_OBJS += sab82532.o
+ endif
endif
+endif # eq($(CONFIG_PCI,y)
+
+ifeq ($(CONFIG_OBP_FLASH),y)
+O_OBJS += flash.o
+else
+ ifeq ($(CONFIG_OBP_FLASH),m)
+ M_OBJS += flash.o
+ endif
+endif
+
+endif # eq($(ARCH),sparc64)
+
ifeq ($(CONFIG_SUN_OPENPROMIO),y)
O_OBJS += openprom.o
else
@@ -90,14 +112,6 @@ else
endif
endif
-ifeq ($(CONFIG_SAB82532),y)
-O_OBJS += sab82532.o
-else
- ifeq ($(CONFIG_SAB82532),m)
- M_OBJS += sab82532.o
- endif
-endif
-
# Add PCI console/fb drivers here.
#
ifeq ($(CONFIG_PCI),y)
@@ -106,5 +120,7 @@ endif
include $(TOPDIR)/Rules.make
+sunkbdmap.o: sunkeymap.c
+
vfc.o: vfc_dev.o vfc_i2c.o
$(LD) -r -o vfc.o vfc_dev.o vfc_i2c.o
diff --git a/drivers/sbus/char/creator.c b/drivers/sbus/char/creator.c
index 815e397e8..8b6ddf40f 100644
--- a/drivers/sbus/char/creator.c
+++ b/drivers/sbus/char/creator.c
@@ -1,4 +1,4 @@
-/* $Id: creator.c,v 1.12 1997/08/25 07:50:27 jj Exp $
+/* $Id: creator.c,v 1.13 1997/10/17 04:14:40 davem Exp $
* creator.c: Creator/Creator3D frame buffer driver
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -194,7 +194,7 @@ ffb_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
unsigned long map_offset = 0;
int i;
int alignment;
- struct vm_area_struct *vmm;
+ struct vm_area_struct *vmm = NULL;
size = vma->vm_end - vma->vm_start;
if (vma->vm_offset & ~PAGE_MASK)
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
new file mode 100644
index 000000000..ba67381a0
--- /dev/null
+++ b/drivers/sbus/char/flash.c
@@ -0,0 +1,232 @@
+/* $Id: flash.c,v 1.5 1997/11/01 10:22:13 ecd Exp $
+ * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
+ *
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/sbus.h>
+#include <asm/ebus.h>
+
+static struct {
+ unsigned long read_base;
+ unsigned long write_base;
+ unsigned long read_size;
+ unsigned long write_size;
+ unsigned long busy;
+} flash;
+
+#define FLASH_MINOR 152
+
+static int
+flash_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ unsigned long addr;
+ unsigned long size;
+
+ if (vma->vm_offset & ~(PAGE_MASK))
+ return -ENXIO;
+
+ if (flash.read_base == flash.write_base) {
+ addr = __pa(flash.read_base);
+ size = flash.read_size;
+ } else {
+ if ((vma->vm_flags & VM_READ) &&
+ (vma->vm_flags & VM_WRITE))
+ return -EINVAL;
+
+ if (vma->vm_flags & VM_READ) {
+ addr = __pa(flash.read_base);
+ size = flash.read_size;
+ } else if (vma->vm_flags & VM_WRITE) {
+ addr = __pa(flash.write_base);
+ size = flash.write_size;
+ } else
+ return -ENXIO;
+ }
+
+ if (vma->vm_offset > size)
+ return -ENXIO;
+ addr += vma->vm_offset;
+
+ if (vma->vm_end - (vma->vm_start + vma->vm_offset) > size)
+ size = vma->vm_end - (vma->vm_start + vma->vm_offset);
+
+ pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE);
+ pgprot_val(vma->vm_page_prot) |= _PAGE_E;
+ vma->vm_flags |= (VM_SHM | VM_LOCKED);
+
+ if (remap_page_range(vma->vm_start, addr, size, vma->vm_page_prot))
+ return -EAGAIN;
+ vma->vm_dentry = dget(file->f_dentry);
+ return 0;
+}
+
+static long long
+flash_llseek(struct file *file, long long offset, int origin)
+{
+ switch (origin) {
+ case 0:
+ file->f_pos = offset;
+ break;
+ case 1:
+ file->f_pos += offset;
+ if (file->f_pos > flash.read_size)
+ file->f_pos = flash.read_size;
+ break;
+ case 2:
+ file->f_pos = flash.read_size;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return file->f_pos;
+}
+
+static ssize_t
+flash_read(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long p = file->f_pos;
+
+ if (count > flash.read_size - p)
+ count = flash.read_size - p;
+
+ if (copy_to_user(buf, flash.read_base + p, count) < 0)
+ return -EFAULT;
+
+ file->f_pos += count;
+ return count;
+}
+
+static int
+flash_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, (void *)&flash.busy) != 0)
+ return -EBUSY;
+
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+flash_release(struct inode *inode, struct file *file)
+{
+ MOD_DEC_USE_COUNT;
+ flash.busy = 0;
+ return 0;
+}
+
+static struct file_operations flash_fops = {
+ flash_llseek,
+ flash_read,
+ NULL, /* no write to the Flash, use mmap
+ * and play flash dependent tricks.
+ */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl */
+ flash_mmap,
+ flash_open,
+ flash_release
+};
+
+static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
+
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int flash_init(void))
+#endif
+{
+ struct linux_sbus *sbus;
+ struct linux_sbus_device *sdev = 0;
+ struct linux_ebus *ebus;
+ struct linux_ebus_device *edev = 0;
+ struct linux_prom_registers regs[2];
+ int len, err;
+
+ for_all_sbusdev(sdev, sbus) {
+ if (!strcmp(sdev->prom_name, "flashprom")) {
+ prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
+ sdev->num_registers, sdev);
+ if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) {
+ flash.read_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
+ sdev->reg_addrs[0].reg_size, "flashprom",
+ sdev->reg_addrs[0].which_io, 0);
+ flash.read_size = sdev->reg_addrs[0].reg_size;
+ flash.write_base = flash.read_base;
+ flash.write_size = flash.read_size;
+ } else {
+ flash.read_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
+ sdev->reg_addrs[0].reg_size, "flashprom",
+ sdev->reg_addrs[0].which_io, 0);
+ flash.read_size = sdev->reg_addrs[0].reg_size;
+ flash.write_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0,
+ sdev->reg_addrs[1].reg_size, "flashprom",
+ sdev->reg_addrs[1].which_io, 0);
+ flash.write_size = sdev->reg_addrs[1].reg_size;
+ }
+ flash.busy = 0;
+ break;
+ }
+ }
+ if (!sdev) {
+#ifdef CONFIG_PCI
+ for_all_ebusdev(edev, ebus)
+ if (!strcmp(edev->prom_name, "flashprom"))
+ break;
+ if (!edev)
+ return -ENODEV;
+
+ len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs));
+ if (len != sizeof(regs)) {
+ printk("flash: Strange reg property size %d\n", len);
+ return -ENODEV;
+ }
+
+ flash.read_base = edev->base_address[0];
+ flash.read_size = regs[0].reg_size;
+ flash.write_base = edev->base_address[1];
+ flash.write_size = regs[1].reg_size;
+ flash.busy = 0;
+
+#else
+ return -ENODEV;
+#endif
+ }
+
+ printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n",
+ __pa(flash.read_base), flash.read_size,
+ __pa(flash.write_base), flash.write_size);
+
+ err = misc_register(&flash_dev);
+ if (err) {
+ printk(KERN_ERR "flash: unable to get misc minor\n");
+ return err;
+ }
+
+ return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+ misc_deregister(&flash_dev);
+}
+#endif
diff --git a/drivers/sbus/char/mach64.c b/drivers/sbus/char/mach64.c
index c3c562306..05ed175d3 100644
--- a/drivers/sbus/char/mach64.c
+++ b/drivers/sbus/char/mach64.c
@@ -1,4 +1,4 @@
-/* $Id: mach64.c,v 1.8 1997/08/25 07:50:34 jj Exp $
+/* $Id: mach64.c,v 1.11 1997/10/17 04:13:35 davem Exp $
* mach64.c: Ultra/PCI Mach64 console driver.
*
* Just about all of this is from the PPC/mac driver, see that for
@@ -8,6 +8,7 @@
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h> /* for CONFIG_CHIP_ID */
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -22,13 +23,18 @@
#include <asm/pbm.h>
#include <asm/fbio.h>
#include <asm/sbus.h>
+#include <asm/pgtable.h>
#include "pcicons.h"
#include "mach64.h"
#include "fb.h"
+static unsigned int mach64_pci_membase;
+static unsigned int mach64_pci_iobase;
+
+#define MACH64_LE_FBOFF 0x000000
#define MACH64_REGOFF 0x7ffc00
-#define MACH64_FBOFF 0x800000
+#define MACH64_BE_FBOFF 0x800000
static inline void mach64_waitq(int entries)
{
@@ -69,7 +75,35 @@ static int
mach64_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma,
long base, fbinfo_t *fb)
{
- return -ENOSYS;
+ unsigned long addr, size;
+
+ size = vma->vm_end - vma->vm_start;
+ if (vma->vm_offset & ~PAGE_MASK)
+ return -ENXIO;
+
+ if (vma->vm_offset == mach64_pci_iobase) {
+ addr = __pa(pcivga_iobase);
+ size = PAGE_SIZE;
+ } else if (vma->vm_offset >= (mach64_pci_membase + 0x800000)) {
+ addr = __pa(pcivga_membase) - mach64_pci_membase
+ + vma->vm_offset;
+ pgprot_val(vma->vm_page_prot) |= _PAGE_IE;
+ } else if (vma->vm_offset >= mach64_pci_membase) {
+ addr = __pa(pcivga_membase) - mach64_pci_membase
+ + vma->vm_offset;
+ } else {
+ return -EINVAL;
+ }
+
+ pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE);
+ pgprot_val(vma->vm_page_prot) |= _PAGE_E;
+ vma->vm_flags |= (VM_SHM | VM_LOCKED);
+
+ if (remap_page_range(vma->vm_start, addr, size, vma->vm_page_prot))
+ return -EAGAIN;
+
+ vma->vm_dentry = dget(file->f_dentry);
+ return 0;
}
static void
@@ -113,11 +147,29 @@ mach64_unblank(fbinfo_t *fb)
static struct mach64_info mach64;
+void mach64_test(fbinfo_t *fb)
+{
+ unsigned int x;
+ int i;
+
+ for (i = 0; i < mach64.total_vram; i += 4)
+ writel(i, pcivga_membase + i);
+
+ for (i = 0; i < mach64.total_vram; i += 4)
+ if ((x = readl(pcivga_membase + i)) != i) {
+ printk("vga mem read error @ %08x: exp %x, rd %x\n",
+ i, i, x);
+ i = (i & ~(0xffff)) + 0x10000;
+ }
+}
+
int mach64_init(fbinfo_t *fb)
{
struct pci_dev *pdev;
struct pcidev_cookie *cookie;
+ struct linux_pbm_info *pbm;
unsigned long addr;
+ unsigned int tmp;
memset(&mach64, 0, sizeof(mach64));
for(pdev = pci_devices; pdev; pdev = pdev->next) {
@@ -148,49 +200,86 @@ int mach64_init(fbinfo_t *fb)
prom_halt();
}
+ pcibios_read_config_dword(pdev->bus->number, pdev->devfn,
+ PCI_BASE_ADDRESS_0, &mach64_pci_membase);
+ mach64_pci_membase &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ pcibios_read_config_dword(pdev->bus->number, pdev->devfn,
+ PCI_BASE_ADDRESS_1, &mach64_pci_iobase);
+ mach64_pci_iobase &= PCI_BASE_ADDRESS_IO_MASK;
+
printk("mach64_init: IOBASE[%016lx] MEMBASE[%016lx]\n",
pcivga_iobase, pcivga_membase);
- cookie = (struct pcidev_cookie *)pdev->sysdata;
+ cookie = pdev->sysdata;
+ pbm = cookie->pbm;
+
fb->prom_node = cookie->prom_node;
- fb->proc_entry.node = cookie->pbm->prom_node;
+ fb->proc_entry.node = pbm->prom_node;
fb->type.fb_type = FBTYPE_PCI_MACH64;
fb->type.fb_cmsize = 256;
fb->info.private = (void *)&mach64;
- fb->base = pcivga_membase + MACH64_FBOFF;
-
- switch(pcivga_readl(MACH64_REGOFF + MEM_CNTL) & MEM_SIZE_ALIAS) {
- case MEM_SIZE_512K:
- mach64.total_vram = 0x80000;
- break;
- case MEM_SIZE_1M:
- mach64.total_vram = 0x100000;
- break;
- case MEM_SIZE_2M:
- mach64.total_vram = 0x200000;
- break;
- case MEM_SIZE_4M:
- mach64.total_vram = 0x400000;
- break;
- case MEM_SIZE_6M:
- mach64.total_vram = 0x600000;
- break;
- case MEM_SIZE_8M:
- mach64.total_vram = 0x800000;
- break;
- default:
- mach64.total_vram = 0x80000;
- break;
- }
+ fb->base = pcivga_membase + MACH64_BE_FBOFF;
if ((pcivga_readl(MACH64_REGOFF + CONFIG_CHIP_ID)
& CFG_CHIP_TYPE) == MACH64_VT_ID)
mach64.flags |= MACH64_MASK_VT;
+ /*
+ * Fix the PROM's idea of MEM_CNTL settings...
+ */
+ tmp = pcivga_readl(MACH64_REGOFF + MEM_CNTL);
+ switch (tmp & 0xf) {
+ case 3:
+ tmp = (tmp & ~(0xf)) | 2;
+ break;
+ case 7:
+ tmp = (tmp & ~(0xf)) | 3;
+ break;
+ case 9:
+ tmp = (tmp & ~(0xf)) | 4;
+ break;
+ case 11:
+ tmp = (tmp & ~(0xf)) | 5;
+ break;
+ default:
+ break;
+ }
+ tmp &= ~(0x00f00000);
+ pcivga_writel(tmp, MACH64_REGOFF + MEM_CNTL);
+
+ switch(tmp & MEM_SIZE_ALIAS) {
+ case MEM_SIZE_512K:
+ mach64.total_vram = 0x80000;
+ break;
+ case MEM_SIZE_1M:
+ mach64.total_vram = 0x100000;
+ break;
+ case MEM_SIZE_2M:
+ mach64.total_vram = 0x200000;
+ break;
+ case MEM_SIZE_4M:
+ mach64.total_vram = 0x400000;
+ break;
+ case MEM_SIZE_6M:
+ mach64.total_vram = 0x600000;
+ break;
+ case MEM_SIZE_8M:
+ mach64.total_vram = 0x800000;
+ break;
+ default:
+ mach64.total_vram = 0x80000;
+ break;
+ }
+
printk("mach64_init: total_vram[%08x] is_vt_chip[%d]\n",
mach64.total_vram, mach64.flags & MACH64_MASK_VT ? 1 : 0);
+#if 0
+ mach64_test(fb);
+#endif
+
fb->mmap = mach64_mmap;
fb->loadcmap = mach64_loadcmap;
fb->ioctl = 0;
diff --git a/drivers/sbus/char/mach64.h b/drivers/sbus/char/mach64.h
index 8bf6be478..02593fa7b 100644
--- a/drivers/sbus/char/mach64.h
+++ b/drivers/sbus/char/mach64.h
@@ -1,4 +1,4 @@
-/* $Id: mach64.h,v 1.3 1997/08/24 12:13:07 ecd Exp $
+/* $Id: mach64.h,v 1.4 1997/10/04 08:51:30 ecd Exp $
* mach64.h: Ultra/PCI mach64 driver constants etc.
*
* Copyright 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -42,6 +42,9 @@ struct mach64_info {
#define CRTC_FIFO 0x001e
#define CRTC_EXT_DISP 0x001f
+#define SHARED_CNTL 0x0030 /* Dword offset 0C */
+#define SHARED_MEM_CONFIG 0x0034 /* Dword offset 0D */
+
#define OVR_CLR 0x0040 /* Dword offset 10 */
#define OVR_WID_LEFT_RIGHT 0x0044 /* Dword offset 11 */
#define OVR_WID_TOP_BOTTOM 0x0048 /* Dword offset 12 */
@@ -60,6 +63,7 @@ struct mach64_info {
#define BUS_CNTL 0x00A0 /* Dword offset 28 */
+#define EXT_MEM_CNTL 0x00AC /* Dword offset 2B */
#define MEM_CNTL 0x00B0 /* Dword offset 2C */
#define MEM_VGA_WP_SEL 0x00B4 /* Dword offset 2D */
@@ -359,6 +363,8 @@ struct mach64_info {
#define MEM_SIZE_6M 0x00000004
#define MEM_SIZE_8M 0x00000005
#define MEM_SIZE_ALIAS_GTB 0x0000000F
+#define MEM_SIZE_512K_GTB 0x00000000
+#define MEM_SIZE_1M_GTB 0x00000001
#define MEM_SIZE_2M_GTB 0x00000003
#define MEM_SIZE_4M_GTB 0x00000007
#define MEM_SIZE_6M_GTB 0x00000009
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 75b950071..6d09bfca4 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -526,8 +526,7 @@ static int openprom_ioctl(struct inode * inode, struct file * file,
}
}
-static long long openprom_lseek(struct inode * inode, struct file * file,
- long long offset, int origin)
+static long long openprom_lseek(struct file * file, long long offset, int origin)
{
return -ESPIPE;
}
diff --git a/drivers/sbus/char/pcicons.c b/drivers/sbus/char/pcicons.c
index 82c0df9aa..c20796e63 100644
--- a/drivers/sbus/char/pcicons.c
+++ b/drivers/sbus/char/pcicons.c
@@ -1,4 +1,4 @@
-/* $Id: pcicons.c,v 1.9 1997/08/28 02:23:24 ecd Exp $
+/* $Id: pcicons.c,v 1.10 1997/10/04 08:52:57 ecd Exp $
* pcicons.c: PCI specific probing and console operations layer.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -37,14 +37,9 @@ static int x_margin = 0;
static int y_margin = 0;
static int skip_bytes;
-static void pci_cursor_blink(unsigned long);
-static __u32 *cursor_screen_pos;
-static __u32 cursor_bits;
+static __u64 *cursor_screen_pos;
+static __u64 cursor_bits[2];
static int cursor_pos = -1;
-static int cursor_off = 1;
-static struct timer_list pci_cursor_timer = {
- NULL, NULL, 0, 0, pci_cursor_blink
-};
extern int serial_console;
@@ -219,52 +214,24 @@ static void pci_set_scrmem(int currcons, long offset)
static void pci_invert_cursor(int cpos)
{
fbinfo_t *fb = &fbinfo[0];
- unsigned char color;
- __u32 *screen, mask;
- int i;
-
- del_timer(&pci_cursor_timer);
+ __u64 *screen;
if (cpos == -1) {
- if (cursor_off)
- return;
screen = cursor_screen_pos;
- mask = cursor_bits;
- } else {
- screen = (__u32 *)(fb->base + fbuf_offset(cpos)
- + 14 * fb->linebytes);
-
- color = CHARATTR_TO_SUNCOLOR(
- vc_cons[fg_console].d->vc_color << 8);
-
- mask = (color ^ (color >> 4)) & 0x0f;
- mask |= mask << 8;
- mask |= mask << 16;
-
- cursor_screen_pos = screen;
- cursor_bits = mask;
-
- pci_cursor_timer.expires = jiffies + (HZ >> 2);
- add_timer(&pci_cursor_timer);
- }
-
- for (i = 0; i < 2; i++) {
- screen[0] ^= mask;
- screen[1] ^= mask;
- screen = (__u32 *)((unsigned long)screen + fb->linebytes);
+ *screen = cursor_bits[0];
+ screen = (__u64 *)((unsigned long)screen + fb->linebytes);
+ *screen = cursor_bits[1];
+ return;
}
-}
-static void pci_cursor_blink(unsigned long ignored)
-{
- unsigned long flags;
+ screen = (__u64 *)(fb->base + fbuf_offset(cpos) + 14 * fb->linebytes);
+ cursor_screen_pos = screen;
- save_flags(flags); cli();
- if (cursor_pos != -1) {
- pci_invert_cursor(cursor_pos);
- cursor_off = 1 - cursor_off;
- }
- restore_flags(flags);
+ cursor_bits[0] = *screen;
+ *screen = 0x0000000000000000;
+ screen = (__u64 *)((unsigned long)screen + fb->linebytes);
+ cursor_bits[1] = *screen;
+ *screen = 0x0000000000000000;
}
static void pci_hide_cursor(void)
@@ -275,11 +242,8 @@ static void pci_hide_cursor(void)
return;
save_flags(flags); cli();
- if (cursor_pos != -1) {
+ if (cursor_pos != -1)
pci_invert_cursor(-1);
- cursor_pos = -1;
- }
- cursor_off = 1;
restore_flags(flags);
}
@@ -300,7 +264,6 @@ static void pci_set_cursor(int currcons)
if (old_cursor != -1)
pci_invert_cursor(-1);
pci_invert_cursor(cursor_pos);
- cursor_off = 0;
}
restore_flags(flags);
}
diff --git a/drivers/sbus/char/pcikbd.c b/drivers/sbus/char/pcikbd.c
index 8d90f85d6..31485aac8 100644
--- a/drivers/sbus/char/pcikbd.c
+++ b/drivers/sbus/char/pcikbd.c
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.4 1997/09/05 22:59:53 ecd Exp $
+/* $Id: pcikbd.c,v 1.12 1997/12/27 16:28:27 jj Exp $
* pcikbd.c: Ultra/AX PC keyboard support.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -8,6 +8,7 @@
* to the original authors.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -19,6 +20,7 @@
#include <linux/random.h>
#include <linux/miscdevice.h>
#include <linux/kbd_ll.h>
+#include <linux/delay.h>
#include <linux/init.h>
#include <asm/ebus.h>
@@ -26,7 +28,6 @@
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <asm/keyboard.h>
#include "pcikbd.h"
#include "sunserial.h"
@@ -35,6 +36,7 @@ static int kbd_node;
static int beep_node;
static unsigned long pcikbd_iobase = 0;
+static unsigned long pcibeep_iobase = 0;
static unsigned int pcikbd_irq;
/* used only by send_data - set by keyboard_interrupt */
@@ -42,12 +44,31 @@ static volatile unsigned char reply_expected = 0;
static volatile unsigned char acknowledge = 0;
static volatile unsigned char resend = 0;
+unsigned char pckbd_read_mask = KBD_STAT_OBF;
+
+extern int pcikbd_init(void);
+extern void pci_compute_shiftstate(void);
+extern int pci_setkeycode(unsigned int, unsigned int);
+extern int pci_getkeycode(unsigned int);
+extern void pci_setledstate(struct kbd_struct *, unsigned int);
+extern unsigned char pci_getledstate(void);
+
+static __inline__ unsigned char pcikbd_inb(unsigned long port)
+{
+ return inb(port);
+}
+
+static __inline__ void pcikbd_outb(unsigned char val, unsigned long port)
+{
+ outb(val, port);
+}
+
static inline void kb_wait(void)
{
unsigned long start = jiffies;
do {
- if(!(inb(pcikbd_iobase + KBD_STATUS_REG) & KBD_STAT_IBF))
+ if(!(pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG) & KBD_STAT_IBF))
return;
} while (jiffies - start < KBC_TIMEOUT);
}
@@ -167,6 +188,19 @@ static unsigned char e0_keys[128] = {
0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
};
+/* Simple translation table for the SysRq keys */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char pcikbd_sysrq_xlate[128] =
+ "\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
+ "qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
+ "dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
+ "bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
+ "\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
+ "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+ "\r\000/"; /* 0x60 - 0x6f */
+#endif
+
static unsigned int prev_scancode = 0;
int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode)
@@ -268,25 +302,17 @@ pcikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char status;
- /*
- * This IRQ might be shared with the 16550A serial chip,
- * so we check dev_id to see if it was for us.
- * (See also drivers/sbus/char/su.c).
- */
- if (dev_id)
- return;
-
- /* kbd_pt_regs = regs; */
- status = inb(pcikbd_iobase + KBD_STATUS_REG);
+ kbd_pt_regs = regs;
+ status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
do {
unsigned char scancode;
- if(status & kbd_read_mask & KBD_STAT_MOUSE_OBF)
+ if(status & pckbd_read_mask & KBD_STAT_MOUSE_OBF)
break;
- scancode = inb(pcikbd_iobase + KBD_DATA_REG);
+ scancode = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
if((status & KBD_STAT_OBF) && do_acknowledge(scancode))
- /* handle_scancode(scancode) */;
- status = inb(pcikbd_iobase + KBD_STATUS_REG);
+ handle_scancode(scancode);
+ status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
} while(status & KBD_STAT_OBF);
mark_bh(KEYBOARD_BH);
}
@@ -300,7 +326,7 @@ static int send_data(unsigned char data)
kb_wait();
acknowledge = resend = 0;
reply_expected = 1;
- outb(data, pcikbd_iobase + KBD_DATA_REG);
+ pcikbd_outb(data, pcikbd_iobase + KBD_DATA_REG);
start = jiffies;
do {
if(acknowledge)
@@ -325,10 +351,10 @@ __initfunc(static int pcikbd_wait_for_input(void))
unsigned long start = jiffies;
do {
- status = inb(pcikbd_iobase + KBD_STATUS_REG);
+ status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
if(!(status & KBD_STAT_OBF))
continue;
- data = inb(pcikbd_iobase + KBD_DATA_REG);
+ data = pcikbd_inb(pcikbd_iobase + KBD_DATA_REG);
if(status & (KBD_STAT_GTO | KBD_STAT_PERR))
continue;
return (data & 0xff);
@@ -341,18 +367,55 @@ __initfunc(static void pcikbd_write(int address, int data))
int status;
do {
- status = inb(pcikbd_iobase + KBD_STATUS_REG);
+ status = pcikbd_inb(pcikbd_iobase + KBD_STATUS_REG);
} while (status & KBD_STAT_IBF);
- outb(data, pcikbd_iobase + address);
+ pcikbd_outb(data, pcikbd_iobase + address);
+}
+
+/* Timer routine to turn off the beep after the interval expires. */
+static void pcikbd_kd_nosound(unsigned long __unused)
+{
+ outl(0, pcibeep_iobase);
}
-__initfunc(static char *do_pcikbd_hwinit(void))
+/*
+ * Initiate a keyboard beep. If the frequency is zero, then we stop
+ * the beep. Any other frequency will start a monotone beep. The beep
+ * will be stopped by a timer after "ticks" jiffies. If ticks is 0,
+ * then we do not start a timer.
+ */
+static void pcikbd_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+ unsigned long flags;
+ static struct timer_list sound_timer = { NULL, NULL, 0, 0,
+ pcikbd_kd_nosound };
+
+ save_flags(flags); cli();
+ del_timer(&sound_timer);
+ if (hz) {
+ outl(1, pcibeep_iobase);
+ if (ticks) {
+ sound_timer.expires = jiffies + ticks;
+ add_timer(&sound_timer);
+ }
+ } else
+ outl(0, pcibeep_iobase);
+ restore_flags(flags);
+}
+
+static void nop_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+}
+
+extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
+
+__initfunc(static char *do_pcikbd_init_hw(void))
{
while(pcikbd_wait_for_input() != -1)
;
pcikbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);
- if(pcikbd_wait_for_input() != 0xff)
+ if(pcikbd_wait_for_input() != 0x55)
return "Keyboard failed self test";
pcikbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);
@@ -388,23 +451,12 @@ __initfunc(static char *do_pcikbd_hwinit(void))
return NULL; /* success */
}
-__initfunc(void pcikbd_hwinit(void))
-{
- char *msg;
-
- disable_irq(pcikbd_irq);
- msg = do_pcikbd_hwinit();
- enable_irq(pcikbd_irq);
-
- if(msg)
- printk("8042: keyboard init failure [%s]\n", msg);
-}
-
-__initfunc(int pcikbd_probe(void))
+__initfunc(void pcikbd_init_hw(void))
{
struct linux_ebus *ebus;
struct linux_ebus_device *edev;
struct linux_ebus_child *child;
+ char *msg;
for_all_ebusdev(edev, ebus) {
if(!strcmp(edev->prom_name, "8042")) {
@@ -415,29 +467,57 @@ __initfunc(int pcikbd_probe(void))
}
}
printk("pcikbd_probe: no 8042 found\n");
- return -ENODEV;
+ return;
found:
pcikbd_iobase = child->base_address[0];
if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
printk("8042: can't get region %lx, %d\n",
pcikbd_iobase, (int)sizeof(unsigned long));
- return -ENODEV;
+ return;
}
request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
pcikbd_irq = child->irqs[0];
if (request_irq(pcikbd_irq, &pcikbd_interrupt,
- SA_SHIRQ, "keyboard", NULL)) {
+ SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
printk("8042: cannot register IRQ %x\n", pcikbd_irq);
- return -ENODEV;
+ return;
}
printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, pcikbd_irq);
- /* pcikbd_init(); */
- kbd_read_mask = KBD_STAT_OBF;
- return 0;
+ kd_mksound = nop_kd_mksound;
+ for_all_ebusdev(edev, ebus) {
+ if(!strcmp(edev->prom_name, "beeper"))
+ break;
+ }
+
+ /*
+ * XXX: my 3.1.3 PROM does not give me the beeper node for the audio
+ * auxio register, though I know it is there... (ecd)
+ */
+ if (!edev)
+ pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;
+ else
+ pcibeep_iobase = edev->base_address[0];
+
+ if (check_region(pcibeep_iobase, sizeof(unsigned int))) {
+ printk("8042: can't get region %lx, %d\n",
+ pcibeep_iobase, (int)sizeof(unsigned int));
+ } else {
+ request_region(pcibeep_iobase, sizeof(unsigned int), "speaker");
+ kd_mksound = pcikbd_kd_mksound;
+ printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,
+ edev ? "" : " (forced)");
+ }
+
+ disable_irq(pcikbd_irq);
+ msg = do_pcikbd_init_hw();
+ enable_irq(pcikbd_irq);
+
+ if(msg)
+ printk("8042: keyboard init failure [%s]\n", msg);
}
@@ -451,8 +531,6 @@ static int ms_node;
static unsigned long pcimouse_iobase = 0;
static unsigned int pcimouse_irq;
-#define PSMOUSE_MINOR 1 /* Minor device # for this mouse */
-
#define AUX_BUF_SIZE 2048
struct aux_queue {
@@ -468,6 +546,16 @@ static int aux_ready = 0;
static int aux_count = 0;
static int aux_present = 0;
+static __inline__ unsigned char pcimouse_inb(unsigned long port)
+{
+ return inb(port);
+}
+
+static __inline__ void pcimouse_outb(unsigned char val, unsigned long port)
+{
+ outb(val, port);
+}
+
/*
* Shared subroutines
*/
@@ -491,11 +579,11 @@ static inline int queue_empty(void)
return queue->head == queue->tail;
}
-static int fasync_aux(struct inode *inode, struct file *filp, int on)
+static int aux_fasync(struct file *filp, int on)
{
int retval;
- retval = fasync_helper(inode, filp, on, &queue->fasync);
+ retval = fasync_helper(filp, on, &queue->fasync);
if (retval < 0)
return retval;
return 0;
@@ -521,11 +609,11 @@ static int poll_aux_status(void)
{
int retries=0;
- while ((inb(pcimouse_iobase + KBD_STATUS_REG) &
+ while ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) &
(KBD_STAT_IBF | KBD_STAT_OBF)) && retries < MAX_RETRIES) {
- if ((inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF)
+ if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF)
== AUX_STAT_OBF)
- inb(pcimouse_iobase + KBD_DATA_REG);
+ pcimouse_inb(pcimouse_iobase + KBD_DATA_REG);
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (5*HZ + 99) / 100;
schedule();
@@ -541,9 +629,10 @@ static int poll_aux_status(void)
static void aux_write_dev(int val)
{
poll_aux_status();
- outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);/* Write magic cookie */
+ pcimouse_outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);/* Write magic cookie */
poll_aux_status();
- outb_p(val, pcimouse_iobase + KBD_DATA_REG); /* Write data */
+ pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG); /* Write data */
+ udelay(1);
}
/*
@@ -555,8 +644,8 @@ __initfunc(static int aux_write_ack(int val))
aux_write_dev(val);
poll_aux_status();
- if ((inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF)
- return (inb(pcimouse_iobase + KBD_DATA_REG));
+ if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF)
+ return (pcimouse_inb(pcimouse_iobase + KBD_DATA_REG));
return 0;
}
@@ -567,9 +656,9 @@ __initfunc(static int aux_write_ack(int val))
static void aux_write_cmd(int val)
{
poll_aux_status();
- outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
+ pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
poll_aux_status();
- outb(val, pcimouse_iobase + KBD_DATA_REG);
+ pcimouse_outb(val, pcimouse_iobase + KBD_DATA_REG);
}
/*
@@ -607,18 +696,10 @@ void pcimouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int head = queue->head;
int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
- /*
- * This IRQ might be shared with the 16550A serial chip,
- * so we check dev_id to see if it was for us.
- * (See also drivers/sbus/char/su.c).
- */
- if (dev_id)
- return;
-
- if ((inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) != AUX_STAT_OBF)
+ if ((pcimouse_inb(pcimouse_iobase + KBD_STATUS_REG) & AUX_STAT_OBF) != AUX_STAT_OBF)
return;
- add_mouse_randomness(queue->buf[head] = inb(pcimouse_iobase + KBD_DATA_REG));
+ add_mouse_randomness(queue->buf[head] = pcimouse_inb(pcimouse_iobase + KBD_DATA_REG));
if (head != maxhead) {
head++;
head &= AUX_BUF_SIZE-1;
@@ -630,9 +711,9 @@ void pcimouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
wake_up_interruptible(&queue->proc_list);
}
-static int release_aux(struct inode * inode, struct file * file)
+static int aux_release(struct inode * inode, struct file * file)
{
- fasync_aux(inode, file, 0);
+ aux_fasync(file, 0);
if (--aux_count)
return 0;
aux_start_atomic();
@@ -642,7 +723,7 @@ static int release_aux(struct inode * inode, struct file * file)
poll_aux_status();
/* Disable Aux device */
- outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
+ pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
poll_aux_status();
aux_end_atomic();
@@ -655,10 +736,11 @@ static int release_aux(struct inode * inode, struct file * file)
* Enable auxiliary device.
*/
-static int open_aux(struct inode * inode, struct file * file)
+static int aux_open(struct inode * inode, struct file * file)
{
if (!aux_present)
return -ENODEV;
+
aux_start_atomic();
if (aux_count++) {
aux_end_atomic();
@@ -674,7 +756,7 @@ static int open_aux(struct inode * inode, struct file * file)
MOD_INC_USE_COUNT;
poll_aux_status();
- outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase+KBD_CNTL_REG); /* Enable Aux */
+ pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase+KBD_CNTL_REG); /* Enable Aux */
aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */
aux_write_cmd(AUX_INTS_ON); /* Enable controller ints */
poll_aux_status();
@@ -688,31 +770,31 @@ static int open_aux(struct inode * inode, struct file * file)
* Write to the aux device.
*/
-static long write_aux(struct inode * inode, struct file * file,
- const char * buffer, unsigned long count)
+static ssize_t aux_write(struct file * file, const char * buffer,
+ size_t count, loff_t *ppos)
{
- int retval = 0;
+ ssize_t retval = 0;
if (count) {
- int written = 0;
+ ssize_t written = 0;
aux_start_atomic();
do {
char c;
if (!poll_aux_status())
break;
- outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);
+ pcimouse_outb(KBD_CCMD_WRITE_MOUSE, pcimouse_iobase + KBD_CNTL_REG);
if (!poll_aux_status())
break;
get_user(c, buffer++);
- outb(c, pcimouse_iobase + KBD_DATA_REG);
+ pcimouse_outb(c, pcimouse_iobase + KBD_DATA_REG);
written++;
} while (--count);
aux_end_atomic();
retval = -EIO;
if (written) {
retval = written;
- inode->i_mtime = CURRENT_TIME;
+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
}
}
@@ -727,11 +809,11 @@ static long write_aux(struct inode * inode, struct file * file,
* Put bytes from input queue to buffer.
*/
-static long read_aux(struct inode * inode, struct file * file,
- char * buffer, unsigned long count)
+static ssize_t aux_read(struct file * file, char * buffer,
+ size_t count, loff_t *ppos)
{
struct wait_queue wait = { current, NULL };
- int i = count;
+ ssize_t i = count;
unsigned char c;
if (queue_empty()) {
@@ -754,7 +836,7 @@ repeat:
}
aux_ready = !queue_empty();
if (count-i) {
- inode->i_atime = CURRENT_TIME;
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count-i;
}
if (signal_pending(current))
@@ -764,7 +846,7 @@ repeat:
static unsigned int aux_poll(struct file *file, poll_table * wait)
{
- poll_wait(&queue->proc_list, wait);
+ poll_wait(file, &queue->proc_list, wait);
if (aux_ready)
return POLLIN | POLLRDNORM;
return 0;
@@ -772,16 +854,16 @@ static unsigned int aux_poll(struct file *file, poll_table * wait)
struct file_operations psaux_fops = {
NULL, /* seek */
- read_aux,
- write_aux,
+ aux_read,
+ aux_write,
NULL, /* readdir */
aux_poll,
NULL, /* ioctl */
NULL, /* mmap */
- open_aux,
- release_aux,
+ aux_open,
+ aux_release,
NULL,
- fasync_aux,
+ aux_fasync,
};
static struct miscdevice psaux_mouse = {
@@ -816,7 +898,7 @@ found:
pcimouse_irq = child->irqs[0];
if (request_irq(pcimouse_irq, &pcimouse_interrupt,
- SA_SHIRQ, "mouse", NULL)) {
+ SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) {
printk("8042: Cannot register IRQ %x\n", pcimouse_irq);
return -ENODEV;
}
@@ -826,7 +908,7 @@ found:
printk("8042: PS/2 auxiliary pointing device detected.\n");
aux_present = 1;
- kbd_read_mask = AUX_STAT_OBF;
+ pckbd_read_mask = AUX_STAT_OBF;
misc_register(&psaux_mouse);
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
@@ -834,18 +916,19 @@ found:
queue->head = queue->tail = 0;
queue->proc_list = NULL;
aux_start_atomic();
- outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG);
+ pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG);
+ aux_write_ack(AUX_RESET);
aux_write_ack(AUX_SET_SAMPLE);
aux_write_ack(100);
aux_write_ack(AUX_SET_RES);
aux_write_ack(3);
aux_write_ack(AUX_SET_SCALE21);
poll_aux_status();
- outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
+ pcimouse_outb(KBD_CCMD_MOUSE_DISABLE, pcimouse_iobase + KBD_CNTL_REG);
poll_aux_status();
- outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
+ pcimouse_outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
poll_aux_status();
- outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG);
+ pcimouse_outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG);
poll_aux_status();
aux_end_atomic();
@@ -853,21 +936,6 @@ found:
}
-__initfunc(static int ps2_init(void))
-{
- int err;
-
- err = pcikbd_probe();
- if (err)
- return err;
-
- err = pcimouse_init();
- if (err)
- return err;
-
- return 0;
-}
-
__initfunc(int ps2kbd_probe(unsigned long *memory_start))
{
int pnode, enode, node, dnode;
@@ -959,6 +1027,12 @@ __initfunc(int ps2kbd_probe(unsigned long *memory_start))
return -ENODEV;
found:
- sunserial_setinitfunc(memory_start, ps2_init);
+ sunkbd_setinitfunc(memory_start, pcimouse_init);
+ sunkbd_setinitfunc(memory_start, pcikbd_init);
+ kbd_ops.compute_shiftstate = pci_compute_shiftstate;
+ kbd_ops.setledstate = pci_setledstate;
+ kbd_ops.getledstate = pci_getledstate;
+ kbd_ops.setkeycode = pci_setkeycode;
+ kbd_ops.getkeycode = pci_getkeycode;
return 0;
}
diff --git a/drivers/sbus/char/pcikbd.h b/drivers/sbus/char/pcikbd.h
index 234a5e980..a9e38090c 100644
--- a/drivers/sbus/char/pcikbd.h
+++ b/drivers/sbus/char/pcikbd.h
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.h,v 1.1 1997/08/24 02:53:25 davem Exp $
+/* $Id: pcikbd.h,v 1.2 1997/12/25 21:13:14 geert Exp $
* pcikbd.h: PCI/PC 8042 keyboard/mouse driver stuff. Mostly snarfed
* from the existing driver by Martin Mares.
*
@@ -28,7 +28,7 @@
* Internal variables of the driver
*/
-extern unsigned char kbd_read_mask;
+extern unsigned char pckbd_read_mask;
extern unsigned char aux_device_present;
extern unsigned long pcikbd_iobase;
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index e0fbf2569..ccc8dd2cd 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -1,4 +1,4 @@
-/* $Id: rtc.c,v 1.10 1997/04/03 08:47:55 davem Exp $
+/* $Id: rtc.c,v 1.11 1997/09/20 20:47:26 davem Exp $
*
* Linux/SPARC Real Time Clock Driver
* Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -70,8 +70,7 @@ void set_rtc_time(struct rtc_time *t)
restore_flags(flags);
}
-static long long rtc_lseek(struct inode *inode, struct file *file,
- long long offset, int origin)
+static long long rtc_lseek(struct file *file, long long offset, int origin)
{
return -ESPIPE;
}
diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c
index 2134d3d75..9eed1d7f6 100644
--- a/drivers/sbus/char/sab82532.c
+++ b/drivers/sbus/char/sab82532.c
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.4 1997/09/03 17:04:21 ecd Exp $
+/* $Id: sab82532.c,v 1.13 1997/12/30 09:37:49 ecd Exp $
* sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -16,6 +16,7 @@
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
+#include <linux/console.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
@@ -40,6 +41,9 @@ static int sab82532_refcount;
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
+#define SERIAL_PARANOIA_CHECK
+#define SERIAL_DO_RESTART
+
/* Set of debugging defines */
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_INTR
@@ -59,10 +63,23 @@ static struct tty_struct *sab82532_table[NR_PORTS];
static struct termios *sab82532_termios[NR_PORTS];
static struct termios *sab82532_termios_locked[NR_PORTS];
+#ifdef CONFIG_SERIAL_CONSOLE
+extern int serial_console;
+static struct console sab82532_console;
+static int sab82532_console_init(void);
+#endif
+
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
+static char *sab82532_version[16] = {
+ "V1.0", "V2.0", "V3.2", "V(0x03)",
+ "V(0x04)", "V(0x05)", "V(0x06)", "V(0x07)",
+ "V(0x08)", "V(0x09)", "V(0x0a)", "V(0x0b)",
+ "V(0x0c)", "V(0x0d)", "V(0x0e)", "V(0x0f)"
+};
+
/*
* tmp_buf is used as a temporary buffer by sab82532_write. We need to
* lock it in case the copy_from_user blocks while swapping in a page,
@@ -178,8 +195,10 @@ static void sab82532_start(struct tty_struct *tty)
restore_flags(flags);
}
-static void batten_down_hatches(void)
+static void batten_down_hatches(struct sab82532 *info)
{
+ unsigned char saved_rfc;
+
/* If we are doing kadb, we call the debugger
* else we just drop into the boot monitor.
* Note that we must flush the user windows
@@ -187,6 +206,16 @@ static void batten_down_hatches(void)
*/
printk("\n");
flush_user_windows();
+
+ /*
+ * Set FIFO to single character mode.
+ */
+ saved_rfc = info->regs->r.rfc;
+ info->regs->rw.rfc &= ~(SAB82532_RFC_RFDF);
+ if (info->regs->r.star & SAB82532_STAR_CEC)
+ udelay(1);
+ info->regs->w.cmdr = SAB82532_CMDR_RRES;
+
#ifndef __sparc_v9__
if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) &&
(((unsigned long)linux_dbvec) <= DEBUG_LASTVADDR))
@@ -194,6 +223,14 @@ static void batten_down_hatches(void)
else
#endif
prom_cmdline();
+
+ /*
+ * Reset FIFO to character + status mode.
+ */
+ info->regs->w.rfc = saved_rfc;
+ if (info->regs->r.star & SAB82532_STAR_CEC)
+ udelay(1);
+ info->regs->w.cmdr = SAB82532_CMDR_RRES;
}
/*
@@ -242,16 +279,11 @@ static inline void receive_chars(struct sab82532 *info,
count = info->recv_fifo_size;
free_fifo++;
}
+
if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
count = info->regs->r.rbcl & (info->recv_fifo_size - 1);
free_fifo++;
}
- if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
-#if 1
- printk("sab82532: receive_chars: RFO");
-#endif
- free_fifo++;
- }
/* Issue a FIFO read command in case we where idle. */
if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
@@ -260,8 +292,15 @@ static inline void receive_chars(struct sab82532 *info,
info->regs->w.cmdr = SAB82532_CMDR_RFRD;
}
+ if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
+#if 1
+ printk("sab82532: receive_chars: RFO");
+#endif
+ free_fifo++;
+ }
+
/* Read the FIFO. */
- for (i = 0; i < (count << 1); i++)
+ for (i = 0; i < count; i++)
buf[i] = info->regs->r.rfifo[i];
/* Issue Receive Message Complete command. */
@@ -271,6 +310,11 @@ static inline void receive_chars(struct sab82532 *info,
info->regs->w.cmdr = SAB82532_CMDR_RMC;
}
+ if (info->is_console)
+ wake_up(&keypress_wait);
+ if (!tty)
+ return;
+
for (i = 0; i < count; ) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
#if 1
@@ -312,6 +356,12 @@ static inline void transmit_chars(struct sab82532 *info,
{
int i;
+ if (!info->tty) {
+ info->interrupt_mask1 |= SAB82532_IMR1_XPR;
+ info->regs->w.imr1 = info->interrupt_mask1;
+ return;
+ }
+
if ((info->xmit_cnt <= 0) || info->tty->stopped ||
info->tty->hw_stopped) {
if (stat->sreg.isr1 & SAB82532_ISR1_ALLS)
@@ -356,7 +406,7 @@ static inline void check_status(struct sab82532 *info,
if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
if (info->is_console) {
- batten_down_hatches();
+ batten_down_hatches(info);
return;
}
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
@@ -369,6 +419,9 @@ static inline void check_status(struct sab82532 *info,
info->icount.brk++;
}
+ if (!tty)
+ return;
+
if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
info->icount.buf_overrun++;
@@ -380,9 +433,6 @@ static inline void check_status(struct sab82532 *info,
info->icount.overrun++;
}
- if (info->is_console)
- return;
-
check_modem:
if (stat->sreg.isr0 & SAB82532_ISR0_CDSC) {
info->dcd = (info->regs->r.vstr & SAB82532_VSTR_CD) ? 0 : 1;
@@ -581,38 +631,18 @@ static void do_serial_hangup(void *private_)
tty_hangup(tty);
}
-
-static int startup(struct sab82532 *info)
+static void
+sab82532_init_line(struct sab82532 *info)
{
- unsigned long flags;
- unsigned long page;
unsigned char stat;
- page = get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- save_flags(flags); cli();
-
- if (info->flags & ASYNC_INITIALIZED) {
- free_page(page);
- goto errout;
- }
-
- if (!info->regs) {
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- free_page(page);
- goto errout;
- }
- if (info->xmit_buf)
- free_page(page);
- else
- info->xmit_buf = (unsigned char *)page;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("starting up serial port %d...", info->line);
-#endif
+ /*
+ * Wait for any commands or immediate characters
+ */
+ if (info->regs->r.star & SAB82532_STAR_CEC)
+ udelay(1);
+ while (info->regs->r.star & SAB82532_STAR_TEC)
+ udelay(1);
/*
* Clear the FIFO buffers.
@@ -662,7 +692,46 @@ static int startup(struct sab82532 *info)
break;
}
info->regs->rw.ccr0 |= SAB82532_CCR0_PU; /* power-up */
-
+}
+
+static int startup(struct sab82532 *info)
+{
+ unsigned long flags;
+ unsigned long page;
+ int retval = 0;
+
+ page = get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ save_flags(flags); cli();
+
+ if (info->flags & ASYNC_INITIALIZED) {
+ free_page(page);
+ goto errout;
+ }
+
+ if (!info->regs) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ free_page(page);
+ retval = -ENODEV;
+ goto errout;
+ }
+ if (info->xmit_buf)
+ free_page(page);
+ else
+ info->xmit_buf = (unsigned char *)page;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("starting up serial port %d...", info->line);
+#endif
+
+ /*
+ * Initialize the Hardware
+ */
+ sab82532_init_line(info);
+
/*
* Finally, enable interrupts
*/
@@ -689,7 +758,7 @@ static int startup(struct sab82532 *info)
errout:
restore_flags(flags);
- return -ENODEV;
+ return retval;
}
/*
@@ -720,6 +789,22 @@ static void shutdown(struct sab82532 *info)
info->xmit_buf = 0;
}
+ if (info->is_console) {
+ info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
+ SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
+ info->regs->w.imr0 = info->interrupt_mask0;
+ info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
+ SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
+ SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
+ SAB82532_IMR1_XPR;
+ info->regs->w.imr1 = info->interrupt_mask1;
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ info->flags &= ~ASYNC_INITIALIZED;
+ restore_flags(flags);
+ return;
+ }
+
/* Disable Interrupts */
info->interrupt_mask0 = 0xff;
info->regs->w.imr0 = info->interrupt_mask0;
@@ -758,7 +843,7 @@ static void change_speed(struct sab82532 *info)
unsigned int ebrg;
tcflag_t cflag;
unsigned char dafo;
- int i;
+ int i, bits;
if (!info->tty || !info->tty->termios)
return;
@@ -766,19 +851,23 @@ static void change_speed(struct sab82532 *info)
/* Byte size and parity */
switch (cflag & CSIZE) {
- case CS5: dafo = SAB82532_DAFO_CHL5; break;
- case CS6: dafo = SAB82532_DAFO_CHL6; break;
- case CS7: dafo = SAB82532_DAFO_CHL7; break;
- case CS8: dafo = SAB82532_DAFO_CHL8; break;
+ case CS5: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
+ case CS6: dafo = SAB82532_DAFO_CHL6; bits = 8; break;
+ case CS7: dafo = SAB82532_DAFO_CHL7; bits = 9; break;
+ case CS8: dafo = SAB82532_DAFO_CHL8; bits = 10; break;
/* Never happens, but GCC is too dumb to figure it out */
- default: dafo = SAB82532_DAFO_CHL5; break;
+ default: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
}
- if (cflag & CSTOPB)
+ if (cflag & CSTOPB) {
dafo |= SAB82532_DAFO_STOP;
+ bits++;
+ }
- if (cflag & PARENB)
+ if (cflag & PARENB) {
dafo |= SAB82532_DAFO_PARE;
+ bits++;
+ }
if (cflag & PARODD) {
#ifdef CMSPAR
@@ -808,6 +897,12 @@ static void change_speed(struct sab82532 *info)
ebrg = ebrg_table[i].n;
ebrg |= (ebrg_table[i].m << 6);
+ if (ebrg_table[i].baud)
+ info->timeout = (info->xmit_fifo_size * HZ * bits) / ebrg_table[i].baud;
+ else
+ info->timeout = 0;
+ info->timeout += HZ / 50; /* Add .02 seconds of slop */
+
/* CTS flow control flags */
if (cflag & CRTSCTS)
info->flags |= ASYNC_CTS_FLOW;
@@ -842,6 +937,10 @@ static void change_speed(struct sab82532 *info)
SAB82532_ISR0_TIME;
save_flags(flags); cli();
+ if (info->regs->r.star & SAB82532_STAR_CEC)
+ udelay(1);
+ while (info->regs->r.star & SAB82532_STAR_TEC)
+ udelay(1);
info->regs->w.dafo = dafo;
info->regs->w.bgr = ebrg & 0xff;
info->regs->rw.ccr2 &= ~(0xc0);
@@ -980,7 +1079,7 @@ static int sab82532_chars_in_buffer(struct tty_struct *tty)
static void sab82532_flush_buffer(struct tty_struct *tty)
{
struct sab82532 *info = (struct sab82532 *)tty->driver_data;
-
+
if (serial_paranoia_check(info, tty->device, "sab82532_flush_buffer"))
return;
cli();
@@ -1003,7 +1102,7 @@ static void sab82532_send_xchar(struct tty_struct *tty, char ch)
if (serial_paranoia_check(info, tty->device, "sab82532_send_xchar"))
return;
- if (info->regs->r.star & SAB82532_STAR_TEC)
+ while (info->regs->r.star & SAB82532_STAR_TEC)
udelay(1);
info->regs->w.tic = ch;
}
@@ -1114,7 +1213,7 @@ static int get_lsr_info(struct sab82532 * info, unsigned int *value)
{
unsigned int result;
- result = info->all_sent ? TIOCSER_TEMT : 0;
+ result = (!info->xmit_buf && info->all_sent) ? TIOCSER_TEMT : 0;
return put_user(result, value);
}
@@ -1496,7 +1595,9 @@ static void sab82532_close(struct tty_struct *tty, struct file * filp)
*/
info->interrupt_mask0 |= SAB82532_IMR0_TCD;
info->regs->w.imr0 = info->interrupt_mask0;
+#if 0
info->regs->rw.mode &= ~(SAB82532_MODE_RAC);
+#endif
if (info->flags & ASYNC_INITIALIZED) {
/*
* Before we drop DTR, make sure the UART transmitter
@@ -1554,16 +1655,23 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout)
char_time = 1;
if (timeout)
char_time = MIN(char_time, timeout);
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+#ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT
printk("In sab82532_wait_until_sent(%d) check=%lu...", timeout, char_time);
printk("jiff=%lu...", jiffies);
#endif
-
- /* XXX: Implement this... */
-
+ while (info->xmit_cnt || !info->all_sent) {
+ current->state = TASK_INTERRUPTIBLE;
+ current->counter = 0;
+ current->timeout = jiffies + char_time;
+ schedule();
+ if (signal_pending(current))
+ break;
+ if (timeout && (orig_jiffies + timeout) < jiffies)
+ break;
+ }
current->state = TASK_RUNNING;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT
+ printk("xmit_cnt = %d, alls = %d (jiff=%lu)...done\n", info->xmit_cnt, info->all_sent, jiffies);
#endif
}
@@ -1573,10 +1681,13 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout)
static void sab82532_hangup(struct tty_struct *tty)
{
struct sab82532 * info = (struct sab82532 *)tty->driver_data;
-
+
if (serial_paranoia_check(info, tty->device, "sab82532_hangup"))
return;
+ if (info->is_console)
+ return;
+
sab82532_flush_buffer(tty);
shutdown(info);
info->event = 0;
@@ -1754,7 +1865,6 @@ static int sab82532_open(struct tty_struct *tty, struct file * filp)
return -ENODEV;
}
- info->count++;
if (serial_paranoia_check(info, tty->device, "sab82532_open"))
return -ENODEV;
@@ -1762,6 +1872,8 @@ static int sab82532_open(struct tty_struct *tty, struct file * filp)
printk("sab82532_open %s%d, count = %d\n", tty->driver.name, info->line,
info->count);
#endif
+
+ info->count++;
tty->driver_data = info;
info->tty = tty;
@@ -1774,7 +1886,22 @@ static int sab82532_open(struct tty_struct *tty, struct file * filp)
else
tmp_buf = (unsigned char *) page;
}
-
+
+ /*
+ * If the port is in the middle of closing, bail out now.
+ */
+ if (tty_hung_up_p(filp) ||
+ (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+ return ((info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+#else
+ return -EAGAIN;
+#endif
+ }
+
/*
* Start up serial port
*/
@@ -1801,6 +1928,14 @@ static int sab82532_open(struct tty_struct *tty, struct file * filp)
change_speed(info);
}
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (sab82532_console.cflag && sab82532_console.index == line) {
+ tty->termios->c_cflag = sab82532_console.cflag;
+ sab82532_console.cflag = 0;
+ change_speed(info);
+ }
+#endif
+
info->session = current->session;
info->pgrp = current->pgrp;
@@ -1856,7 +1991,7 @@ int sab82532_read_proc(char *page, char **start, off_t off, int count,
int i, len = 0;
off_t begin = 0;
- len += sprintf(page, "serinfo:1.0 driver:%s\n", "$Revision: 1.4 $");
+ len += sprintf(page, "serinfo:1.0 driver:%s\n", "$Revision: 1.13 $");
for (i = 0; i < NR_PORTS && len < 4000; i++) {
len += line_info(page + len, sab82532_table[i]);
if (len+begin > off+count)
@@ -1881,7 +2016,7 @@ done:
* sab82532_init() is called at boot-time to initialize the serial driver.
* ---------------------------------------------------------------------
*/
-__initfunc(static int get_sab82532(void))
+__initfunc(static int get_sab82532(unsigned long *memory_start))
{
struct linux_ebus *ebus;
struct linux_ebus_device *edev;
@@ -1895,23 +2030,29 @@ __initfunc(static int get_sab82532(void))
if (!edev)
return -ENODEV;
- printk("%s: SAB82532 at 0x%lx IRQ %x\n", __FUNCTION__,
- edev->base_address[0], edev->irqs[0]);
-
regs = edev->base_address[0];
offset = sizeof(union sab82532_async_regs);
for (i = 0; i < 2; i++) {
- sab = (struct sab82532 *)kmalloc(sizeof(struct sab82532),
- GFP_KERNEL);
- if (!sab) {
- printk("sab82532: can't alloc sab struct\n");
- break;
+ if (memory_start) {
+ *memory_start = (*memory_start + 7) & ~(7);
+ sab = (struct sab82532 *)*memory_start;
+ *memory_start += sizeof(struct sab82532);
+ } else {
+ sab = (struct sab82532 *)kmalloc(sizeof(struct sab82532),
+ GFP_KERNEL);
+ if (!sab) {
+ printk("sab82532: can't alloc sab struct\n");
+ break;
+ }
}
memset(sab, 0, sizeof(struct sab82532));
sab->regs = (union sab82532_async_regs *)(regs + offset);
sab->irq = edev->irqs[0];
+ sab->line = 1 - i;
+ sab->xmit_fifo_size = 32;
+ sab->recv_fifo_size = 32;
if (check_region((unsigned long)sab->regs,
sizeof(union sab82532_async_regs))) {
@@ -1932,20 +2073,8 @@ __initfunc(static int get_sab82532(void))
return 0;
}
-/* Hooks for running a serial console. con_init() calls this if the
- * console is run over one of the ttya/ttyb serial ports.
- * 'chip' should be zero, as for now we only have one chip on board.
- * 'line' is decoded as 0=ttya, 1=ttyb.
- */
-void
-sab82532_cons_hook(int chip, int out, int line)
-{
- prom_printf("sab82532: serial console is not implemented, yet\n");
- prom_halt();
-}
-
-void
-sab82532_kgdb_hook(int line)
+__initfunc(static void
+sab82532_kgdb_hook(int line))
{
prom_printf("sab82532: kgdb support is not implemented, yet\n");
prom_halt();
@@ -1953,7 +2082,7 @@ sab82532_kgdb_hook(int line)
__initfunc(static inline void show_serial_version(void))
{
- char *revision = "$Revision: 1.4 $";
+ char *revision = "$Revision: 1.13 $";
char *version, *p;
version = strchr(revision, ' ');
@@ -1971,7 +2100,7 @@ __initfunc(int sab82532_init(void))
int i;
if (!sab82532_chain)
- get_sab82532();
+ get_sab82532(0);
if (!sab82532_chain)
return -ENODEV;
@@ -2035,9 +2164,6 @@ __initfunc(int sab82532_init(void))
for (info = sab82532_chain, i = 0; info; info = info->next, i++) {
info->magic = SERIAL_MAGIC;
- info->line = i;
- info->tty = 0;
- info->count = 0;
info->type = info->regs->r.vstr & 0x0f;
info->regs->w.pcr = ~((1 << 1) | (1 << 2) | (1 << 4));
@@ -2053,14 +2179,11 @@ __initfunc(int sab82532_init(void))
info->regs->rw.mode |= SAB82532_MODE_FRTS;
info->regs->rw.mode |= SAB82532_MODE_RTS;
- info->xmit_fifo_size = 32;
- info->recv_fifo_size = 32;
info->custom_divisor = 16;
info->close_delay = 5*HZ/10;
info->closing_wait = 30*HZ;
info->x_char = 0;
info->event = 0;
- info->count = 0;
info->blocked_open = 0;
info->tqueue.routine = do_softint;
info->tqueue.data = info;
@@ -2086,9 +2209,9 @@ __initfunc(int sab82532_init(void))
}
}
- printk(KERN_INFO "ttyS%02d at 0x%lx (irq = %x) is a %s\n",
+ printk(KERN_INFO "ttyS%02d at 0x%lx (irq = %x) is a SAB82532 %s\n",
info->line, (unsigned long)info->regs, info->irq,
- "SAB82532");
+ sab82532_version[info->type]);
}
return 0;
}
@@ -2125,8 +2248,10 @@ __initfunc(int sab82532_probe(unsigned long *memory_start))
return -ENODEV;
found:
+#ifdef CONFIG_SERIAL_CONSOLE
+ sunserial_setinitfunc(memory_start, sab82532_console_init);
+#endif
sunserial_setinitfunc(memory_start, sab82532_init);
- rs_ops.rs_cons_hook = sab82532_cons_hook;
rs_ops.rs_kgdb_hook = sab82532_kgdb_hook;
return 0;
}
@@ -2134,7 +2259,7 @@ found:
#ifdef MODULE
int init_module(void)
{
- if (get_sab82532())
+ if (get_sab82532(0))
return -ENODEV;
return sab82532_init();
@@ -2171,3 +2296,200 @@ void cleanup_module(void)
}
}
#endif /* MODULE */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+static void
+sab82532_console_putchar(struct sab82532 *info, char c)
+{
+ while (info->regs->r.star & SAB82532_STAR_TEC)
+ udelay(1);
+ info->regs->w.tic = c;
+}
+
+static void
+sab82532_console_write(struct console *con, const char *s, unsigned n)
+{
+ struct sab82532 *info;
+ int i;
+
+ info = sab82532_chain + con->index;
+
+ for (i = 0; i < n; i++) {
+ if (*s == '\n')
+ sab82532_console_putchar(info, '\r');
+ sab82532_console_putchar(info, *s++);
+ }
+ while (info->regs->r.star & SAB82532_STAR_TEC)
+ udelay(1);
+}
+
+static int
+sab82532_console_wait_key(struct console *con)
+{
+ sleep_on(&keypress_wait);
+ return 0;
+}
+
+static kdev_t
+sab82532_console_device(struct console *con)
+{
+ return MKDEV(TTY_MAJOR, 64 + con->index);
+}
+
+static int
+sab82532_console_setup(struct console *con, char *options)
+{
+ struct sab82532 *info;
+ unsigned int ebrg;
+ tcflag_t cflag;
+ unsigned char dafo;
+ int i, bits;
+ unsigned long flags;
+
+ info = sab82532_chain + con->index;
+ info->is_console = 1;
+
+ /*
+ * Initialize the hardware
+ */
+ sab82532_init_line(info);
+
+ /*
+ * Finally, enable interrupts
+ */
+ info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
+ SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
+ info->regs->w.imr0 = info->interrupt_mask0;
+ info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
+ SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
+ SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
+ SAB82532_IMR1_XPR;
+ info->regs->w.imr1 = info->interrupt_mask1;
+
+ printk("Console: ttyS%d (SAB82532)\n", info->line);
+
+ sunserial_console_termios(con);
+ cflag = con->cflag;
+
+ /* Byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
+ case CS6: dafo = SAB82532_DAFO_CHL6; bits = 8; break;
+ case CS7: dafo = SAB82532_DAFO_CHL7; bits = 9; break;
+ case CS8: dafo = SAB82532_DAFO_CHL8; bits = 10; break;
+ /* Never happens, but GCC is too dumb to figure it out */
+ default: dafo = SAB82532_DAFO_CHL5; bits = 7; break;
+ }
+
+ if (cflag & CSTOPB) {
+ dafo |= SAB82532_DAFO_STOP;
+ bits++;
+ }
+
+ if (cflag & PARENB) {
+ dafo |= SAB82532_DAFO_PARE;
+ bits++;
+ }
+
+ if (cflag & PARODD) {
+#ifdef CMSPAR
+ if (cflag & CMSPAR)
+ dafo |= SAB82532_DAFO_PAR_MARK;
+ else
+#endif
+ dafo |= SAB82532_DAFO_PAR_ODD;
+ } else {
+#ifdef CMSPAR
+ if (cflag & CMSPAR)
+ dafo |= SAB82532_DAFO_PAR_SPACE;
+ else
+#endif
+ dafo |= SAB82532_DAFO_PAR_EVEN;
+ }
+
+ /* Determine EBRG values based on baud rate */
+ i = cflag & CBAUD;
+ if (i & CBAUDEX) {
+ i &= ~(CBAUDEX);
+ if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES))
+ info->tty->termios->c_cflag &= ~CBAUDEX;
+ else
+ i += 15;
+ }
+ ebrg = ebrg_table[i].n;
+ ebrg |= (ebrg_table[i].m << 6);
+
+ if (ebrg_table[i].baud)
+ info->timeout = (info->xmit_fifo_size * HZ * bits) / ebrg_table[i].baud;
+ else
+ info->timeout = 0;
+ info->timeout += HZ / 50; /* Add .02 seconds of slop */
+
+ /* CTS flow control flags */
+ if (cflag & CRTSCTS)
+ info->flags |= ASYNC_CTS_FLOW;
+ else
+ info->flags &= ~(ASYNC_CTS_FLOW);
+
+ if (cflag & CLOCAL)
+ info->flags &= ~(ASYNC_CHECK_CD);
+ else
+ info->flags |= ASYNC_CHECK_CD;
+
+ save_flags(flags); cli();
+ if (info->regs->r.star & SAB82532_STAR_CEC)
+ udelay(1);
+ while (info->regs->r.star & SAB82532_STAR_TEC)
+ udelay(1);
+ info->regs->w.dafo = dafo;
+ info->regs->w.bgr = ebrg & 0xff;
+ info->regs->rw.ccr2 &= ~(0xc0);
+ info->regs->rw.ccr2 |= (ebrg >> 2) & 0xc0;
+ if (info->flags & ASYNC_CTS_FLOW) {
+ info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
+ info->regs->rw.mode |= SAB82532_MODE_FRTS;
+ info->regs->rw.mode &= ~(SAB82532_MODE_FCTS);
+ } else {
+ info->regs->rw.mode |= SAB82532_MODE_RTS;
+ info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
+ info->regs->rw.mode |= SAB82532_MODE_FCTS;
+ }
+ info->regs->rw.mode |= SAB82532_MODE_RAC;
+ restore_flags(flags);
+
+ return 0;
+}
+
+static struct console sab82532_console = {
+ "ttyS",
+ sab82532_console_write,
+ NULL,
+ sab82532_console_device,
+ sab82532_console_wait_key,
+ NULL,
+ sab82532_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+__initfunc(int sab82532_console_init(void))
+{
+ extern int con_is_present(void);
+
+ if (con_is_present())
+ return 0;
+
+ if (!sab82532_chain) {
+ prom_printf("sab82532_console_setup: can't get SAB82532 chain");
+ prom_halt();
+ }
+
+ sab82532_console.index = serial_console - 1;
+ register_console(&sab82532_console);
+ return 0;
+}
+
+#endif /* CONFIG_SERIAL_CONSOLE */
diff --git a/drivers/sbus/char/sbuscons.c b/drivers/sbus/char/sbuscons.c
index a0d47d79c..eda06fa76 100644
--- a/drivers/sbus/char/sbuscons.c
+++ b/drivers/sbus/char/sbuscons.c
@@ -1,4 +1,4 @@
-/* $Id: sbuscons.c,v 1.7 1997/08/28 09:30:07 davem Exp $
+/* $Id: sbuscons.c,v 1.10 1998/01/07 06:37:22 baccala Exp $
* sbuscons.c: Routines specific to SBUS frame buffer consoles.
*
* Copyright (C) 1995 Peter Zaitcev (zaitcev@lab.ipmce.su)
@@ -1168,7 +1168,7 @@ static int sbus_blitc(uint charattr, unsigned long addr)
const int cpl = chars_per_line;
/* The register assignment is important here, do not modify without touching the assembly code as well */
register unsigned int x1 __asm__("g4"), x2 __asm__("g5"), x3 __asm__("g2"), x4 __asm__("g3"), flags __asm__("g7");
- register unsigned int *dst __asm__("g1");
+ register unsigned int *dst;
#else
const int ipl = ints_per_line;
unsigned int data2, data3, data4;
@@ -1182,9 +1182,9 @@ static int sbus_blitc(uint charattr, unsigned long addr)
if (j == ' ') /* space is quite common, so we optimize a bit */ {
#ifdef ASM_BLITC
#define BLITC_SPACE \
- "\n\t std %%g4, [%%g1]" \
- "\n\t std %%g4, [%%g1 + %0]" \
- "\n\t add %%g1, %1, %%g1"
+ "\n\t std %3, [%0]" \
+ "\n\t std %3, [%0 + %1]" \
+ "\n\t add %0, %2, %0"
#define BLITC_SPC \
"\n\t std %0, [%1]" \
"\n\t std %0, [%1 + %2]"
@@ -1195,7 +1195,7 @@ static int sbus_blitc(uint charattr, unsigned long addr)
x3 = cpl << 1;
__asm__ __volatile__ (
- "\n\t mov %2, %3"
+ "\n\t mov %3, %4"
BLITC_SPACE
BLITC_SPACE
BLITC_SPACE
@@ -1203,12 +1203,19 @@ static int sbus_blitc(uint charattr, unsigned long addr)
BLITC_SPACE
BLITC_SPACE
BLITC_SPACE
- : : "r" (cpl), "r" (x3), "r" (x1), "r" (x2));
+ : "=r" (dst)
+ : "r" (cpl), "r" (x3), "r" (x1), "r" (x2));
__save_and_cli (flags);
if (idx != cursor_pos)
- __asm__ __volatile__ (BLITC_SPC : : "r" (x1), "r" (dst), "r" (cpl));
+ __asm__ __volatile__ (
+ BLITC_SPC
+ : /* no outputs */
+ : "r" (x1), "r" (dst), "r" (cpl));
else
- __asm__ __volatile__ (BLITC_SPC : : "r" (x1), "r" (under_cursor), "i" (8));
+ __asm__ __volatile__ (BLITC_SPC
+ : /* no outputs */
+ : "r" (x1), "r" (under_cursor),
+ "i" (8));
__restore_flags (flags);
#else
bgmask = attrib >> 4;
diff --git a/drivers/sbus/char/su.c b/drivers/sbus/char/su.c
index 6cc5801cd..beba2e7e6 100644
--- a/drivers/sbus/char/su.c
+++ b/drivers/sbus/char/su.c
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.3 1997/09/03 11:54:56 ecd Exp $
+/* $Id: su.c,v 1.4 1997/09/07 15:40:19 ecd Exp $
* su.c: Small serial driver for keyboard/mouse interface on Ultra/AX
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -150,16 +150,6 @@ su_interrupt(int irq, void *dev_id, struct pt_regs * regs)
struct su_struct *info = (struct su_struct *)dev_id;
unsigned char status;
- /*
- * We might share interrupts with ps2kbd/ms driver,
- * in case we want to use the 16550A as general serial
- * driver in the presence of ps2 devices, so do a
- * sanity check here, needs to be done in ps2kbd/ms
- * driver, too.
- */
- if (!info || info->magic != SERIAL_MAGIC)
- return;
-
#ifdef SERIAL_DEBUG_INTR
printk("su_interrupt(%d)...", irq);
#endif
@@ -644,12 +634,12 @@ __initfunc(int su_probe (unsigned long *memory_start))
* Does it match?
*/
if (sunode == kbnode) {
- info->kbd_node = kbnode;
+ info->kbd_node = sunode;
++info;
++devices;
}
if (sunode == msnode) {
- info->ms_node = msnode;
+ info->ms_node = sunode;
++info;
++devices;
}
@@ -674,5 +664,15 @@ __initfunc(int su_probe (unsigned long *memory_start))
found:
sunserial_setinitfunc(memory_start, su_init);
rs_ops.rs_change_mouse_baud = su_change_mouse_baud;
+ sunkbd_setinitfunc(memory_start, sun_kbd_init);
+ kbd_ops.compute_shiftstate = sun_compute_shiftstate;
+ kbd_ops.setledstate = sun_setledstate;
+ kbd_ops.getledstate = sun_getledstate;
+ kbd_ops.setkeycode = sun_setkeycode;
+ kbd_ops.getkeycode = sun_getkeycode;
+ sunkbd_install_keymaps(memory_start, sun_key_maps, sun_keymap_count,
+ sun_func_buf, sun_func_table,
+ sun_funcbufsize, sun_funcbufleft,
+ sun_accent_table, sun_accent_table_size);
return 0;
}
diff --git a/drivers/sbus/char/suncons.c b/drivers/sbus/char/suncons.c
index 7e88b4688..586ac28c0 100644
--- a/drivers/sbus/char/suncons.c
+++ b/drivers/sbus/char/suncons.c
@@ -1,4 +1,4 @@
-/* $Id: suncons.c,v 1.73 1997/08/25 07:50:33 jj Exp $
+/* $Id: suncons.c,v 1.77 1997/12/19 07:32:59 ecd Exp $
* suncons.c: Sparc platform console generic layer.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -100,13 +100,11 @@ static void nop_console_restore_palette(void)
static unsigned long nop_con_type_init(unsigned long mem_start,
const char **display_desc)
{
- prom_printf("YIEEE: nop_con_type_init called!\n");
return mem_start;
}
static void nop_con_type_init_finish(void)
{
- prom_printf("YIEEE: nop_con_type_init_finish called!\n");
}
static void nop_vesa_blank(void)
@@ -323,12 +321,17 @@ __initfunc(static unsigned long finish_console_init(unsigned long memory_start))
extern void pci_console_inithook(void);
#endif
+__initfunc(int con_is_present(void))
+{
+ return serial_console ? 0 : 1;
+}
+
__initfunc(unsigned long sun_console_init(unsigned long memory_start))
{
int i;
/* Nothing to do in this case. */
- if(serial_console)
+ if (!con_is_present())
return memory_start;
fbinfo = (fbinfo_t *)memory_start;
@@ -358,7 +361,7 @@ extern int pci_console_probe(void);
__initfunc(unsigned long pci_console_init(unsigned long memory_start))
{
/* Nothing to do in this case. */
- if(serial_console)
+ if (!con_is_present())
return memory_start;
if(pci_console_probe()) {
@@ -369,8 +372,6 @@ __initfunc(unsigned long pci_console_init(unsigned long memory_start))
memory_start = finish_console_init(memory_start);
con_type_init_finish();
- register_console(&vt_console_driver);
-
return memory_start;
}
#endif
diff --git a/drivers/sbus/char/sunfb.c b/drivers/sbus/char/sunfb.c
index 2ebd9cc5a..cae5bacbd 100644
--- a/drivers/sbus/char/sunfb.c
+++ b/drivers/sbus/char/sunfb.c
@@ -1,4 +1,4 @@
-/* $Id: sunfb.c,v 1.28 1997/08/22 15:55:23 jj Exp $
+/* $Id: sunfb.c,v 1.29 1997/09/20 20:47:26 davem Exp $
* sunfb.c: Sun generic frame buffer support.
*
* Copyright (C) 1995, 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -45,7 +45,7 @@ extern void set_other_palette (int);
extern void set_cursor (int);
#define FB_SETUP(err) \
- int minor = FB_DEV (inode->i_rdev); \
+ int minor = FB_DEV (file->f_dentry->d_inode->i_rdev); \
\
if (minor >= fbinfos || \
fbinfo [minor].type.fb_type == FBTYPE_NOTYPE) \
@@ -229,7 +229,7 @@ fb_ioctl (struct inode *inode, struct file *file, uint cmd, unsigned long arg)
}
static int
-fb_close (struct inode * inode, struct file *filp)
+fb_close (struct inode * inode, struct file *file)
{
fbinfo_t *fb;
struct fbcursor cursor;
@@ -255,7 +255,7 @@ fb_close (struct inode * inode, struct file *filp)
if (fb->open)
fb->open = 0;
- fb_ioctl (inode, filp, FBIOSCURPOS, (unsigned long) &cursor);
+ fb_ioctl (inode, file, FBIOSCURPOS, (unsigned long) &cursor);
set_other_palette (minor);
if (!minor) {
render_screen ();
@@ -266,7 +266,7 @@ fb_close (struct inode * inode, struct file *filp)
}
static int
-fb_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
+fb_mmap (struct file *file, struct vm_area_struct *vma)
{
fbinfo_t *fb;
FB_SETUP(ENXIO)
@@ -276,7 +276,7 @@ fb_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
if (fb->mmap){
int v;
- v = (*fb->mmap)(inode, file, vma, fb->base, fb);
+ v = (*fb->mmap)(file->f_dentry->d_inode, file, vma, fb->base, fb);
if (v)
return v;
vma->vm_flags |= VM_IO;
diff --git a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c
index 1340e3f7c..d55fb5ba5 100644
--- a/drivers/sbus/char/sunkbd.c
+++ b/drivers/sbus/char/sunkbd.c
@@ -6,6 +6,7 @@
* compatibility - Miguel (miguel@nuclecu.unam.mx)
*
* Added PCI 8042 controller support -DaveM
+ * Added Magic SysRq support -MJ
*/
#include <linux/config.h>
@@ -22,6 +23,7 @@
#include <linux/random.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/sysrq.h>
#include <asm/kbio.h>
#include <asm/vuid_event.h>
@@ -77,10 +79,10 @@ extern void scrollback(int);
extern void scrollfront(int);
struct l1a_kbd_state l1a_state = { 0, 0 };
-unsigned char kbd_read_mask = 0x01; /* modified by psaux.c */
-unsigned char aux_device_present = 0x00; /* To make kernel/ksyms.c happy */
+#ifndef CONFIG_PCI
struct wait_queue * keypress_wait = NULL;
+#endif
void keyboard_wait_for_keypress(void)
{
@@ -96,7 +98,6 @@ void keyboard_wait_for_keypress(void)
/* shift state counters.. */
static unsigned char k_down[NR_SHIFT] = {0, };
/* keyboard key bitmap */
-#define BITS_PER_LONG (8*sizeof(unsigned long))
static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
void push_kbd (int scan);
@@ -108,7 +109,9 @@ static int dead_key_next = 0;
* the variable must be global, or a new procedure must be created to
* return the value. I chose the former way.
*/
+#ifndef CONFIG_PCI
/*static*/ int shift_state = 0;
+#endif
static int npadch = -1; /* -1 or number assembled on pad */
static unsigned char diacr = 0;
static char rep = 0; /* flag telling character repeat */
@@ -120,7 +123,7 @@ static int compose_led_on = 0;
static int kbd_delay_ticks = HZ / 5;
static int kbd_rate_ticks = HZ / 20;
-extern void compute_shiftstate(void);
+void sun_compute_shiftstate(void);
typedef void (*k_hand)(unsigned char value, char up_flag);
typedef void (k_handfn)(unsigned char value, char up_flag);
@@ -151,13 +154,16 @@ static void_fnp spec_fn_table[] = {
};
/* maximum values each key_handler can handle */
+#ifndef CONFIG_PCI
const int max_vals[] = {
255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1,
NR_DEAD - 1, 255, 3, NR_SHIFT - 1,
- 255, NR_ASCII - 1, NR_LOCK - 1, 255
+ 255, NR_ASCII - 1, NR_LOCK - 1, 255,
+ NR_LOCK - 1
};
const int NR_TYPES = SIZE(max_vals);
+#endif
static void put_queue(int);
static unsigned char handle_diacr(unsigned char);
@@ -165,6 +171,18 @@ static unsigned char handle_diacr(unsigned char);
/* pt_regs - set by keyboard_interrupt(), used by show_ptregs() */
static struct pt_regs * pt_regs;
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char sun_sysrq_xlate[128] =
+ "\0\0\0\0\0\201\202\212\203\213\204\214\205\0\206\0" /* 0x00 - 0x0f */
+ "\207\210\211\0\0\0\0\0\0\0\0\0\0\03312" /* 0x10 - 0x1f */
+ "34567890-=`\177\0=/*" /* 0x20 - 0x2f */
+ "\0\0.\0\0\011qwertyuiop" /* 0x30 - 0x3f */
+ "[]\177\000789-\0\0\0\0\0asd" /* 0x40 - 0x4f */
+ "fghjkl;'\\\015\0154560\0" /* 0x50 - 0x5f */
+ "\0\0\0\0zxcvbnm,./\0\012" /* 0x60 - 0x6f */
+ "123\0\0\0\0\0\0 \0\0\0\0\0\0"; /* 0x70 - 0x7f */
+#endif
+
volatile unsigned char sunkbd_layout;
volatile unsigned char sunkbd_type;
#define SUNKBD_TYPE2 0x02
@@ -222,7 +240,7 @@ static unsigned char sunkbd_clickp;
#define KEY_ALT 0x86
#define KEY_L1 0x87
-/* Do to kbd_init() being called before rs_init(), and kbd_init() doing:
+/* Do to sun_kbd_init() being called before rs_init(), and sun_kbd_init() doing:
*
* init_bh(KEYBOARD_BH, kbd_bh);
* mark_bh(KEYBOARD_BH);
@@ -394,7 +412,7 @@ static unsigned char norepeat_keys[128] = {
};
-int setkeycode(unsigned int scancode, unsigned int keycode)
+int sun_setkeycode(unsigned int scancode, unsigned int keycode)
{
if (scancode < SC_LIM || scancode > 255 || keycode > 127)
return -EINVAL;
@@ -405,7 +423,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
return 0;
}
-int getkeycode(unsigned int scancode)
+int sun_getkeycode(unsigned int scancode)
{
return
(scancode < SC_LIM || scancode > 255) ? -EINVAL :
@@ -468,7 +486,7 @@ void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
} else if(ch == SKBD_ALLUP) {
del_timer (&auto_repeat_timer);
memset(key_down, 0, sizeof(key_down));
- compute_shiftstate();
+ sun_compute_shiftstate();
goto out;
}
#ifdef SKBD_DEBUG
@@ -520,6 +538,14 @@ void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
rep = test_and_set_bit(keycode, key_down);
}
+#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq hack */
+ if (l1a_state.l1_down) {
+ if (!up_flag)
+ handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty);
+ goto out;
+ }
+#endif
+
if(raw_mode)
goto out;
@@ -548,7 +574,7 @@ void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
u_char type;
/* the XOR below used to be an OR */
- int shift_final = shift_state ^ kbd->lockstate;
+ int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
ushort *key_map = key_maps[shift_final];
if (key_map != NULL) {
@@ -572,7 +598,7 @@ void sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
} else {
/* maybe beep? */
/* we have at least to update shift_state */
- compute_shiftstate();
+ sun_compute_shiftstate();
}
}
out:
@@ -774,7 +800,7 @@ static void do_ignore(unsigned char value, char up_flag)
static void do_null()
{
- compute_shiftstate();
+ sun_compute_shiftstate();
}
static void do_spec(unsigned char value, char up_flag)
@@ -981,7 +1007,7 @@ static void do_shift(unsigned char value, char up_flag)
/* called after returning from RAW mode or when changing consoles -
recompute k_down[] and shift_state from key_down[] */
/* maybe called when keymap is undefined, so that shiftkey release is seen */
-void compute_shiftstate(void)
+void sun_compute_shiftstate(void)
{
int i, j, k, sym, val;
@@ -1055,11 +1081,11 @@ static unsigned char ledstate = 0xff; /* undefined */
static unsigned char sunkbd_ledstate = 0xff; /* undefined */
static unsigned char ledioctl;
-unsigned char getledstate(void) {
+unsigned char sun_getledstate(void) {
return ledstate;
}
-void setledstate(struct kbd_struct *kbd, unsigned int led) {
+void sun_setledstate(struct kbd_struct *kbd, unsigned int led) {
if (!(led & ~7)) {
ledioctl = led;
kbd->ledmode = LED_SHOW_IOCTL;
@@ -1181,7 +1207,7 @@ static void sunkbd_kd_mksound(unsigned int hz, unsigned int ticks)
extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
-__initfunc(int kbd_init(void))
+__initfunc(int sun_kbd_init(void))
{
int i, opt_node;
struct kbd_struct kbd0;
@@ -1190,6 +1216,7 @@ __initfunc(int kbd_init(void))
kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
kbd0.ledmode = LED_SHOW_FLAGS;
kbd0.lockstate = KBD_DEFLOCK;
+ kbd0.slockstate = 0;
kbd0.modeflags = KBD_DEFMODE;
kbd0.kbdmode = VC_XLATE;
@@ -1245,8 +1272,8 @@ push_kbd (int scan)
wake_up_interruptible (&kbd_wait);
}
-static long
-kbd_read (struct inode *inode, struct file *f, char *buffer, unsigned long count)
+static ssize_t
+kbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos)
{
struct wait_queue wait = { current, NULL };
char *end, *p;
@@ -1278,12 +1305,11 @@ kbd_read (struct inode *inode, struct file *f, char *buffer, unsigned long count
}
/* Needed by X */
-static int
-kbd_fasync (struct inode *inode, struct file *filp, int on)
+static int kbd_fasync (struct file *filp, int on)
{
int retval;
- retval = fasync_helper (inode, filp, on, &kb_fasync);
+ retval = fasync_helper (filp, on, &kb_fasync);
if (retval < 0)
return retval;
return 0;
@@ -1291,7 +1317,7 @@ kbd_fasync (struct inode *inode, struct file *filp, int on)
static unsigned int kbd_poll (struct file *f, poll_table *wait)
{
- poll_wait(&kbd_wait, wait);
+ poll_wait(f, &kbd_wait, wait);
if (kbd_head != kbd_tail)
return POLLIN | POLLRDNORM;
return 0;
@@ -1353,7 +1379,7 @@ kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
if (c & LED_NLOCK) leds |= (1 << VC_NUMLOCK);
if (c & LED_CLOCK) leds |= (1 << VC_CAPSLOCK);
compose_led_on = !!(c & LED_CMPOSE);
- setledstate(kbd_table + fg_console, leds);
+ sun_setledstate(kbd_table + fg_console, leds);
break;
case KIOCGLED:
put_user_ret(vcleds_to_sunkbd(getleds()), (unsigned char *) arg, -EFAULT);
@@ -1433,7 +1459,7 @@ kbd_close (struct inode *i, struct file *f)
kbd_redirected = 0;
kbd_opened = 0;
- kbd_fasync (i, f, 0);
+ kbd_fasync (f, 0);
return 0;
}
diff --git a/drivers/sbus/char/sunkbd.h b/drivers/sbus/char/sunkbd.h
index 151c77457..a1bfeb85b 100644
--- a/drivers/sbus/char/sunkbd.h
+++ b/drivers/sbus/char/sunkbd.h
@@ -1,4 +1,4 @@
-/* $Id: sunkbd.h,v 1.1 1997/08/28 02:23:34 ecd Exp $
+/* $Id: sunkbd.h,v 1.3 1997/09/08 03:05:10 tdyas Exp $
* sunkbd.h: Defines needed by SUN Keyboard drivers
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -7,6 +7,8 @@
#ifndef _SPARC_SUNKBD_H
#define _SPARC_SUNKBD_H 1
+#include <linux/config.h>
+
/* Keyboard defines for L1-A processing... */
#define SUNKBD_RESET 0xff
#define SUNKBD_L1 0x01
@@ -24,4 +26,26 @@ extern void keyboard_zsinit(void (*kbd_put_char)(unsigned char));
extern void sunkbd_inchar(unsigned char, struct pt_regs *);
extern void batten_down_hatches(void);
+extern int sun_kbd_init(void);
+extern void sun_compute_shiftstate(void);
+extern void sun_setledstate(struct kbd_struct *, unsigned int);
+extern unsigned char sun_getledstate(void);
+extern int sun_setkeycode(unsigned int, unsigned int);
+extern int sun_getkeycode(unsigned int);
+
+#ifdef CONFIG_PCI
+
+extern ushort *sun_key_maps[MAX_NR_KEYMAPS];
+extern unsigned int sun_keymap_count;
+
+extern char sun_func_buf[];
+extern char *sun_func_table[MAX_NR_FUNC];
+extern int sun_funcbufsize;
+extern int sun_funcbufleft;
+
+extern struct kbdiacr sun_accent_table[MAX_DIACR];
+extern unsigned int sun_accent_table_size;
+
+#endif /* CONFIG_PCI */
+
#endif /* !(_SPARC_SUNKBD_H) */
diff --git a/drivers/sbus/char/sunkbdmap.c b/drivers/sbus/char/sunkbdmap.c
new file mode 100644
index 000000000..43afa0343
--- /dev/null
+++ b/drivers/sbus/char/sunkbdmap.c
@@ -0,0 +1,33 @@
+
+/* $Id: sunkbdmap.c,v 1.1 1997/09/07 15:40:27 ecd Exp $
+ * sunkbdmap.c: Wrapper around sunkeymap.c to change table names.
+ *
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#define func_buf sun_func_buf
+#define func_table sun_func_table
+#define funcbufsize sun_funcbufsize
+#define funcbufleft sun_funcbufleft
+#define funcbufptr sun_funcbufptr
+#define accent_table sun_accent_table
+#define accent_table_size sun_accent_table_size
+
+#define key_maps sun_key_maps
+#define keymap_count sun_keymap_count
+
+#define plain_map sun_plain_map
+#define shift_map sun_shift_map
+#define ctrl_map sun_ctrl_map
+#define alt_map sun_alt_map
+#define altgr_map sun_altgr_map
+#define shift_ctrl_map sun_shift_ctrl_map
+#define ctrl_alt_map sun_ctrl_alt_map
+
+#endif /* CONFIG_PCI */
+
+#include "sunkeymap.c"
diff --git a/drivers/sbus/char/sunmouse.c b/drivers/sbus/char/sunmouse.c
index 2f8f8b3c9..0de65c330 100644
--- a/drivers/sbus/char/sunmouse.c
+++ b/drivers/sbus/char/sunmouse.c
@@ -329,12 +329,11 @@ sun_mouse_open(struct inode * inode, struct file * file)
return 0;
}
-static int
-sun_mouse_fasync (struct inode *inode, struct file *filp, int on)
+static int sun_mouse_fasync (struct file *filp, int on)
{
int retval;
- retval = fasync_helper (inode, filp, on, &sunmouse.fasync);
+ retval = fasync_helper (filp, on, &sunmouse.fasync);
if (retval < 0)
return retval;
return 0;
@@ -343,23 +342,23 @@ sun_mouse_fasync (struct inode *inode, struct file *filp, int on)
static int
sun_mouse_close(struct inode *inode, struct file *file)
{
- sun_mouse_fasync (inode, file, 0);
+ sun_mouse_fasync (file, 0);
if (--sunmouse.active)
return 0;
sunmouse.ready = 0;
return 0;
}
-static long
-sun_mouse_write(struct inode *inode, struct file *file, const char *buffer,
- unsigned long count)
+static ssize_t
+sun_mouse_write(struct file *file, const char *buffer,
+ size_t count, loff_t *ppos)
{
return -EINVAL; /* foo on you */
}
-static long
-sun_mouse_read(struct inode *inode, struct file *file, char *buffer,
- unsigned long count)
+static ssize_t
+sun_mouse_read(struct file *file, char *buffer,
+ size_t count, loff_t *ppos)
{
struct wait_queue wait = { current, NULL };
@@ -399,7 +398,7 @@ sun_mouse_read(struct inode *inode, struct file *file, char *buffer,
}
}
sunmouse.ready = !queue_empty ();
- inode->i_atime = CURRENT_TIME;
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return p-buffer;
} else {
int c;
@@ -410,7 +409,7 @@ sun_mouse_read(struct inode *inode, struct file *file, char *buffer,
sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE;
}
sunmouse.ready = !queue_empty();
- inode->i_atime = CURRENT_TIME;
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count-c;
}
/* Only called if nothing was sent */
@@ -421,7 +420,7 @@ sun_mouse_read(struct inode *inode, struct file *file, char *buffer,
static unsigned int sun_mouse_poll(struct file *file, poll_table *wait)
{
- poll_wait(&sunmouse.proc_list, wait);
+ poll_wait(file, &sunmouse.proc_list, wait);
if(sunmouse.ready)
return POLLIN | POLLRDNORM;
return 0;
@@ -484,8 +483,11 @@ static struct miscdevice sun_mouse_mouse = {
__initfunc(int sun_mouse_init(void))
{
+ if (!sunmouse.present)
+ return -ENODEV;
+
printk("Sun Mouse-Systems mouse driver version 1.00\n");
- sunmouse.present = 1;
+
sunmouse.ready = sunmouse.active = 0;
misc_register (&sun_mouse_mouse);
sunmouse.delta_x = sunmouse.delta_y = 0;
@@ -498,5 +500,5 @@ __initfunc(int sun_mouse_init(void))
void
sun_mouse_zsinit(void)
{
- sunmouse.ready = 1;
+ sunmouse.present = 1;
}
diff --git a/drivers/sbus/char/sunserial.c b/drivers/sbus/char/sunserial.c
index da90d5ade..8fb203207 100644
--- a/drivers/sbus/char/sunserial.c
+++ b/drivers/sbus/char/sunserial.c
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.50 1997/09/03 11:54:59 ecd Exp $
+/* $Id: sunserial.c,v 1.56 1997/12/19 07:33:07 ecd Exp $
* serial.c: Serial port driver infrastructure for the Sparc.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -9,17 +9,19 @@
#include <linux/errno.h>
#include <linux/tty.h>
#include <linux/serial.h>
+#include <linux/string.h>
+#include <linux/kbd_diacr.h>
+#include <linux/version.h>
+#include <linux/init.h>
#include <asm/oplib.h>
#include "sunserial.h"
-static void nop_rs_cons_hook(int chip, int out, int line)
-{
- printk("Oops: %s called\n", __FUNCTION__);
-}
+int serial_console;
-static void nop_rs_kgdb_hook(int channel)
+__initfunc(static void
+nop_rs_kgdb_hook(int channel))
{
printk("Oops: %s called\n", __FUNCTION__);
}
@@ -36,10 +38,8 @@ static int nop_rs_read_proc(char *page, char **start, off_t off, int count,
return 0;
}
-
struct sunserial_operations rs_ops = {
0,
- nop_rs_cons_hook,
nop_rs_kgdb_hook,
nop_rs_change_mouse_baud,
nop_rs_read_proc
@@ -47,25 +47,41 @@ struct sunserial_operations rs_ops = {
int rs_init(void)
{
- struct rs_initfunc *init;
+ struct initfunc *init;
int err = -ENODEV;
init = rs_ops.rs_init;
while (init) {
- err = init->rs_init();
+ err = init->init();
init = init->next;
}
return err;
}
-void rs_cons_hook(int chip, int out, int line)
+__initfunc(void
+rs_kgdb_hook(int channel))
{
- rs_ops.rs_cons_hook(chip, out, line);
+ rs_ops.rs_kgdb_hook(channel);
}
-void rs_kgdb_hook(int channel)
+__initfunc(static void sun_serial_finish_init(void))
{
- rs_ops.rs_kgdb_hook(channel);
+ extern unsigned char *linux_serial_image;
+ extern int con_is_present(void);
+ char buffer[2048];
+
+ if (con_is_present())
+ return;
+
+ sprintf (buffer, linux_serial_image, UTS_RELEASE);
+ printk(buffer);
+}
+
+__initfunc(long
+serial_console_init(long kmem_start, long kmem_end))
+{
+ sun_serial_finish_init();
+ return kmem_start;
}
void rs_change_mouse_baud(int baud)
@@ -88,45 +104,299 @@ void unregister_serial(int line)
{
}
+
+static void nop_compute_shiftstate (void)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+}
+
+static void nop_setledstate (struct kbd_struct *kbd, unsigned int ledstate)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+}
+
+static unsigned char nop_getledstate (void)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+ return 0;
+}
+
+static int nop_setkeycode (unsigned int scancode, unsigned int keycode)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+ return -EINVAL;
+}
+
+static int nop_getkeycode (unsigned int scancode)
+{
+ printk("Oops: %s called\n", __FUNCTION__);
+ return -EINVAL;
+}
+
+struct sunkbd_operations kbd_ops = {
+ 0,
+ nop_compute_shiftstate,
+ nop_setledstate,
+ nop_getledstate,
+ nop_setkeycode,
+ nop_getkeycode
+};
+
+int kbd_init(void)
+{
+ struct initfunc *init;
+ int err = -ENODEV;
+
+ init = kbd_ops.kbd_init;
+ while (init) {
+ err = init->init();
+ init = init->next;
+ }
+ return err;
+}
+
+void compute_shiftstate (void)
+{
+ kbd_ops.compute_shiftstate();
+}
+
+void setledstate (struct kbd_struct *kbd, unsigned int ledstate)
+{
+ kbd_ops.setledstate(kbd, ledstate);
+}
+
+unsigned char getledstate (void)
+{
+ return kbd_ops.getledstate();
+}
+
+int setkeycode (unsigned int scancode, unsigned int keycode)
+{
+ return kbd_ops.setkeycode(scancode, keycode);
+}
+
+int getkeycode (unsigned int scancode)
+{
+ return kbd_ops.getkeycode(scancode);
+}
+
+
void
sunserial_setinitfunc(unsigned long *memory_start, int (*init) (void))
{
- struct rs_initfunc *rs_init;
+ struct initfunc *rs_init;
*memory_start = (*memory_start + 7) & ~(7);
- rs_init = (struct rs_initfunc *) *memory_start;
- *memory_start += sizeof(struct rs_initfunc);
+ rs_init = (struct initfunc *) *memory_start;
+ *memory_start += sizeof(struct initfunc);
- rs_init->rs_init = init;
+ rs_init->init = init;
rs_init->next = rs_ops.rs_init;
rs_ops.rs_init = rs_init;
}
+void
+sunserial_console_termios(struct console *con)
+{
+ char mode[16], buf[16], *s;
+ char *mode_prop = "ttyX-mode";
+ char *cd_prop = "ttyX-ignore-cd";
+ char *dtr_prop = "ttyX-rts-dtr-off";
+ int baud, bits, stop, cflag;
+ char parity;
+ int carrier = 0;
+ int rtsdtr = 1;
+ int topnd, nd;
+
+ if (!serial_console)
+ return;
+
+ if (serial_console == 1) {
+ mode_prop[3] = 'a';
+ cd_prop[3] = 'a';
+ dtr_prop[3] = 'a';
+ } else {
+ mode_prop[3] = 'b';
+ cd_prop[3] = 'b';
+ dtr_prop[3] = 'b';
+ }
+
+ topnd = prom_getchild(prom_root_node);
+ nd = prom_searchsiblings(topnd, "options");
+ if (!nd) {
+ strcpy(mode, "9600,8,n,1,-");
+ goto no_options;
+ }
+
+ if (!prom_node_has_property(nd, mode_prop)) {
+ strcpy(mode, "9600,8,n,1,-");
+ goto no_options;
+ }
+
+ memset(mode, 0, sizeof(mode));
+ prom_getstring(nd, mode_prop, mode, sizeof(mode));
+
+ if (prom_node_has_property(nd, cd_prop)) {
+ memset(buf, 0, sizeof(buf));
+ prom_getstring(nd, cd_prop, buf, sizeof(buf));
+ if (!strcmp(buf, "false"))
+ carrier = 1;
+
+ /* XXX: this is unused below. */
+ }
+
+ if (prom_node_has_property(nd, cd_prop)) {
+ memset(buf, 0, sizeof(buf));
+ prom_getstring(nd, cd_prop, buf, sizeof(buf));
+ if (!strcmp(buf, "false"))
+ rtsdtr = 0;
+
+ /* XXX: this is unused below. */
+ }
+
+no_options:
+ cflag = CREAD | HUPCL | CLOCAL;
+
+ s = mode;
+ baud = simple_strtoul(s, 0, 0);
+ s = strchr(s, ',');
+ bits = simple_strtoul(++s, 0, 0);
+ s = strchr(s, ',');
+ parity = *(++s);
+ s = strchr(s, ',');
+ stop = simple_strtoul(++s, 0, 0);
+ s = strchr(s, ',');
+ /* XXX handshake is not handled here. */
+
+ switch (baud) {
+ case 150: cflag |= B150; break;
+ case 300: cflag |= B300; break;
+ case 600: cflag |= B600; break;
+ case 1200: cflag |= B1200; break;
+ case 2400: cflag |= B2400; break;
+ case 4800: cflag |= B4800; break;
+ case 9600: cflag |= B9600; break;
+ case 19200: cflag |= B19200; break;
+ case 38400: cflag |= B38400; break;
+ default: cflag |= B9600; break;
+ }
+
+ switch (bits) {
+ case 5: cflag |= CS5; break;
+ case 6: cflag |= CS6; break;
+ case 7: cflag |= CS7; break;
+ case 8: cflag |= CS8; break;
+ default: cflag |= CS8; break;
+ }
+
+ switch (parity) {
+ case 'o': cflag |= (PARENB | PARODD); break;
+ case 'e': cflag |= PARENB; break;
+ case 'n': default: break;
+ }
+
+ switch (stop) {
+ case 2: cflag |= CSTOPB; break;
+ case 1: default: break;
+ }
+
+ con->cflag = cflag;
+}
+
+void
+sunkbd_setinitfunc(unsigned long *memory_start, int (*init) (void))
+{
+ struct initfunc *kbd_init;
+
+ *memory_start = (*memory_start + 7) & ~(7);
+ kbd_init = (struct initfunc *) *memory_start;
+ *memory_start += sizeof(struct initfunc);
+
+ kbd_init->init = init;
+ kbd_init->next = kbd_ops.kbd_init;
+ kbd_ops.kbd_init = kbd_init;
+}
+
+#ifdef CONFIG_PCI
+void
+sunkbd_install_keymaps(unsigned long *memory_start,
+ ushort **src_key_maps, unsigned int src_keymap_count,
+ char *src_func_buf, char **src_func_table,
+ int src_funcbufsize, int src_funcbufleft,
+ struct kbdiacr *src_accent_table,
+ unsigned int src_accent_table_size)
+{
+ extern unsigned int keymap_count;
+ int i, j;
+
+ for (i = 0; i < MAX_NR_KEYMAPS; i++) {
+ if (src_key_maps[i]) {
+ if (!key_maps[i]) {
+ key_maps[i] = (ushort *)*memory_start;
+ *memory_start += NR_KEYS * sizeof(ushort);
+ }
+ for (j = 0; j < NR_KEYS; j++)
+ key_maps[i][j] = src_key_maps[i][j];
+ }
+ key_maps[i] = src_key_maps[i];
+ }
+ keymap_count = src_keymap_count;
+
+ for (i = 0; i < MAX_NR_FUNC; i++)
+ func_table[i] = src_func_table[i];
+ funcbufptr = src_func_buf;
+ funcbufsize = src_funcbufsize;
+ funcbufleft = src_funcbufleft;
+
+ for (i = 0; i < MAX_DIACR; i++)
+ accent_table[i] = src_accent_table[i];
+ accent_table_size = src_accent_table_size;
+}
+#endif
+
extern int zs_probe(unsigned long *);
#ifdef CONFIG_SAB82532
extern int sab82532_probe(unsigned long *);
#endif
-#ifdef __sparc_v9__
+#ifdef CONFIG_PCI
extern int ps2kbd_probe(unsigned long *);
extern int su_probe(unsigned long *);
#endif
-unsigned long
-sun_serial_setup(unsigned long memory_start)
+__initfunc(unsigned long
+sun_serial_setup(unsigned long memory_start))
{
+ int ret = -ENODEV;
+
/* Probe for controllers. */
- if (zs_probe(&memory_start) == 0)
+ ret = zs_probe(&memory_start);
+ if (!ret)
return memory_start;
#ifdef CONFIG_SAB82532
- sab82532_probe(&memory_start);
+ ret = sab82532_probe(&memory_start);
#endif
-#ifdef __sparc_v9__
- if (ps2kbd_probe(&memory_start) == 0)
- return memory_start;
- if (su_probe(&memory_start) == 0)
- return memory_start;
+#ifdef CONFIG_PCI
+ /*
+ * Keyboard serial devices.
+ *
+ * Well done, Sun, prom_devopen("/pci@1f,4000/ebus@1/su@14,3083f8")
+ * hangs the machine if no keyboard is connected to the device...
+ * All PCI PROMs seem to do this, I have seen this on the Ultra 450
+ * with version 3.5 PROM, and on the Ultra/AX with 3.1.5 PROM.
+ *
+ * So be very careful not to probe for keyboards if we are on a
+ * serial console.
+ */
+ if (!serial_console) {
+ if (ps2kbd_probe(&memory_start) == 0)
+ return memory_start;
+ if (su_probe(&memory_start) == 0)
+ return memory_start;
+ }
#endif
+ if (!ret)
+ return memory_start;
prom_printf("No serial devices found, bailing out.\n");
prom_halt();
diff --git a/drivers/sbus/char/sunserial.h b/drivers/sbus/char/sunserial.h
index 8877d4b56..e0438051b 100644
--- a/drivers/sbus/char/sunserial.h
+++ b/drivers/sbus/char/sunserial.h
@@ -1,5 +1,5 @@
-/* $Id: sunserial.h,v 1.13 1997/09/03 11:55:00 ecd Exp $
- * sunserial.h: SUN serial driver infrastructure.
+/* $Id: sunserial.h,v 1.17 1997/12/19 07:33:12 ecd Exp $
+ * sunserial.h: SUN serial driver infrastructure (including keyboards).
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
*/
@@ -7,42 +7,45 @@
#ifndef _SPARC_SUNSERIAL_H
#define _SPARC_SUNSERIAL_H 1
+#include <linux/config.h>
#include <linux/tty.h>
+#include <linux/kd.h>
+#include <linux/kbd_kern.h>
+#include <linux/console.h>
-struct rs_initfunc {
- int (*rs_init) (void);
- struct rs_initfunc *next;
+struct initfunc {
+ int (*init) (void);
+ struct initfunc *next;
};
struct sunserial_operations {
- struct rs_initfunc *rs_init;
- void (*rs_cons_hook) (int, int, int);
- void (*rs_kgdb_hook) (int);
- void (*rs_change_mouse_baud) (int);
- int (*rs_read_proc) (char *, char **, off_t, int, int *, void *);
+ struct initfunc *rs_init;
+ void (*rs_kgdb_hook) (int);
+ void (*rs_change_mouse_baud) (int);
+ int (*rs_read_proc) (char *, char **, off_t, int, int *, void *);
};
-/*
- * XXX: Work in progress, don't worry this will go away in a few days. (ecd)
- *
- * To support multiple keyboards in one binary we have to take care
- * about (at least) the following:
- *
- * int shift_state;
- *
- * char *func_buf;
- * char *func_bufptr;
- * int funcbufsize;
- * int funcbufleft;
- * char **func_table;
- *
- * XXX: keymaps need to be handled...
- *
- * struct kbd_struct *kbd_table;
- * int (*kbd_init)(void);
- */
+struct sunkbd_operations {
+ struct initfunc *kbd_init;
+ void (*compute_shiftstate) (void);
+ void (*setledstate) (struct kbd_struct *, unsigned int);
+ unsigned char (*getledstate) (void);
+ int (*setkeycode) (unsigned int, unsigned int);
+ int (*getkeycode) (unsigned int);
+};
extern struct sunserial_operations rs_ops;
+extern struct sunkbd_operations kbd_ops;
+
extern void sunserial_setinitfunc(unsigned long *, int (*) (void));
+extern void sunkbd_setinitfunc(unsigned long *, int (*) (void));
+
+extern int serial_console;
+extern void sunserial_console_termios(struct console *);
+
+#ifdef CONFIG_PCI
+extern void sunkbd_install_keymaps(unsigned long *, ushort **, unsigned int, char *,
+ char **, int, int, struct kbdiacr *, unsigned int);
+#endif
#endif /* !(_SPARC_SUNSERIAL_H) */
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 007174a82..d144c7823 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -666,9 +666,6 @@ int init_module(void)
int vfc_init(void)
#endif
{
-#ifdef MODULE
- register_symtab(0);
-#endif
return vfc_probe();
}
diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c
index 8875f7dc7..6162ed4ad 100644
--- a/drivers/sbus/char/zs.c
+++ b/drivers/sbus/char/zs.c
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.3 1997/09/04 14:57:34 jj Exp $
+/* $Id: zs.c,v 1.15 1997/12/22 16:09:34 jj Exp $
* zs.c: Zilog serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -22,8 +22,8 @@
#include <linux/keyboard.h>
#include <linux/console.h>
#include <linux/delay.h>
-#include <linux/version.h>
#include <linux/init.h>
+#include <linux/sysrq.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -36,6 +36,9 @@
#include <asm/sbus.h>
#ifdef __sparc_v9__
#include <asm/fhc.h>
+#ifdef CONFIG_PCI
+#include <linux/bios32.h>
+#endif
#endif
#include "sunserial.h"
@@ -52,7 +55,6 @@ static int num_serial = 2; /* sun4/sun4c/sun4m - Two chips on board. */
struct sun_zslayout **zs_chips;
struct sun_zschannel **zs_channels;
-struct sun_zschannel *zs_conschan;
struct sun_zschannel *zs_mousechan;
struct sun_zschannel *zs_kbdchan;
struct sun_zschannel *zs_kgdbchan;
@@ -63,12 +65,12 @@ struct sun_serial *zs_chain; /* IRQ servicing chain */
int zilog_irq;
struct tty_struct *zs_ttys;
-/** struct tty_struct *zs_constty; **/
/* Console hooks... */
-static int zs_cons_chanout = 0;
-static int zs_cons_chanin = 0;
-struct sun_serial *zs_consinfo = 0;
+#ifdef CONFIG_SERIAL_CONSOLE
+static struct console zs_console;
+static int zs_console_init(void);
+#endif
static unsigned char kgdb_regs[16] = {
0, 0, 0, /* write 0, 1, 2 */
@@ -114,6 +116,8 @@ static int serial_refcount;
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
+#define SERIAL_DO_RESTART
+
/* Debugging... DEBUG_INTR is bad to use when one of the zs
* lines is your console ;(
*/
@@ -127,8 +131,7 @@ static int serial_refcount;
#define _INLINE_ inline
int zs_init(void);
-void zs_cons_hook(int, int, int);
-void zs_kgdb_hook(int);
+static void zs_kgdb_hook(int);
static void change_speed(struct sun_serial *info);
@@ -443,20 +446,29 @@ static _INLINE_ void receive_chars(struct sun_serial *info, struct pt_regs *regs
return;
}
if(info->is_cons) {
+#ifdef CONFIG_MAGIC_SYSRQ
+ static int serial_sysrq;
+
+ if (!ch) {
+ serial_sysrq = 1;
+ return;
+ } else if (serial_sysrq) {
+ if (ch == 'a' || ch == 'A')
+ /* whee, break-A received */
+ batten_down_hatches();
+ else
+ handle_sysrq(ch, regs, NULL, NULL);
+ serial_sysrq = 0;
+ return;
+ }
+#else
if(ch==0) {
/* whee, break received */
batten_down_hatches();
/* Continue execution... */
return;
-#if 0
- } else if (ch == 1) {
- show_state();
- return;
- } else if (ch == 2) {
- show_buffers();
- return;
-#endif
}
+#endif
/* It is a 'keyboard interrupt' ;-) */
wake_up(&keypress_wait);
}
@@ -996,21 +1008,6 @@ void mouse_put_char(char ch)
restore_flags(flags);
}
-
-/* This is for console output over ttya/ttyb */
-static void zs_cons_put_char(char ch)
-{
- struct sun_zschannel *chan = zs_conschan;
- unsigned long flags;
-
- if(!chan)
- return;
-
- save_flags(flags); cli();
- zs_put_char(chan, ch);
- restore_flags(flags);
-}
-
/* These are for receiving and sending characters under the kgdb
* source level kernel debugger.
*/
@@ -1032,70 +1029,6 @@ char getDebugChar(void)
return chan->data;
}
-/*
- * Fair output driver allows a process to speak.
- */
-static void zs_fair_output(void)
-{
- int left; /* Output no more than that */
- unsigned long flags;
- struct sun_serial *info = zs_consinfo;
- char c;
-
- if (info == 0) return;
- if (info->xmit_buf == 0) return;
-
- save_flags(flags); cli();
- left = info->xmit_cnt;
- while (left != 0) {
- c = info->xmit_buf[info->xmit_tail];
- info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt--;
- restore_flags(flags);
-
- zs_cons_put_char(c);
-
- cli();
- left = MIN(info->xmit_cnt, left-1);
- }
-
- /* Last character is being transmitted now (hopefully). */
- zs_conschan->control = RES_Tx_P;
- udelay(5);
-
- restore_flags(flags);
- return;
-}
-
-/*
- * zs_console_print is registered for printk.
- */
-static void zs_console_print(const char *s, unsigned count)
-{
- int i;
-
- for (i = 0; i < count; i++, s++) {
- if(*s == '\n')
- zs_cons_put_char('\r');
- zs_cons_put_char(*s);
- }
-
- /* Comment this if you want to have a strict interrupt-driven output */
- zs_fair_output();
-}
-
-static void zs_console_wait_key(void)
-{
- sleep_on(&keypress_wait);
-}
-
-static int zs_console_device(void)
-{
- extern int serial_console;
-
- return MKDEV(TTYAUX_MAJOR, 64 + serial_console - 1);
-}
-
static void zs_flush_chars(struct tty_struct *tty)
{
struct sun_serial *info = (struct sun_serial *)tty->driver_data;
@@ -1190,7 +1123,7 @@ static int zs_write_room(struct tty_struct *tty)
{
struct sun_serial *info = (struct sun_serial *)tty->driver_data;
int ret;
-
+
if (serial_paranoia_check(info, tty->device, "zs_write_room"))
return 0;
ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
@@ -1202,7 +1135,7 @@ static int zs_write_room(struct tty_struct *tty)
static int zs_chars_in_buffer(struct tty_struct *tty)
{
struct sun_serial *info = (struct sun_serial *)tty->driver_data;
-
+
if (serial_paranoia_check(info, tty->device, "zs_chars_in_buffer"))
return 0;
return info->xmit_cnt;
@@ -1211,7 +1144,7 @@ static int zs_chars_in_buffer(struct tty_struct *tty)
static void zs_flush_buffer(struct tty_struct *tty)
{
struct sun_serial *info = (struct sun_serial *)tty->driver_data;
-
+
if (serial_paranoia_check(info, tty->device, "zs_flush_buffer"))
return;
cli();
@@ -1641,10 +1574,13 @@ static void zs_close(struct tty_struct *tty, struct file * filp)
void zs_hangup(struct tty_struct *tty)
{
struct sun_serial * info = (struct sun_serial *)tty->driver_data;
-
+
if (serial_paranoia_check(info, tty->device, "zs_hangup"))
return;
-
+
+ if (info->is_cons)
+ return;
+
#ifdef SERIAL_DEBUG_OPEN
printk("zs_hangup<%p: tty-%d, count = %d bye\n",
__builtin_return_address(0), info->line, info->count);
@@ -1862,6 +1798,14 @@ int zs_open(struct tty_struct *tty, struct file * filp)
change_speed(info);
}
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (zs_console.cflag && zs_console.index == line) {
+ tty->termios->c_cflag = zs_console.cflag;
+ zs_console.cflag = 0;
+ change_speed(info);
+ }
+#endif
+
info->session = current->session;
info->pgrp = current->pgrp;
@@ -1875,7 +1819,7 @@ int zs_open(struct tty_struct *tty, struct file * filp)
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.3 $";
+ char *revision = "$Revision: 1.15 $";
char *version, *p;
version = strchr(revision, ' ');
@@ -1895,7 +1839,8 @@ static void show_serial_version(void)
#ifdef __sparc_v9__
static struct devid_cookie zs_dcookie;
static unsigned long zs_irq_flags;
-static struct sun_zslayout *get_zs(int chip)
+__initfunc(static struct sun_zslayout *
+get_zs(int chip))
{
unsigned int vaddr[2] = { 0, 0 };
int busnode, seen, zsnode, sun4u_ino;
@@ -1968,13 +1913,16 @@ static struct sun_zslayout *get_zs(int chip)
return (struct sun_zslayout *)(unsigned long) vaddr[0];
}
#else /* !(__sparc_v9__) */
-static struct sun_zslayout *get_zs(int chip)
+__initfunc(static struct sun_zslayout *
+get_zs(int chip))
{
struct linux_prom_irqs tmp_irq[2];
unsigned int paddr = 0;
unsigned int vaddr[2] = { 0, 0 };
- int zsnode, tmpnode, iospace, slave, len, seen, sun4u_irq;
+ int zsnode, tmpnode, iospace, slave, len;
+ int cpunode = 0, bbnode = 0;
static int irq = 0;
+ int chipid = chip;
#if CONFIG_AP1000
printk("No zs chip\n");
@@ -2014,7 +1962,10 @@ static struct sun_zslayout *get_zs(int chip)
if (board == (chip >> 1)) {
node = prom_getchild(tmpnode);
if (node && (node = prom_searchsiblings(node, "bootbus"))) {
- zsnode = node;
+ cpunode = tmpnode;
+ bbnode = node;
+ zsnode = prom_getchild(node);
+ chipid = (chip & 1);
break;
}
}
@@ -2022,10 +1973,6 @@ static struct sun_zslayout *get_zs(int chip)
}
if (!tmpnode)
panic ("get_zs: couldn't find board%d's bootbus\n", chip >> 1);
- } else if (sparc_cpu_model == sun4u) {
- tmpnode = prom_searchsiblings(zsnode, "sbus");
- if(tmpnode)
- zsnode = prom_getchild(tmpnode);
} else {
tmpnode = prom_searchsiblings(zsnode, "obio");
if(tmpnode)
@@ -2033,41 +1980,46 @@ static struct sun_zslayout *get_zs(int chip)
}
if(!zsnode)
panic("get_zs no zs serial prom node");
- seen = 0;
while(zsnode) {
zsnode = prom_searchsiblings(zsnode, "zs");
slave = prom_getintdefault(zsnode, "slave", -1);
- if((slave == chip) ||
- (sparc_cpu_model == sun4u && seen == chip)) {
+ if(slave == chipid) {
/* The one we want */
- len = prom_getproperty(zsnode, "address",
- (void *) vaddr,
- sizeof(vaddr));
- if (len % sizeof(unsigned int)) {
- prom_printf("WHOOPS: proplen for %s "
- "was %d, need multiple of "
- "%d\n", "address", len,
- sizeof(unsigned int));
- panic("zilog: address property");
- }
- zs_nodes[chip] = zsnode;
- if(sparc_cpu_model == sun4u) {
- len = prom_getproperty(zsnode, "interrupts",
- (char *) &sun4u_irq,
- sizeof(tmp_irq));
- tmp_irq[0].pri = sun4u_irq;
- } else {
- len = prom_getproperty(zsnode, "intr",
- (char *) tmp_irq,
- sizeof(tmp_irq));
- if (len % sizeof(struct linux_prom_irqs)) {
- prom_printf(
- "WHOOPS: proplen for %s "
- "was %d, need multiple of "
- "%d\n", "address", len,
- sizeof(struct linux_prom_irqs));
+ if (sparc_cpu_model != sun4d) {
+ len = prom_getproperty(zsnode, "address",
+ (void *) vaddr,
+ sizeof(vaddr));
+ if (len % sizeof(unsigned int)) {
+ prom_printf("WHOOPS: proplen for %s "
+ "was %d, need multiple of "
+ "%d\n", "address", len,
+ sizeof(unsigned int));
panic("zilog: address property");
}
+ } else {
+ /* On sun4d don't have address property :( */
+ struct linux_prom_registers zsreg[4];
+
+ if (prom_getproperty(zsnode, "reg", (char *)zsreg, sizeof(zsreg)) == -1) {
+ prom_printf ("Cannot map zs regs\n");
+ prom_halt();
+ }
+ prom_apply_generic_ranges(bbnode, cpunode, zsreg, 1);
+ vaddr[0] = (unsigned long)
+ sparc_alloc_io(zsreg[0].phys_addr, 0, 8,
+ "Zilog Serial", zsreg[0].which_io, 0);
+ }
+ zs_nodes[chip] = zsnode;
+ len = prom_getproperty(zsnode, "intr",
+ (char *) tmp_irq,
+ sizeof(tmp_irq));
+ if (len % sizeof(struct linux_prom_irqs)) {
+ prom_printf(
+ "WHOOPS: proplen for %s "
+ "was %d, need multiple of "
+ "%d\n", "address", len,
+ sizeof(struct linux_prom_irqs));
+ panic("zilog: address property");
}
if(!irq) {
irq = zilog_irq = tmp_irq[0].pri;
@@ -2078,7 +2030,6 @@ static struct sun_zslayout *get_zs(int chip)
break;
}
zsnode = prom_getsibling(zsnode);
- seen++;
}
if(!zsnode)
panic("get_zs whee chip not found");
@@ -2089,242 +2040,6 @@ static struct sun_zslayout *get_zs(int chip)
return (struct sun_zslayout *)(unsigned long) vaddr[0];
}
#endif
-
-static inline void
-init_zscons_termios(struct termios *termios)
-{
- char mode[16], buf[16];
- char *mode_prop = "ttyX-mode";
- char *cd_prop = "ttyX-ignore-cd";
- char *dtr_prop = "ttyX-rts-dtr-off";
- char *s;
- int baud, bits, cflag;
- char parity;
- int topnd, nd;
- int channel, stop;
- int carrier = 0;
- int rtsdtr = 1;
- extern int serial_console;
-
- if (!serial_console)
- return;
-
- if (serial_console == 1) {
- mode_prop[3] = 'a';
- cd_prop[3] = 'a';
- dtr_prop[3] = 'a';
- } else {
- mode_prop[3] = 'b';
- cd_prop[3] = 'b';
- dtr_prop[3] = 'b';
- }
-
- topnd = prom_getchild(prom_root_node);
- nd = prom_searchsiblings(topnd, "options");
- if (!nd) {
- strcpy(mode, "9600,8,n,1,-");
- goto no_options;
- }
-
- if (!prom_node_has_property(nd, mode_prop)) {
- strcpy(mode, "9600,8,n,1,-");
- goto no_options;
- }
-
- memset(mode, 0, sizeof(mode));
- prom_getstring(nd, mode_prop, mode, sizeof(mode));
-
- if (prom_node_has_property(nd, cd_prop)) {
- memset(buf, 0, sizeof(buf));
- prom_getstring(nd, cd_prop, buf, sizeof(buf));
- if (!strcmp(buf, "false"))
- carrier = 1;
-
- /* XXX this is unused below. */
- }
-
- if (prom_node_has_property(nd, cd_prop)) {
- memset(buf, 0, sizeof(buf));
- prom_getstring(nd, cd_prop, buf, sizeof(buf));
- if (!strcmp(buf, "false"))
- rtsdtr = 0;
-
- /* XXX this is unused below. */
- }
-
-no_options:
- cflag = CREAD | HUPCL | CLOCAL;
-
- s = mode;
- baud = simple_strtoul(s, 0, 0);
- s = strchr(s, ',');
- bits = simple_strtoul(++s, 0, 0);
- s = strchr(s, ',');
- parity = *(++s);
- s = strchr(s, ',');
- stop = simple_strtoul(++s, 0, 0);
- s = strchr(s, ',');
- /* XXX handshake is not handled here. */
-
- for (channel = 0; channel < NUM_CHANNELS; channel++)
- if (zs_soft[channel].is_cons)
- break;
-
- switch (baud) {
- case 150:
- cflag |= B150;
- break;
- case 300:
- cflag |= B300;
- break;
- case 600:
- cflag |= B600;
- break;
- case 1200:
- cflag |= B1200;
- break;
- case 2400:
- cflag |= B2400;
- break;
- case 4800:
- cflag |= B4800;
- break;
- default:
- baud = 9600;
- case 9600:
- cflag |= B9600;
- break;
- case 19200:
- cflag |= B19200;
- break;
- case 38400:
- cflag |= B38400;
- break;
- }
- zs_soft[channel].zs_baud = baud;
-
- switch (bits) {
- case 5:
- zscons_regs[3] = Rx5 | RxENAB;
- zscons_regs[5] = Tx5 | TxENAB;
- zs_soft[channel].parity_mask = 0x1f;
- cflag |= CS5;
- break;
- case 6:
- zscons_regs[3] = Rx6 | RxENAB;
- zscons_regs[5] = Tx6 | TxENAB;
- zs_soft[channel].parity_mask = 0x3f;
- cflag |= CS6;
- break;
- case 7:
- zscons_regs[3] = Rx7 | RxENAB;
- zscons_regs[5] = Tx7 | TxENAB;
- zs_soft[channel].parity_mask = 0x7f;
- cflag |= CS7;
- break;
- default:
- case 8:
- zscons_regs[3] = Rx8 | RxENAB;
- zscons_regs[5] = Tx8 | TxENAB;
- zs_soft[channel].parity_mask = 0xff;
- cflag |= CS8;
- break;
- }
- zscons_regs[5] |= DTR;
-
- switch (parity) {
- case 'o':
- zscons_regs[4] |= PAR_ENAB;
- cflag |= (PARENB | PARODD);
- break;
- case 'e':
- zscons_regs[4] |= (PAR_ENAB | PAR_EVEN);
- cflag |= PARENB;
- break;
- default:
- case 'n':
- break;
- }
-
- switch (stop) {
- default:
- case 1:
- zscons_regs[4] |= SB1;
- break;
- case 2:
- cflag |= CSTOPB;
- zscons_regs[4] |= SB2;
- break;
- }
-
- termios->c_cflag = cflag;
-}
-
-__initfunc(static void serial_finish_init(void (*printfunc)(const char *, unsigned)))
-{
- extern unsigned char *linux_serial_image;
- char buffer[2048];
-
- sprintf (buffer, linux_serial_image, UTS_RELEASE);
- (*printfunc)(buffer, strlen(buffer));
-}
-
-static inline void
-zs_cons_check(struct sun_serial *ss, int channel)
-{
- int i, o, io;
- static int consout_registered = 0;
- static int msg_printed = 0;
- static struct console console = {
- zs_console_print, 0,
- zs_console_wait_key, zs_console_device };
-
- i = o = io = 0;
-
- /* Is this one of the serial console lines? */
- if((zs_cons_chanout != channel) &&
- (zs_cons_chanin != channel))
- return;
- zs_conschan = ss->zs_channel;
- zs_consinfo = ss;
-
- /* Register the console output putchar, if necessary */
- if((zs_cons_chanout == channel)) {
- o = 1;
- /* double whee.. */
- if(!consout_registered) {
- serial_finish_init (zs_console_print);
- register_console(&console);
- consout_registered = 1;
- }
- }
-
- /* If this is console input, we handle the break received
- * status interrupt on this line to mean prom_halt().
- */
- if(zs_cons_chanin == channel) {
- ss->break_abort = 1;
- i = 1;
- }
- if(o && i)
- io = 1;
-
- /* Set flag variable for this port so that it cannot be
- * opened for other uses by accident.
- */
- ss->is_cons = 1;
-
- if(io) {
- if(!msg_printed) {
- printk("zs%d: console I/O\n", ((channel>>1)&1));
- msg_printed = 1;
- }
- } else {
- printk("zs%d: console %s\n", ((channel>>1)&1),
- (i==1 ? "input" : (o==1 ? "output" : "WEIRD")));
- }
-}
-
/* This is for the auto baud rate detection in the mouse driver. */
void zs_change_mouse_baud(int newbaud)
{
@@ -2347,10 +2062,11 @@ __initfunc(int zs_probe (unsigned long *memory_start))
if(sparc_cpu_model == sun4)
goto no_probe;
+ NUM_SERIAL = 0;
+
node = prom_getchild(prom_root_node);
if (sparc_cpu_model == sun4d) {
node = prom_searchsiblings(node, "boards");
- NUM_SERIAL = 0;
if (!node)
panic ("Cannot find out count of boards");
else
@@ -2360,22 +2076,38 @@ __initfunc(int zs_probe (unsigned long *memory_start))
node = prom_getsibling(node);
}
goto no_probe;
- } else if (sparc_cpu_model == sun4u) {
- node = prom_searchsiblings(node, "sbus");
- if(node)
+ }
+#ifdef __sparc_v9__
+ else if (sparc_cpu_model == sun4u) {
+ int central_node;
+
+ /* Central bus zilogs must be checked for first,
+ * since Enterprise boxes have SBUS as well.
+ */
+ central_node = prom_finddevice("/central");
+ if(central_node != 0 && central_node != -1)
+ node = prom_searchsiblings(prom_getchild(central_node), "fhc");
+ else
+ node = prom_searchsiblings(node, "sbus");
+ if(node != 0 && node != -1)
node = prom_getchild(node);
- if(!node)
+ if(node == 0 || node == -1)
return -ENODEV;
- } else {
+ }
+#endif /* __sparc_v9__ */
+ else {
node = prom_searchsiblings(node, "obio");
if(node)
node = prom_getchild(node);
+ NUM_SERIAL = 2;
goto no_probe;
}
node = prom_searchsiblings(node, "zs");
if (!node)
return -ENODEV;
+
+ NUM_SERIAL = 2;
no_probe:
p = (char *)((*memory_start + 7) & ~7);
@@ -2399,17 +2131,85 @@ no_probe:
*memory_start = (((unsigned long)p) + i + 7) & ~7;
/* Fill in rs_ops struct... */
+#ifdef CONFIG_SERIAL_CONSOLE
+ sunserial_setinitfunc(memory_start, zs_console_init);
+#endif
sunserial_setinitfunc(memory_start, zs_init);
- rs_ops.rs_cons_hook = zs_cons_hook;
rs_ops.rs_kgdb_hook = zs_kgdb_hook;
rs_ops.rs_change_mouse_baud = zs_change_mouse_baud;
+ sunkbd_setinitfunc(memory_start, sun_kbd_init);
+ kbd_ops.compute_shiftstate = sun_compute_shiftstate;
+ kbd_ops.setledstate = sun_setledstate;
+ kbd_ops.getledstate = sun_getledstate;
+ kbd_ops.setkeycode = sun_setkeycode;
+ kbd_ops.getkeycode = sun_getkeycode;
+#ifdef CONFIG_PCI
+ sunkbd_install_keymaps(memory_start, sun_key_maps, sun_keymap_count,
+ sun_func_buf, sun_func_table,
+ sun_funcbufsize, sun_funcbufleft,
+ sun_accent_table, sun_accent_table_size);
+#endif
return 0;
}
+static inline void zs_prepare(void)
+{
+ int channel, chip;
+ unsigned long flags;
+
+ if (!NUM_SERIAL) return;
+
+ save_and_cli(flags);
+
+ /* Set up our interrupt linked list */
+ zs_chain = &zs_soft[0];
+ for(channel = 0; channel < NUM_CHANNELS - 1; channel++) {
+ zs_soft[channel].zs_next = &zs_soft[channel + 1];
+ zs_soft[channel].line = channel;
+ }
+ zs_soft[channel].zs_next = 0;
+
+ /* Initialize Softinfo */
+ for(chip = 0; chip < NUM_SERIAL; chip++) {
+ /* If we are doing kgdb over one of the channels on
+ * chip zero, kgdb_channel will be set to 1 by the
+ * zs_kgdb_hook() routine below.
+ */
+ if(!zs_chips[chip]) {
+ zs_chips[chip] = get_zs(chip);
+ /* Two channels per chip */
+ zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
+ zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
+ zs_soft[(chip*2)].kgdb_channel = 0;
+ zs_soft[(chip*2)+1].kgdb_channel = 0;
+ }
+
+ /* First, set up channel A on this chip. */
+ channel = chip * 2;
+ zs_soft[channel].zs_channel = zs_channels[channel];
+ zs_soft[channel].change_needed = 0;
+ zs_soft[channel].clk_divisor = 16;
+ zs_soft[channel].cons_keyb = 0;
+ zs_soft[channel].cons_mouse = 0;
+ zs_soft[channel].channelA = 1;
+
+ /* Now, channel B */
+ channel++;
+ zs_soft[channel].zs_channel = zs_channels[channel];
+ zs_soft[channel].change_needed = 0;
+ zs_soft[channel].clk_divisor = 16;
+ zs_soft[channel].cons_keyb = 0;
+ zs_soft[channel].cons_mouse = 0;
+ zs_soft[channel].channelA = 0;
+ }
+
+ restore_flags(flags);
+}
+
__initfunc(int zs_init(void))
{
- int chip, channel, brg, i;
+ int channel, brg, i;
unsigned long flags;
struct sun_serial *info;
char dummy;
@@ -2420,7 +2220,7 @@ __initfunc(int zs_init(void))
#endif
#ifdef CONFIG_PCI
- if (prom_searchsiblings(prom_getchild(prom_root_node), "pci"))
+ if (pcibios_present())
return 0;
#endif
@@ -2444,7 +2244,6 @@ __initfunc(int zs_init(void))
serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
serial_driver.subtype = SERIAL_TYPE_NORMAL;
serial_driver.init_termios = tty_std_termios;
-
serial_driver.init_termios.c_cflag =
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver.flags = TTY_DRIVER_REAL_RAW;
@@ -2472,8 +2271,6 @@ __initfunc(int zs_init(void))
serial_driver.read_proc = 0;
serial_driver.proc_entry = 0;
- init_zscons_termios(&serial_driver.init_termios);
-
/*
* The callout device is just like normal device except for
* major number and the subtype code.
@@ -2487,48 +2284,11 @@ __initfunc(int zs_init(void))
panic("Couldn't register serial driver\n");
if (tty_register_driver(&callout_driver))
panic("Couldn't register callout driver\n");
-
- save_flags(flags); cli();
- /* Set up our interrupt linked list */
- zs_chain = &zs_soft[0];
- for(channel = 0; channel < NUM_CHANNELS - 1; channel++)
- zs_soft[channel].zs_next = &zs_soft[channel + 1];
- zs_soft[channel + 1].zs_next = 0;
+ save_flags(flags); cli();
/* Initialize Softinfo */
- for(chip = 0; chip < NUM_SERIAL; chip++) {
- /* If we are doing kgdb over one of the channels on
- * chip zero, kgdb_channel will be set to 1 by the
- * zs_kgdb_hook() routine below.
- */
- if(!zs_chips[chip]) {
- zs_chips[chip] = get_zs(chip);
- /* Two channels per chip */
- zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
- zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
- zs_soft[(chip*2)].kgdb_channel = 0;
- zs_soft[(chip*2)+1].kgdb_channel = 0;
- }
-
- /* First, set up channel A on this chip. */
- channel = chip * 2;
- zs_soft[channel].zs_channel = zs_channels[channel];
- zs_soft[channel].change_needed = 0;
- zs_soft[channel].clk_divisor = 16;
- zs_soft[channel].cons_keyb = 0;
- zs_soft[channel].cons_mouse = 0;
- zs_soft[channel].channelA = 1;
-
- /* Now, channel B */
- channel++;
- zs_soft[channel].zs_channel = zs_channels[channel];
- zs_soft[channel].change_needed = 0;
- zs_soft[channel].clk_divisor = 16;
- zs_soft[channel].cons_keyb = 0;
- zs_soft[channel].cons_mouse = 0;
- zs_soft[channel].channelA = 0;
- }
+ zs_prepare();
/* Initialize Hardware */
for(channel = 0; channel < NUM_CHANNELS; channel++) {
@@ -2719,50 +2479,13 @@ __initfunc(int zs_init(void))
return 0;
}
-/* Hooks for running a serial console. con_init() calls this if the
- * console is being run over one of the ttya/ttyb serial ports.
- * 'chip' should be zero, as chip 1 drives the mouse/keyboard.
- * 'channel' is decoded as 0=TTYA 1=TTYB, note that the channels
- * are addressed backwards, channel B is first, then channel A.
- */
-void
-zs_cons_hook(int chip, int out, int line)
-{
- int channel;
-
-#ifdef CONFIG_PCI
- if (prom_searchsiblings(prom_getchild(prom_root_node), "pci"))
- return;
-#endif
-
- if(chip)
- panic("zs_cons_hook called with chip not zero");
- if(line != 1 && line != 2)
- panic("zs_cons_hook called with line not ttya or ttyb");
- channel = line - 1;
- if(!zs_chips[chip]) {
- zs_chips[chip] = get_zs(chip);
- /* Two channels per chip */
- zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
- zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
- }
- zs_soft[channel].zs_channel = zs_channels[channel];
- zs_soft[channel].change_needed = 0;
- zs_soft[channel].clk_divisor = 16;
- if(out)
- zs_cons_chanout = ((chip * 2) + channel);
- else
- zs_cons_chanin = ((chip * 2) + channel);
- zs_cons_check(&zs_soft[channel], channel);
-}
-
/* This is called at boot time to prime the kgdb serial debugging
* serial line. The 'tty_num' argument is 0 for /dev/ttya and 1
* for /dev/ttyb which is determined in setup_arch() from the
* boot command line flags.
*/
-void
-zs_kgdb_hook(int tty_num)
+__initfunc(static void
+zs_kgdb_hook(int tty_num))
{
int chip = 0;
@@ -2784,3 +2507,183 @@ zs_kgdb_hook(int tty_num)
ZS_CLEARERR(zs_kgdbchan);
ZS_CLEARFIFO(zs_kgdbchan);
}
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/* This is for console output over ttya/ttyb */
+static void
+zs_console_putchar(struct sun_serial *info, char ch)
+{
+ unsigned long flags;
+
+ if(!info->zs_channel)
+ return;
+
+ save_flags(flags); cli();
+ zs_put_char(info->zs_channel, ch);
+ restore_flags(flags);
+}
+
+/*
+ * Fair output driver allows a process to speak.
+ */
+static void zs_fair_output(struct sun_serial *info)
+{
+ int left; /* Output no more than that */
+ unsigned long flags;
+ char c;
+
+ if (info == 0) return;
+ if (info->xmit_buf == 0) return;
+
+ save_flags(flags); cli();
+ left = info->xmit_cnt;
+ while (left != 0) {
+ c = info->xmit_buf[info->xmit_tail];
+ info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt--;
+ restore_flags(flags);
+
+ zs_console_putchar(info, c);
+
+ cli();
+ left = MIN(info->xmit_cnt, left-1);
+ }
+
+ /* Last character is being transmitted now (hopefully). */
+ info->zs_channel->control = RES_Tx_P;
+ udelay(5);
+
+ restore_flags(flags);
+ return;
+}
+
+/*
+ * zs_console_write is registered for printk.
+ */
+static void
+zs_console_write(struct console *con, const char *s, unsigned count)
+{
+ struct sun_serial *info;
+ int i;
+
+ info = zs_soft + con->index;
+
+ for (i = 0; i < count; i++, s++) {
+ if(*s == '\n')
+ zs_console_putchar(info, '\r');
+ zs_console_putchar(info, *s);
+ }
+
+ /* Comment this if you want to have a strict interrupt-driven output */
+ zs_fair_output(info);
+}
+
+static int
+zs_console_wait_key(struct console *con)
+{
+ sleep_on(&keypress_wait);
+ return 0;
+}
+
+static kdev_t zs_console_device(struct console *con)
+{
+ return MKDEV(TTY_MAJOR, 64 + con->index);
+}
+
+__initfunc(static int
+zs_console_setup(struct console *con, char *options))
+{
+ struct sun_serial *info;
+ int i, brg, baud;
+
+ info = zs_soft + con->index;
+ info->is_cons = 1;
+
+ printk("Console: ttyS%d (Zilog8530)\n", info->line);
+
+ sunserial_console_termios(con);
+
+ i = con->cflag & CBAUD;
+ if (con->cflag & CBAUDEX) {
+ i &= ~CBAUDEX;
+ con->cflag &= ~CBAUDEX;
+ }
+ baud = baud_table[i];
+ info->zs_baud = baud;
+
+ switch (con->cflag & CSIZE) {
+ case CS5:
+ zscons_regs[3] = Rx5 | RxENAB;
+ zscons_regs[5] = Tx5 | TxENAB;
+ info->parity_mask = 0x1f;
+ break;
+ case CS6:
+ zscons_regs[3] = Rx6 | RxENAB;
+ zscons_regs[5] = Tx6 | TxENAB;
+ info->parity_mask = 0x3f;
+ break;
+ case CS7:
+ zscons_regs[3] = Rx7 | RxENAB;
+ zscons_regs[5] = Tx7 | TxENAB;
+ info->parity_mask = 0x7f;
+ break;
+ default:
+ case CS8:
+ zscons_regs[3] = Rx8 | RxENAB;
+ zscons_regs[5] = Tx8 | TxENAB;
+ info->parity_mask = 0xff;
+ break;
+ }
+ zscons_regs[5] |= DTR;
+
+ if (con->cflag & PARENB)
+ zscons_regs[4] |= PAR_ENAB;
+ if (!(con->cflag & PARODD))
+ zscons_regs[4] |= PAR_EVEN;
+
+ if (con->cflag & CSTOPB)
+ zscons_regs[4] |= SB2;
+ else
+ zscons_regs[4] |= SB1;
+
+ brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor);
+ zscons_regs[12] = brg & 0xff;
+ zscons_regs[13] = (brg >> 8) & 0xff;
+
+ memcpy(info->curregs, zscons_regs, sizeof(zscons_regs));
+ load_zsregs(info, zscons_regs);
+
+ ZS_CLEARERR(info->zs_channel);
+ ZS_CLEARFIFO(info->zs_channel);
+ return 0;
+}
+
+static struct console zs_console = {
+ "ttyS",
+ zs_console_write,
+ NULL,
+ zs_console_device,
+ zs_console_wait_key,
+ NULL,
+ zs_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+__initfunc(static int
+zs_console_init(void))
+{
+ extern int con_is_present(void);
+
+ if (con_is_present())
+ return 0;
+
+ zs_console.index = serial_console - 1;
+ register_console(&zs_console);
+ return 0;
+}
+
+#endif /* CONFIG_SERIAL_CONSOLE */