Allow multiple interrupt handler on same interrupt event.

Clear interrupt mask for specified interrupt in apbus_intr_establish().
Add dma stuff; define apbus_dmamap_sync() to flush DMA write cache by
accessing the corresponding I/O port.
This commit is contained in:
onoe 2000-10-12 03:11:38 +00:00
parent de22372491
commit 655ba83924
1 changed files with 87 additions and 32 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: apbus.c,v 1.2 1999/12/23 06:52:30 tsubai Exp $ */
/* $NetBSD: apbus.c,v 1.3 2000/10/12 03:11:38 onoe Exp $ */
/*-
* Copyright (C) 1999 SHIMIZU Ryo. All rights reserved.
@ -28,10 +28,13 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <machine/adrsmap.h>
#include <machine/autoconf.h>
#define _NEWSMIPS_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <newsmips/apbus/apbusvar.h>
static int apbusmatch __P((struct device *, struct cfdata *, void *));
@ -52,19 +55,18 @@ struct cfattach ap_ca = {
#define APBUS_DEVNAMELEN 16
struct ap_intrhand {
struct ap_intrhand *ai_next;
int ai_mask;
int ai_priority;
void (*ai_func) __P((void*)); /* function */
int (*ai_func) __P((void*)); /* function */
void *ai_aux; /* softc */
char ai_name[APBUS_DEVNAMELEN];
int ai_ctlno;
};
#define NLEVEL 2
#define NBIT 16
#define LEVELxBIT(l,b) (((l)*NBIT)+(b))
static struct ap_intrhand apintr[NLEVEL*NBIT];
static struct ap_intrhand *apintr[NLEVEL];
static int
apbusmatch(parent, cfdata, aux)
@ -181,16 +183,13 @@ apbus_intr_call(level, stat)
int level;
int stat;
{
int i;
int nintr = 0;
struct ap_intrhand *aip = &apintr[LEVELxBIT(level,0)];
struct ap_intrhand *ai;
for(i = 0; i < NBIT; i++) {
if (aip->ai_mask & stat) {
(*aip->ai_func)(aip->ai_aux);
nintr++;
for (ai = apintr[level]; ai != NULL; ai = ai->ai_next) {
if (ai->ai_mask & stat) {
nintr += (*ai->ai_func)(ai->ai_aux);
}
aip++;
}
return nintr;
}
@ -203,32 +202,88 @@ apbus_intr_establish(level, mask, priority, func, aux, name, ctlno)
int level;
int mask;
int priority;
void (*func) __P((void *));
int (*func) __P((void *));
void *aux;
char *name;
int ctlno;
{
int i;
int nbit = -1;
struct ap_intrhand *aip;
struct ap_intrhand *ai, **aip;
volatile unsigned int *inten0 = (volatile unsigned int *)NEWS5000_INTEN0;
volatile unsigned int *inten1 = (volatile unsigned int *)NEWS5000_INTEN1;
for (i = 0; i < NBIT; i++) {
if (mask & (1 << i)) {
nbit = i;
ai = malloc(sizeof(*ai), M_DEVBUF, M_NOWAIT);
if (ai == NULL)
panic("apbus_intr_establish: can't malloc handler info");
ai->ai_mask = mask;
ai->ai_priority = priority;
ai->ai_func = func;
ai->ai_aux = aux;
strncpy(ai->ai_name, name, APBUS_DEVNAMELEN-1);
ai->ai_ctlno = ctlno;
for (aip = &apintr[level]; *aip != NULL; aip = &(*aip)->ai_next) {
if ((*aip)->ai_priority < priority)
break;
}
}
ai->ai_next = *aip;
*aip = ai;
switch (level) {
case 0:
*inten0 |= mask;
break;
case 1:
*inten1 |= mask;
break;
}
if (nbit == -1)
panic("apbus_intr_establish");
aip = &apintr[LEVELxBIT(level,nbit)];
aip->ai_mask = 1 << nbit;
aip->ai_priority = priority;
aip->ai_func = func;
aip->ai_aux = aux;
strncpy(aip->ai_name, name, APBUS_DEVNAMELEN-1);
aip->ai_ctlno = ctlno;
return (void *)aip;
return (void *)ai;
}
void
apbus_dmamap_sync(t, map, offset, len, ops)
bus_dma_tag_t t;
bus_dmamap_t map;
bus_addr_t offset;
bus_size_t len;
int ops;
{
/*
* Flush DMA cache by issueing IO read for the AProm of specified slot.
*/
bus_space_read_4(t->_slotbaset, t->_slotbaseh, 0);
_bus_dmamap_sync(t, map, offset, len, ops);
}
struct newsmips_bus_dma_tag apbus_dma_tag = {
_bus_dmamap_create,
_bus_dmamap_destroy,
_bus_dmamap_load,
_bus_dmamap_load_mbuf,
_bus_dmamap_load_uio,
_bus_dmamap_load_raw,
_bus_dmamap_unload,
apbus_dmamap_sync,
_bus_dmamem_alloc,
_bus_dmamem_free,
_bus_dmamem_map,
_bus_dmamem_unmap,
_bus_dmamem_mmap,
};
struct newsmips_bus_dma_tag *
apbus_dmatag_init(apa)
struct apbus_attach_args *apa;
{
struct newsmips_bus_dma_tag *dmat;
dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
if (dmat != NULL) {
memcpy(dmat, &apbus_dma_tag, sizeof(*dmat));
dmat->_slotno = apa->apa_slotno;
dmat->_slotbaset = 0;
dmat->_slotbaseh = apa->apa_hwbase;
}
return dmat;
}