Files
Arquivotheca.SunOS-4.1.4/sys/sbusdev/dmaga.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

236 lines
4.6 KiB
C

#ident "@(#)dmaga.c 1.1"
/* @(#)dmaga.c 1.1 94/10/31 SMI */
/*
* Copyright (c) 1988, 1989, 1990 by Sun Microsystems, Inc.
*/
#include "dma.h"
#if NDMA > 0
/*
* Sbus DMA gate array 'driver'
*/
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/debug.h>
#include <sundev/mbvar.h>
#include <sun/autoconf.h>
#include <sbusdev/dmaga.h>
#include <machine/mmu.h>
static int dmaintr();
int ndma_map = 0;
struct dma_map {
struct dmaga *regs;
int bustype;
addr_t addr;
char free;
} *dma_map;
static int dmaidentify(), dmaattach();
struct dev_ops dma_ops = {
1,
dmaidentify,
dmaattach
};
#ifdef GASP
/*
* This code for GASP cards (that have no prom)
*/
/*
* GASP cards can be in slot 1, slot 1 + 0x1000000,
* slot 2, slot 2 + 0x2000000
*/
int gasp_cards = 0;
#define GASP_OFFSET 0x1000000
u_long gasp_addrs[4] = {
SBUS_BASE+SBUS_SIZE,
SBUS_BASE+SBUS_SIZE+GASP_OFFSET,
SBUS_BASE+(SBUS_SIZE<<1),
SBUS_BASE+(SBUS_SIZE<<1)+GASP_OFFSET
};
#include <machine/pte.h>
#define DMA_OFFSET 0x400000
#define Dma_addr(card) (gasp_addrs[(card)] + DMA_OFFSET)
static void
new_dma(prev, gaddr)
struct dev_info *prev;
u_long gaddr;
{
struct dev_info *dev;
auto long tmp;
dev = (struct dev_info *) kmem_zalloc (sizeof (*dev));
dev->devi_parent = prev->devi_parent;
dev->devi_next = prev->devi_next;
prev->devi_next = dev;
dev->devi_name = prev->devi_name;
dev->devi_nreg = 1;
dev->devi_reg = (struct dev_reg *)
kmem_zalloc(sizeof (struct dev_reg));
dev->devi_reg->reg_bustype = OBIO;
dev->devi_reg->reg_addr = (addr_t) gaddr;
dev->devi_reg->reg_size = sizeof (struct dmaga);
dev->devi_driver = &dma_ops;
dev->devi_nodeid = prev->devi_nodeid; /* lies. all lies */
#if defined(DEVINFO_DEBUG)
printf("new_dma() constructed a devinfo node\n");
#endif
ndma_map += 1;
}
#endif GASP
static int
dmaidentify(name)
char *name;
{
if (strcmp(name, "dma") == 0) {
ndma_map++;
return (1);
} else
return (0);
}
/*
*
*/
static int
dmaattach(dev)
register struct dev_info *dev;
{
register struct dma_map *dp;
static char unit_no = 0;
#ifdef GASP
if (unit_no == 0) {
register card;
struct dev_info *tmp = dev;
for (card = 0; card < 4; card++) {
if (gasp_cards & (1<<card)) {
new_dma(tmp, Dma_addr(card));
tmp = tmp->devi_next;
}
}
}
#endif GASP
if (!dma_map) {
dma_map = (struct dma_map *)
kmem_alloc((u_int) (sizeof (struct dma_map) * ndma_map));
if (!dma_map) {
printf("dma%d: No space for dma_map structure\n",
dev->devi_unit);
return (-1);
}
}
if ((dev->devi_unit = unit_no++) >= ndma_map) {
printf("dma%d: bad unit number\n", dev->devi_unit);
return (-1);
} else
dp = &dma_map[dev->devi_unit];
if (dev->devi_nreg > 1) {
printf("dma%d: bad register specification\n", dev->devi_unit);
return (-1);
}
/* map in the device registers */
dp->regs = (struct dmaga *)
map_regs(dev->devi_reg->reg_addr, dev->devi_reg->reg_size,
dev->devi_reg->reg_bustype);
if (dp->regs == (struct dmaga *) 0) {
printf("dma%d: unable to map registers\n", dev->devi_unit);
return (-1);
}
dp->bustype = dev->devi_reg->reg_bustype;
dp->addr = dev->devi_reg->reg_addr;
dp->free = 1;
if (dev->devi_nintr) {
addintr(dev->devi_intr->int_pri, dmaintr,
dev->devi_name, dev->devi_unit);
}
report_dev(dev);
attach_devs(dev);
#ifdef GASP
if (dev->devi_unit == 0 && ndma_map > 1) {
int slot;
for (slot = 1; slot < ndma_map; slot++) {
dev = dev->devi_next;
(void) dmaattach(dev);
}
}
#endif GASP
return (0);
}
#ifdef SBUS_SIZE
/*
* If SBUS_SIZE is provided, then we just consider the PArange as
* divided up into hunks the size of the S-Bus, and this macro returns
* which one it is. It may not really correspond to the slot, but is
* OK for use in dma_alloc. Otherwise, a function sbusslot() must be
* available that gives the slot number from the low 32 bits of the
* paddr.
*/
#define sbusslot(pa) (((int)(pa))/SBUS_SIZE)
#endif
struct dmaga *
dma_alloc(bustype, addr)
register int bustype;
register addr_t addr;
{
register i;
register struct dma_map *dp = dma_map;
for (i = 0; i < ndma_map; i++) {
if ((dp->free && (dp->bustype == bustype)) &&
(sbusslot((unsigned) dp->addr) == sbusslot((unsigned) addr))) {
dp->free = 0;
return (dp->regs);
}
dp++;
}
return ((struct dmaga *) 0);
}
void
dma_free(regs)
struct dmaga *regs;
{
register i;
register struct dma_map *dp = dma_map;
for (i = 0; i < ndma_map; i++) {
if (!(dp->free) && dp->regs == regs) {
dp->free = 1;
break;
}
dp++;
}
}
static int
dmaintr()
{
return (0);
}
#endif NDMA > 0