#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 #include #include #include #include #include #include #include #include #include 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 #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<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