diff options
author | Alex deVries <Alex.deVries@windriver.com> | 1999-01-27 04:50:27 +0000 |
---|---|---|
committer | Alex deVries <Alex.deVries@windriver.com> | 1999-01-27 04:50:27 +0000 |
commit | 6f8fbd8c4d4278453711319149ffffd3bf09df26 (patch) | |
tree | b5e099c8147be763fa6a1172b0b9eb532fe3f305 /arch/mips | |
parent | ec64862792a20b0114c4cf556f270a49dec5dc7b (diff) |
Ulf's HAL driver.
- Alex
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/config.in | 2 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/Makefile | 6 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/indy_pbus.c | 202 | ||||
-rw-r--r-- | arch/mips/sgi/kernel/setup.c | 12 |
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 } |