summaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorAlex deVries <Alex.deVries@windriver.com>1999-01-27 04:50:27 +0000
committerAlex deVries <Alex.deVries@windriver.com>1999-01-27 04:50:27 +0000
commit6f8fbd8c4d4278453711319149ffffd3bf09df26 (patch)
treeb5e099c8147be763fa6a1172b0b9eb532fe3f305 /arch/mips
parentec64862792a20b0114c4cf556f270a49dec5dc7b (diff)
Ulf's HAL driver.
- Alex
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/config.in2
-rw-r--r--arch/mips/sgi/kernel/Makefile6
-rw-r--r--arch/mips/sgi/kernel/indy_pbus.c202
-rw-r--r--arch/mips/sgi/kernel/setup.c12
4 files changed, 217 insertions, 5 deletions
diff --git a/arch/mips/config.in b/arch/mips/config.in
index 6cb3e2a0b..8c66ff8c9 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -221,7 +221,7 @@ fi
endmenu
if [ "$CONFIG_SGI" = "y" ]; then
- source drivers/sgi/char/Config.in
+ source drivers/sgi/Config.in
fi
mainmenu_option next_comment
diff --git a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile
index 5234f8548..8c425912a 100644
--- a/arch/mips/sgi/kernel/Makefile
+++ b/arch/mips/sgi/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 1998/06/25 20:19:17 ralf Exp $
+# $Id: Makefile,v 1.4 1998/08/25 09:14:48 ralf Exp $
# Makefile for the SGI specific kernel interface routines
# under Linux.
#
@@ -13,8 +13,8 @@
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \
- indy_timer.o indyIRQ.o reset.o setup.o time.o
+OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o indy_pbus.o \
+ system.o indy_timer.o indyIRQ.o reset.o setup.o time.o
all: sgikern.a
diff --git a/arch/mips/sgi/kernel/indy_pbus.c b/arch/mips/sgi/kernel/indy_pbus.c
new file mode 100644
index 000000000..efa99a927
--- /dev/null
+++ b/arch/mips/sgi/kernel/indy_pbus.c
@@ -0,0 +1,202 @@
+/* $Id$
+ *
+ * indy_pbus.c: Routines for manipulation of the HPC PBUS DMA controller.
+ *
+ * Copyright (C) 1998 Ulf Carlsson
+ */
+
+#define PBUS_DMA_RAM 384 /* Bytes of PBUS DMA ram */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#include <asm/addrspace.h>
+#include <asm/sgihpc.h>
+#include <asm/indy_pbus.h>
+
+struct pbus_chan {
+ int lock;
+ const char *device_id;
+};
+
+static struct pbus_chan pbus_chan_busy[MAX_PBUS_CHANNELS] = {
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+};
+
+struct pbus_fifo {
+ struct pbus_fifo *next;
+
+ int channel;
+ int beg;
+ int size;
+};
+
+struct pbus_fifo pbus_fifo_busy = {
+ NULL,
+ -1,
+ 0,
+ 0
+};
+
+
+int sgipbus_get_list(char *buf)
+{
+ int i, len = 0;
+
+ for (i = 0 ; i < MAX_PBUS_CHANNELS ; i++) {
+ if (pbus_chan_busy[i].lock) {
+ len += sprintf(buf+len, "%2d: %s\n",
+ i, pbus_chan_busy[i].device_id);
+ }
+ }
+ return len;
+}
+
+int sgipbus_request(unsigned int channel, char *device_id)
+{
+ if (channel > MAX_PBUS_CHANNELS)
+ return -EINVAL;
+
+ if (xchg(&pbus_chan_busy[channel].lock, 1) != 0)
+ return -EBUSY;
+
+ pbus_chan_busy[channel].device_id = device_id;
+
+ /* old flag was 0, it's now 1 to indicate busy */
+ return 0;
+}
+
+static int sgipbus_fifo_alloc(unsigned int channel, int fifo_size)
+{
+ struct pbus_fifo *p, *tmp;
+ int beg;
+
+ if (!pbus_chan_busy[channel].lock)
+ return -EINVAL;
+
+ /* fifo_size is in 64 bit words */
+ if (fifo_size > PBUS_DMA_RAM / 8)
+ goto no_space;
+
+ for (p = &pbus_fifo_busy; p; p = p->next) {
+ int used = p->beg + p->size;
+ if (PBUS_DMA_RAM / 8 - used > fifo_size) {
+ if (p->next && p->next->beg - used <= fifo_size)
+ continue;
+
+ beg = used + 1;
+ goto found_space;
+ }
+ }
+
+no_space:
+
+ printk("No memory left for PBUS device %s\n",
+ pbus_chan_busy[channel].device_id);
+ return -EBUSY;
+
+found_space:
+ tmp = p->next;
+ p->next = (struct pbus_fifo *)
+ kmalloc(sizeof(struct pbus_fifo), GFP_KERNEL);
+ if (!p->next)
+ return -ENOMEM;
+
+ p->next->next = tmp;
+
+ p = p->next;
+ p->beg = beg;
+ p->size = fifo_size;
+ p->channel = channel;
+
+ return p->beg;
+}
+
+static void sgipbus_fifo_free(unsigned int channel)
+{
+ struct pbus_fifo *p, *tmp;
+
+ for (p = &pbus_fifo_busy ; p->next ; p = p->next) {
+ if (p->next->channel == channel)
+ goto out;
+ }
+
+ return; /* nothing to free? */
+out:
+ tmp = p->next;
+ p->next = p->next->next;
+ kfree(tmp);
+}
+
+/*
+ * Setup the pbus channel
+ * fifo_size in doublewords (64 bit) , highwater in halfwords (16 bit)
+ */
+int sgipbus_setup(unsigned int channel, int fifo_size,
+ unsigned long highwater, unsigned long flags,
+ unsigned long dmacfg)
+{
+ struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0;
+ unsigned int fifobeg, fifoend;
+ int ret;
+
+ ret = sgipbus_fifo_alloc(channel, fifo_size);
+ if (ret < 0)
+ return ret;
+ fifobeg = ret;
+ fifoend = fifobeg + fifo_size - 1;
+
+ pbus[channel].pbdma_ctrl = (highwater << 8) | (fifobeg << 16) |
+ (fifoend << 24) | flags;
+
+ return 0;
+}
+
+void sgipbus_free(unsigned int channel)
+{
+ if (channel > MAX_PBUS_CHANNELS) {
+ printk("Trying to free PBUS %d\n", channel);
+ return;
+ }
+
+ if (xchg(&pbus_chan_busy[channel].lock, 0) == 0) {
+ printk("Trying to free free PBUS %d\n", channel);
+ return;
+ }
+
+ sgipbus_fifo_free(channel);
+}
+
+/* enable/disable a specific PBUS dma channel */
+__inline__ void sgipbus_enable(unsigned int channel, unsigned long desc)
+{
+ struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0;
+
+ pbus[channel].pbdma_dptr = desc;
+ pbus[channel].pbdma_ctrl |= HPC3_PDMACTRL_ACT;
+}
+
+__inline__ void sgipbus_disable(unsigned int channel)
+{
+ struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0;
+
+ pbus[channel].pbdma_ctrl &= ~HPC3_PDMACTRL_ACT;
+}
+
+__inline__ int sgipbus_interrupted(unsigned int channel)
+{
+ struct hpc3_pbus_dmacregs *pbus = &hpc3c0->pbdma0;
+
+ /* When we read pbdma_ctrl, bit 0 indicates interrupt signal.
+ * The interrupt signal is also cleared after read
+ */
+
+ return (pbus[channel].pbdma_ctrl & 0x01);
+}
diff --git a/arch/mips/sgi/kernel/setup.c b/arch/mips/sgi/kernel/setup.c
index dd1a67bfd..a1f7a2510 100644
--- a/arch/mips/sgi/kernel/setup.c
+++ b/arch/mips/sgi/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.16 1998/10/02 22:06:11 tsbogend Exp $
+/* $Id: setup.c,v 1.17 1999/01/04 16:03:57 ralf Exp $
*
* setup.c: SGI specific setup, including init of the feature struct.
*
@@ -34,6 +34,12 @@ void indy_reboot_setup(void);
#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
+
+#ifdef CONFIG_SGI_HAL2
+extern void sgiaudio_init(void);
+#endif
+
+
static void sgi_request_region(void)
{
/* No I/O ports are being used on the Indy. */
@@ -152,4 +158,8 @@ __initfunc(void sgi_setup(void))
#ifdef CONFIG_PSMOUSE
aux_device_present = 0xaa;
#endif
+
+#ifdef CONFIG_SGI_HAL2
+ sgiaudio_init();
+#endif
}