Add ISA support needed for Shark and the CATS board (CATS isa_machdep not

here yet).
This commit is contained in:
tv 1998-06-08 17:49:42 +00:00
parent 636443752e
commit ee69a0b0a0
17 changed files with 9940 additions and 0 deletions

676
sys/arch/arm32/isa/clock.c Normal file
View File

@ -0,0 +1,676 @@
/* $NetBSD: clock.c,v 1.1 1998/06/08 17:49:42 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*-
* Copyright (c) 1993, 1994 Charles Hannum.
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz and Don Ahn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)clock.c 7.2 (Berkeley) 5/12/91
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appears in all
copies and that both the copyright notice and this permission notice
appear in supporting documentation, and that the name of Intel
not be used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Primitive clock interrupt routines.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <machine/cpu.h>
#include <machine/irqhandler.h>
#include <machine/pio.h>
#include <machine/cpufunc.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <dev/ic/mc146818reg.h>
#include <arm32/isa/isa_machdep.h>
#include <arm32/isa/nvram.h>
#include <arm32/isa/timerreg.h>
#include <arm32/isa/spkrreg.h>
#ifdef SHARK
#include <arm32/shark/hat.h>
#endif
void sysbeepstop __P((void *));
void sysbeep __P((int, int));
void rtcinit __P((void));
int timer_hz_to_count(int);
static void findcpuspeed __P((void));
static void init_isa_timer_tables();
static void delayloop(int);
static int clockintr __P((void *));
static int gettick __P((void));
__inline u_int mc146818_read __P((void *, u_int));
__inline void mc146818_write __P((void *, u_int, u_int));
#define SECMIN ((unsigned)60) /* seconds per minute */
#define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */
#define SECDAY ((unsigned)(24*SECHOUR)) /* seconds per day */
#define SECYR ((unsigned)(365*SECDAY)) /* seconds per common year */
__inline u_int
mc146818_read(sc, reg)
void *sc; /* XXX use it? */
u_int reg;
{
outb(IO_RTC, reg);
return (inb(IO_RTC+1));
}
__inline void
mc146818_write(sc, reg, datum)
void *sc; /* XXX use it? */
u_int reg, datum;
{
outb(IO_RTC, reg);
outb(IO_RTC+1, datum);
}
unsigned int count1024usec; /* calibrated loop variable (1024 microseconds) */
/* number of timer ticks in a Musec = 2^20 usecs */
#define TIMER_MUSECFREQ\
(((((((TIMER_FREQ) * 1024) + 999) / 1000) * 1024) + 999) / 1000)
#define TIMER_MUSECDIV(x) ((TIMER_MUSECFREQ+(x)/2)/(x))
/*
* microtime() makes use of the following globals.
* timer_msb_table[] and timer_lsb_table[] are used to compute the
* microsecond increment.
*
* time.tv_usec += isa_timer_msb_table[cnt_msb] + isa_timer_lsb_table[cnt_lsb];
*/
u_short isa_timer_msb_table[256]; /* timer->usec MSB */
u_short isa_timer_lsb_table[256]; /* timer->usec conversion for LSB */
/* 64 bit counts from timer 0 */
struct count64 {
unsigned lo; /* low 32 bits */
unsigned hi; /* high 32 bits */
};
#define TIMER0_ROLLOVER 0xFFFF /* maximum rollover for 8254 counter */
struct count64 timer0count;
struct count64 timer0_at_last_clockintr;
unsigned timer0last;
/*#define TESTHAT*/
#ifdef TESTHAT
#define HATSTACKSIZE 1024
#define HATHZ 50000
#define HATHZ2 10000
unsigned char hatStack[HATSTACKSIZE];
unsigned testHatOn = 0;
unsigned nHats = 0;
unsigned nHatWedges = 0;
unsigned fiqReason = 0;
unsigned hatCount = 0;
unsigned hatCount2 = 0;
void hatTest(int testReason)
{
fiqReason |= testReason;
nHats++;
}
void hatWedge(int nFIQs)
{
printf("Unwedging the HAT. fiqs_happened = %d\n", nFIQs);
nHatWedges++;
}
#endif
void
startrtclock()
{
findcpuspeed(); /* use the clock (while it's free)
to find the cpu speed */
init_isa_timer_tables();
timer0count.lo = 0;
timer0count.hi = 0;
timer0_at_last_clockintr.lo = 0;
timer0_at_last_clockintr.hi = 0;
timer0last = 0;
/* initialize 8253 clock */
outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
outb(TIMER_CNTR0, TIMER0_ROLLOVER % 256);
outb(TIMER_CNTR0, TIMER0_ROLLOVER / 256);
#ifdef TESTHAT
hatCount = timer_hz_to_count(HATHZ);
hatCount2 = timer_hz_to_count(HATHZ2);
printf("HAT test on @ %d Hz = %d ticks\n", HATHZ, hatCount);
#endif
}
static void
init_isa_timer_tables()
{
int s;
u_long t, msbmillion, quotient, remainder;
for (s = 0; s < 256; s++) {
/* LSB table is easy, just divide and round */
t = ((u_long) s * 1000000 * 2) / TIMER_FREQ;
isa_timer_lsb_table[s] = (u_short) ((t / 2) + (t & 0x1));
msbmillion = s * 1000000;
quotient = msbmillion / TIMER_FREQ;
remainder = msbmillion % TIMER_FREQ;
t = (remainder * 256 * 2) / TIMER_FREQ;
isa_timer_msb_table[s] =
(u_short)((t / 2) + (t & 1) + (quotient * 256));
#ifdef DIAGNOSTIC
if ((s > 0) &&
(isa_timer_msb_table[s] <
(isa_timer_msb_table[s - 1] + isa_timer_lsb_table[0xFF])))
panic ("time tables not monotonic %d: %d < (%d + %d) = %d\n",
s, isa_timer_msb_table[s],
isa_timer_msb_table[s - 1],
isa_timer_lsb_table[0xFF],
isa_timer_msb_table[s - 1] +
isa_timer_lsb_table[0xFF]);
#endif
} /* END for */
}
int
timer_hz_to_count(timer_hz)
int timer_hz;
{
u_long tval;
tval = (TIMER_FREQ * 2) / (u_long) timer_hz;
tval = (tval / 2) + (tval & 0x1);
return (int)tval;
}
/* must be called at SPL_CLOCK or higher */
void gettimer0count(pcount)
struct count64 *pcount;
{
unsigned current, ticks, oldlo;
/*
* Latch the current value of the timer and then read it.
* This guarentees an atomic reading of the time.
*/
current = gettick();
if (timer0last >= current)
ticks = timer0last - current;
else
ticks = timer0last + (TIMER0_ROLLOVER - current);
timer0last = current;
oldlo = timer0count.lo;
if (oldlo > (timer0count.lo = oldlo + ticks)) /* carry? */
timer0count.hi++;
*pcount = timer0count;
}
static int
clockintr(arg)
void *arg;
{
struct clockframe *frame = arg; /* not strictly necessary */
extern void isa_specific_eoi(int irq);
#ifdef TESTHAT
static int ticks = 0;
#endif
#ifdef SHARK
static int hatUnwedgeCtr = 0;
#endif
gettimer0count(&timer0_at_last_clockintr);
mc146818_read(NULL, MC_REGC); /* clear the clock interrupt */
#ifdef SHARK
/* check to see if the high-availability timer needs to be unwedged */
if (++hatUnwedgeCtr >= (hz / HAT_MIN_FREQ)) {
hatUnwedgeCtr = 0;
hatUnwedge();
}
#endif
#ifdef TESTHAT
++ticks;
if (testHatOn && ((ticks & 0x3f) == 0)) {
if (testHatOn == 1) {
hatClkAdjust(hatCount2);
testHatOn = 2;
} else {
testHatOn = 0;
hatClkOff();
printf("hat off status: %d %d %x\n", nHats, nHatWedges, fiqReason);
}
} else if (!testHatOn && (ticks & 0x1ff) == 0) {
printf("hat on status: %d %d %x\n", nHats, nHatWedges, fiqReason);
testHatOn = 1;
nHats = 0;
fiqReason = 0;
hatClkOn(hatCount, hatTest, 0xfeedface,
hatStack + HATSTACKSIZE - sizeof(unsigned),
hatWedge);
}
#endif
hardclock(frame);
return(0);
}
static int
gettick()
{
u_char lo, hi;
u_int savedints;
/* Don't want someone screwing with the counter while we're here. */
savedints = disable_interrupts(I32_bit);
/* Select counter 0 and latch it. */
outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
lo = inb(TIMER_CNTR0);
hi = inb(TIMER_CNTR0);
restore_interrupts(savedints);
return ((hi << 8) | lo);
}
/* modifications from i386 to arm32 isa version:
- removed hardcoded "n -=" values that approximated the time to
calculate delay ticks
- made the time to calculate delay ticks almost negligable. 4 multiplies
= maximum of 12 cycles = 75ns on a slow SA-110, plus a bunch of shifts;
as opposed to 4 multiplies plus a bunch of divides.
- removed i386 assembly language hack
- put code in findcpuspeed that works even if FIRST_GUESS is orders
of magnitude low
- put code in delay() to use delayloop() for short delays
- microtime no longer in assembly language
*/
/*
* Wait "n" microseconds.
* Relies on timer 1 counting down from (TIMER_FREQ / hz) at TIMER_FREQ Hz.
* Note: timer had better have been programmed before this is first used!
* (Note that we use `rate generator' mode, which counts at 1:1; `square
* wave' mode counts at 2:1).
*/
void
delay(n)
unsigned n;
{
int tick, otick;
int nticks;
if (n < 100) {
/* it can take a long time (1 usec or longer) just for 1 ISA read,
so it's best not to use the timer for short delays */
delayloop((n * count1024usec) >> 10);
return;
}
/*
* Read the counter first, so that the rest of the setup overhead is
* counted.
*/
otick = gettick();
/*
* Calculate ((n * TIMER_FREQ) / 1e6) without using floating point and
* without any avoidable overflows.
*/
{
/* a Musec = 2^20 usec */
int Musec = n >> 20,
usec = n & ((1 << 20) - 1);
nticks
= (Musec * TIMER_MUSECFREQ) +
(usec * (TIMER_MUSECFREQ >> 20)) +
((usec * ((TIMER_MUSECFREQ & ((1 <<20) - 1)) >>10)) >>10) +
((usec * (TIMER_MUSECFREQ & ((1 << 10) - 1))) >> 20);
}
while (nticks > 0) {
tick = gettick();
if (tick > otick)
nticks -= TIMER0_ROLLOVER - (tick - otick);
else
nticks -= otick - tick;
otick = tick;
}
}
void
sysbeepstop(arg)
void *arg;
{
}
void
sysbeep(pitch, period)
int pitch, period;
{
}
#define FIRST_GUESS 0x2000
static void
findcpuspeed()
{
int ticks;
unsigned int guess = FIRST_GUESS;
while (1) { /* loop until accurate enough */
/* Put counter in count down mode */
outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
outb(TIMER_CNTR0, 0xff);
outb(TIMER_CNTR0, 0xff);
delayloop(guess);
/* Read the value left in the counter */
/*
* Formula for delaycount is:
* (loopcount * timer clock speed) / (counter ticks * 1000)
*/
ticks = 0xFFFF - gettick();
if (ticks == 0) ticks = 1; /* just in case */
if (ticks < (TIMER_MUSECDIV(1024))) { /* not accurate enough */
guess *= max(2, (TIMER_MUSECDIV(1024) / ticks));
continue;
}
count1024usec = (guess * (TIMER_MUSECDIV(1024))) / ticks;
return;
}
}
static void
delayloop(counts)
{
while (counts--);
}
void
cpu_initclocks()
{
unsigned hzval;
printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz);
/* install RTC interrupt handler */
(void)isa_intr_establish(NULL, IRQ_RTC, IST_LEVEL, IPL_CLOCK,
clockintr, 0);
/* code for values of hz that don't divide 1000000 exactly */
tickfix = 1000000 - (hz * tick);
if (tickfix) {
int ftp;
ftp = min(ffs(tickfix), ffs(hz));
tickfix >>= (ftp - 1);
tickfixinterval = hz >> (ftp - 1);
}
/* set up periodic interrupt @ hz
this is the subset of hz values in kern_clock.c that are
supported by the ISA RTC */
switch (hz) {
case 64:
hzval = MC_RATE_64_Hz;
break;
case 128:
hzval = MC_RATE_128_Hz;
break;
case 256:
hzval = MC_RATE_256_Hz;
break;
case 1024:
hzval = MC_RATE_1024_Hz;
break;
default:
panic("cannot configure hz = %d\n", hz);
}
rtcinit(); /* make sure basics are done by now */
/* blast values to set up clock interrupt */
mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | hzval);
/* enable periodic interrupt */
mc146818_write(NULL, MC_REGB,
mc146818_read(NULL, MC_REGB) | MC_REGB_PIE);
}
void
rtcinit()
{
static int first_rtcopen_ever = 1;
if (!first_rtcopen_ever)
return;
first_rtcopen_ever = 0;
mc146818_write(NULL, MC_REGA, /* XXX softc */
MC_BASE_32_KHz | MC_RATE_1024_Hz);
mc146818_write(NULL, MC_REGB, MC_REGB_24HR); /* XXX softc */
}
void
setstatclockrate(arg)
int arg;
{
}
/*
* void microtime(struct timeval *tvp)
*
* Fill in the specified timeval struct with the current time
* accurate to the microsecond.
*/
void
microtime(tvp)
struct timeval *tvp;
{
int s;
unsigned lsb, msb;
int tm;
static struct timeval oldtv;
struct count64 timer0current;
int ticks;
s = splstatclock();
gettimer0count(&timer0current);
tm = time.tv_usec;
/* unsigned arithmetic should take care of overflow */
/* with a >= 32 Hz clock, ticks will always be < 0x7FFF */
ticks = (int)((unsigned)
(timer0current.lo - timer0_at_last_clockintr.lo));
#ifdef DIAGNOSTIC
if ((ticks < 0) || (ticks > 0xffff))
printf("microtime bug: ticks = %x\n", ticks);
#endif
while (ticks > 0) {
if (ticks < 0xffff) {
msb = (ticks >> 8) & 0xFF;
lsb = ticks & 0xFF;
} else {
msb = 0xff;
lsb = 0xff;
}
/* see comments above */
tm += isa_timer_msb_table[msb] + isa_timer_lsb_table[lsb];
/* for a 64 Hz RTC, ticks will never overflow table */
/* microtime will be less accurate if the RTC is < 36 Hz */
ticks -= 0xffff;
}
tvp->tv_sec = time.tv_sec;
if (tm > 1000000) {
tvp->tv_sec += 1;
tm -= 1000000;
}
tvp->tv_usec = tm;
/* Make sure the time has advanced. */
if (tvp->tv_sec == oldtv.tv_sec &&
tvp->tv_usec <= oldtv.tv_usec) {
tvp->tv_usec = oldtv.tv_usec + 1;
if (tvp->tv_usec > 1000000) {
tvp->tv_usec -= 1000000;
++tvp->tv_sec;
}
}
oldtv = *tvp;
(void)splx(s);
}
void
need_proftick(p)
struct proc *p;
{
}
/* End of clock.c */

2646
sys/arch/arm32/isa/ess.c Normal file

File diff suppressed because it is too large Load Diff

254
sys/arch/arm32/isa/essreg.h Normal file
View File

@ -0,0 +1,254 @@
/* $NetBSD: essreg.h,v 1.1 1998/06/08 17:49:43 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
** @(#) $RCSfile: essreg.h,v $ $Revision: 1.1 $ (SHARK) $Date: 1998/06/08 17:49:43 $
**
**++
**
** essreg.h
**
** FACILITY:
**
** DIGITAL Network Appliance Reference Design (DNARD)
**
** MODULE DESCRIPTION:
**
** This module contains the constant definitions for the device
** registers on the ESS Technologies 1888/1887/888 sound chip.
**
** AUTHORS:
**
** Blair Fidler Software Engineering Australia
** Gold Coast, Australia.
**
** CREATION DATE:
**
** March 10, 1997.
**
** MODIFICATION HISTORY:
**
**--
*/
/*
* DSP commands. This unit handles MIDI and audio capabilities.
* The DSP can be reset, data/commands can be read or written to it,
* and it can generate interrupts. Interrupts are generated for MIDI
* input or DMA completion. They seem to have neglected the fact
* that it would be nice to have a MIDI transmission complete interrupt.
* Worse, the DMA engine is half-duplex. This means you need to do
* (timed) programmed I/O to be able to record and play simulataneously.
*/
#define ESS_ACMD_DAC8WRITE 0x10 /* direct-mode 8-bit DAC write */
#define ESS_ACMD_DAC16WRITE 0x11 /* direct-mode 16-bit DAC write */
#define ESS_ACMD_DMA8OUT 0x14 /* 8-bit linear DMA output */
#define ESS_ACMD_DMA16OUT 0x15 /* 16-bit linear DMA output */
#define ESS_ACMD_AUTODMA8OUT 0x1C /* auto-init 8-bit linear DMA output */
#define ESS_ACMD_AUTODMA16OUT 0x1D /* auto-init 16-bit linear DMA output */
#define ESS_ACMD_ADC8READ 0x20 /* direct-mode 8-bit ADC read */
#define ESS_ACMD_ADC16READ 0x21 /* direct-mode 16-bit ADC read */
#define ESS_ACMD_DMA8IN 0x24 /* 8-bit linear DMA input */
#define ESS_ACMD_DMA16IN 0x25 /* 16-bit linear DMA input */
#define ESS_ACMD_AUTODMA8IN 0x2C /* auto-init 8-bit linear DMA input */
#define ESS_ACMD_AUTODMA16IN 0x2D /* auto-init 16-bit linear DMA input */
#define ESS_ACMD_SETTIMECONST1 0x40 /* set time constant (1MHz base) */
#define ESS_ACMD_SETTIMECONST15 0x41 /* set time constant (1.5MHz base) */
#define ESS_ACMD_SETFILTER 0x42 /* set filter clock independently */
#define ESS_ACMD_BLOCKSIZE 0x48 /* set blk size for high speed xfer */
#define ESS_ACMD_DMA4OUT 0x74 /* 4-bit ADPCM DMA output */
#define ESS_ACMD_DMA4OUTREF 0x75 /* 4-bit ADPCM DMA output with ref */
#define ESS_ACMD_DMA2_6OUT 0x76 /* 2.6-bit ADPCM DMA output */
#define ESS_ACMD_DMA2_6OUTREF 0x77 /* 2.6-bit ADPCM DMA output with ref */
#define ESS_ACMD_DMA2OUT 0x7A /* 2-bit ADPCM DMA output */
#define ESS_ACMD_DMA2OUTREF 0x7B /* 2-bit ADPCM DMA output with ref */
#define ESS_ACMD_SILENCEOUT 0x80 /* output a block of silence */
#define ESS_ACMD_START_AUTO_OUT 0x90 /* start auto-init 8-bit DMA output */
#define ESS_ACMD_START_OUT 0x91 /* start 8-bit DMA output */
#define ESS_ACMD_START_AUTO_IN 0x98 /* start auto-init 8-bit DMA input */
#define ESS_ACMD_START_IN 0x99 /* start 8-bit DMA input */
#define ESS_XCMD_SAMPLE_RATE 0xA1 /* sample rate for Audio1 channel */
#define ESS_XCMD_FILTER_CLOCK 0xA2 /* filter clock for Audio1 channel*/
#define ESS_XCMD_XFER_COUNTLO 0xA4 /* */
#define ESS_XCMD_XFER_COUNTHI 0xA5 /* */
#define ESS_XCMD_AUDIO_CTRL 0xA8 /* */
#define ESS_AUDIO_CTRL_MONITOR 0x08
/* 0=disable/1=enable */
#define ESS_AUDIO_CTRL_MONO 0x02
/* 0=disable/1=enable */
#define ESS_AUDIO_CTRL_STEREO 0x01
/* 0=disable/1=enable */
#define ESS_XCMD_PREAMP_CTRL 0xA9 /* */
#define ESS_PREAMP_CTRL_ENABLE 0x04
#define ESS_XCMD_IRQ_CTRL 0xB1 /* legacy audio interrupt control */
#define ESS_XCMD_DRQ_CTRL 0xB2 /* audio DRQ control */
#define ESS_XCMD_VOLIN_CTRL 0xB4 /* stereo input volume control */
#define ESS_XCMD_AUDIO1_CTRL1 0xB7 /* */
#define ESS_AUDIO1_CTRL1_FIFO_SIGNED 0x20
/* 0=unsigned/1=signed */
#define ESS_AUDIO1_CTRL1_FIFO_SIZE 0x04
/* 0=8-bit/1=16-bit */
#define ESS_XCMD_AUDIO1_CTRL2 0xB8 /* */
#define ESS_AUDIO1_CTRL2_FIFO_ENABLE 0x01
/* 0=disable/1=enable */
#define ESS_AUDIO1_CTRL2_DMA_READ 0x02
/* 0=DMA write/1=DMA read */
#define ESS_AUDIO1_CTRL2_ADC_ENABLE 0x08
/* 0=DAC mode/1=ADC mode */
#define ESS_XCMD_DEMAND_CTRL 0xB9 /* */
#define ESS_ACMD_ENABLE_EXT 0xC6 /* enable ESS extension commands */
#define ESS_ACMD_DISABLE_EXT 0xC7 /* enable ESS extension commands */
#define ESS_ACMD_PAUSE_DMA 0xD0 /* pause DMA */
#define ESS_ACMD_ENABLE_SPKR 0xD1 /* enable Audio1 DAC input to mixer */
#define ESS_ACMD_DISABLE_SPKR 0xD3 /* disable Audio1 DAC input to mixer */
#define ESS_ACMD_CONT_DMA 0xD4 /* continue paused DMA */
#define ESS_ACMD_SPKR_STATUS 0xD8 /* return Audio1 DAC status: */
#define ESS_SPKR_OFF 0x00
#define ESS_SPKR_ON 0xFF
#define ESS_ACMD_VERSION 0xE1 /* get version number */
#define ESS_ACMD_LEGACY_ID 0xE7 /* get legacy ES688/ES1688 ID bytes */
/*
* Macros to detect valid hardware configuration data.
*/
#define ESS_IRQ1_VALID(irq, model) ((irq) == 5 || (irq) == 7 || (irq) == 9 || (irq) == 10 || ((model) == ESS_1887 && (irq) == 15))
#define ESS_IRQ2_VALID(irq, model) (((model) != ESS_1887) ? ((irq) == 15) : ((irq) == 5 || (irq) == 7 || (irq) == 9 || (irq) == 10) || (irq) == 15)
#define ESS_DRQ1_VALID(chan, model) ((chan) == 0 || (chan) == 1 || (chan) == 3 || ((model) == ESS_1887 && (chan) == 5))
#define ESS_DRQ2_VALID(chan, model) (((model) != ESS_1887) ? ((chan) == 5) : ((chan) == 0 || (chan) == 1 || (chan) == 3 || (chan) == 5))
#define ESS_BASE_VALID(base) ((base) == 0x220 || (base) == 0x230 || (base) == 0x240 || (base) == 0x250)
#define ESS_DMA_SIZE(chan) ((chan & 4) ? ESS_MODE_16BIT: ESS_MODE_8BIT)
/*
* Macros to manipulate gain values
*/
#define ESS_4BIT_GAIN(x) ((x) & 0xf0)
#define ESS_3BIT_GAIN(x) (((x) & 0xe0) >> 1)
#define ESS_STEREO_GAIN(l, r) ((l) | ((r) >> 4))
#define ESS_MONO_GAIN(x) ((x) >> 4)
#ifdef ESS_AMODE_LOW
/*
* Registers used to configure ESS chip via Read Key Sequence
*/
#define ESS_CONFIG_KEY_BASE 0x229
#define ESS_CONFIG_KEY_PORTS 3
#else
/*
* Registers used to configure ESS chip via System Control Register (SCR)
*/
#define ESS_SCR_ACCESS_BASE 0xF9
#define ESS_SCR_ACCESS_PORTS 3
#define ESS_SCR_LOCK 0
#define ESS_SCR_UNLOCK 2
#define ESS_SCR_BASE 0xE0
#define ESS_SCR_PORTS 2
#define ESS_SCR_INDEX 0
#define ESS_SCR_DATA 1
/*
* Bit definitions for SCR
*/
#define ESS_SCR_AUDIO_ENABLE 0x04
#define ESS_SCR_AUDIO_220 0x00
#define ESS_SCR_AUDIO_230 0x01
#define ESS_SCR_AUDIO_240 0x02
#define ESS_SCR_AUDIO_250 0x03
#endif
/*****************************************************************************/
/* DSP Timeout Definitions */
/*****************************************************************************/
#define ESS_RESET_TIMEOUT 5000 /* ??? */
#define ESS_READ_TIMEOUT 5000 /* number of times to try a read */
#define ESS_WRITE_TIMEOUT 5000 /* number of times to try a write */
#define ESS_NPORT 16
#define ESS_DSP_RESET 0x06
#define ESS_MAGIC 0xAA /* response to successful reset */
#define ESS_DSP_READ 0x0A
#define ESS_DSP_WRITE 0x0C
#define ESS_DSP_RW_STATUS 0x0C
#define ESS_CLEAR_INTR 0x0E
#define ESS_DSP_READ_STATUS 0x0C
#define ESS_DSP_READ_MASK 0x40
#define ESS_DSP_READ_READY 0x40
#define ESS_DSP_WRITE_STATUS 0x0C
#define ESS_DSP_WRITE_MASK 0x80
#define ESS_DSP_WRITE_READY 0x00
#define ESS_MIX_REG_SELECT 0x04
#define ESS_MIX_REG_DATA 0x05
#define ESS_MIX_RESET 0x00 /* mixer reset port and value */
/*
* ESS Mixer registers
*/
#define ESS_MREG_SAMPLE_RATE 0x70 /* sample rate for Audio2 channel */
#define ESS_MREG_FILTER_CLOCK 0x72 /* filter clock for Audio2 channel */
#define ESS_MREG_XFER_COUNTLO 0x74 /* low-byte of DMA transfer size */
#define ESS_MREG_XFER_COUNTHI 0x76 /* high-byte of DMA transfer size */
#define ESS_MREG_AUDIO2_CTRL1 0x78 /* control register 1 for Audio2: */
#define ESS_AUDIO2_CTRL1_XFER_SIZE 0x20
/* 0=8-bit/1=16-bit */
#define ESS_AUDIO2_CTRL1_FIFO_ENABLE 0x02
/* 0=disable/1=enable */
#define ESS_AUDIO2_CTRL1_DAC_ENABLE 0x01
/* 0=disable/1=enable */
#define ESS_MREG_AUDIO2_CTRL2 0x7A /* control register 2 for Audio2: */
#define ESS_AUDIO2_CTRL2_FIFO_SIZE 0x01
/* 0=8-bit/1=16-bit */
#define ESS_AUDIO2_CTRL2_CHANNELS 0x02
/* 0=mono/1=stereo */
#define ESS_AUDIO2_CTRL2_FIFO_SIGNED 0x04
/* 0=unsigned/1=signed */
#define ESS_AUDIO2_CTRL2_DMA_ENABLE 0x20
/* 0=disable/1=enable */

211
sys/arch/arm32/isa/essvar.h Normal file
View File

@ -0,0 +1,211 @@
/* $NetBSD: essvar.h,v 1.1 1998/06/08 17:49:43 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
** @(#) $RCSfile: essvar.h,v $ $Revision: 1.1 $ (SHARK) $Date: 1998/06/08 17:49:43 $
**
**++
**
** essvar.h
**
** FACILITY:
**
** DIGITAL Network Appliance Reference Design (DNARD)
**
** MODULE DESCRIPTION:
**
** This module contains the structure definitions and function
** prototypes for the ESS Technologies 1887/888 sound chip
** driver.
**
** AUTHORS:
**
** Blair Fidler Software Engineering Australia
** Gold Coast, Australia.
**
** CREATION DATE:
**
** May 12, 1997.
**
** MODIFICATION HISTORY:
**
**--
*/
#define ESS_DAC_PLAY_VOL 0
#define ESS_MIC_PLAY_VOL 1
#define ESS_LINE_PLAY_VOL 2
#define ESS_SYNTH_PLAY_VOL 3
#define ESS_CD_PLAY_VOL 4
#define ESS_AUXB_PLAY_VOL 5
#define ESS_INPUT_CLASS 6
#define ESS_MASTER_VOL 7
#define ESS_PCSPEAKER_VOL 8
#define ESS_OUTPUT_CLASS 9
#define ESS_DAC_REC_VOL 10
#define ESS_MIC_REC_VOL 11
#define ESS_LINE_REC_VOL 12
#define ESS_SYNTH_REC_VOL 13
#define ESS_CD_REC_VOL 14
#define ESS_AUXB_REC_VOL 15
#define ESS_MIC_PREAMP 16
#define ESS_RECORD_VOL 17
#define ESS_RECORD_SOURCE 18
#define ESS_RECORD_CLASS 19
#define ESS_RECORD_MONITOR 20
#define ESS_MONITOR_CLASS 21
#define ESS_NDEVS 22
struct ess_audio_channel
{
int drq; /* DMA channel */
int mode; /* DMA mode */
#define ESS_MODE_8BIT 0
#define ESS_MODE_16BIT 1
int irq; /* IRQ line for this DMA channel */
void *ih; /* interrupt vectoring */
u_long nintr; /* number of interrupts taken */
void (*intr)(void*); /* ISR for DMA complete */
void *arg; /* arg for intr() */
/* Status information */
int active; /* boolean: channel in use? */
int dmaflags; /* value last passed to isa_dmastart */
caddr_t dmaaddr; /* value last passed to isa_dmastart */
vm_size_t dmacnt; /* value last passed to isa_dmastart */
u_int rate; /* sample rate in Hz*/
u_int channels; /* 1:mono, 2:stereo */
u_int precision; /* size of each sample in bits */
u_int encoding; /* method used to encode samples */
};
struct ess_softc
{
/* REVISIT: currently the initial part of this is directly from sbdsp */
struct device sc_dev; /* base device */
struct isadev sc_id; /* ISA device */
isa_chipset_tag_t sc_ic;
bus_space_tag_t sc_iot; /* tag */
bus_space_handle_t sc_ioh; /* handle */
void *sc_ih; /* interrupt vectoring */
int sc_iobase; /* I/O port base address */
u_short sc_open; /* reference count of open calls */
u_char gain[ESS_NDEVS][2]; /* kept in input levels */
#define ESS_LEFT 0
#define ESS_RIGHT 1
u_int out_port; /* output port */
u_int in_mask; /* input ports */
u_int in_port; /* XXX needed for MI interface */
u_int spkr_state; /* non-null is on */
struct ess_audio_channel sc_in; /* audio channel for record */
struct ess_audio_channel sc_out;/* audio channel for playback */
void (*sc_mintr)(void*, int);/* midi input intr handler */
u_int sc_model;
#define ESS_UNSUPPORTED 0
#define ESS_1888 1
#define ESS_1887 2
#define ESS_888 3
u_int sc_version; /* Legacy ES688/ES1688 ID */
};
#ifdef _KERNEL
#ifdef __BROKEN_INDIRECT_CONFIG
int ess_probe __P((struct device *, void *, void *));
#else
int ess_probe __P((struct device *, struct cfdata *, void *));
#endif
void ess_attach __P((struct device *, struct device *, void *));
int ess_open __P((dev_t, int));
void ess_close __P((void *));
int ess_getdev __P((void *, struct audio_device *));
int ess_drain __P((void *));
int ess_query_encoding __P((void *, struct audio_encoding *));
int ess_set_params __P((void *, int, struct audio_params *, struct audio_params *));
int ess_set_in_sr __P((void *, u_long, int));
int ess_set_out_sr __P((void *, u_long, int));
int ess_set_in_precision __P((void *, u_int));
int ess_set_out_precision __P((void *, u_int));
int ess_set_in_channels __P((void *, int));
int ess_set_out_channels __P((void *, int));
int ess_round_blocksize __P((void *, int));
int ess_set_out_port __P((void *, int));
int ess_get_out_port __P((void *));
int ess_set_in_port __P((void *, int));
int ess_get_in_port __P((void *));
int ess_commit_settings __P((void *));
u_int ess_get_silence __P((int));
int ess_dma_output __P((void *, void *, int, void (*)(void *), void *));
int ess_dma_input __P((void *, void *, int, void (*)(void *), void *));
int ess_halt_output __P((void *));
int ess_halt_input __P((void *));
int ess_cont_output __P((void *));
int ess_cont_input __P((void *));
int ess_intr_output __P((void *));
int ess_intr_input __P((void *));
int ess_speaker_ctl __P((void *, int));
int ess_getdev __P((void *, struct audio_device *));
int ess_setfd __P((void *, int));
int ess_set_port __P((void *, mixer_ctrl_t *));
int ess_get_port __P((void *, mixer_ctrl_t *));
int ess_query_devinfo __P((void *, mixer_devinfo_t *));
#endif

71
sys/arch/arm32/isa/icu.h Normal file
View File

@ -0,0 +1,71 @@
/* $NetBSD: icu.h,v 1.1 1998/06/08 17:49:43 tv Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)icu.h 5.6 (Berkeley) 5/9/91
*/
/*
* AT/386 Interrupt Control constants
* W. Jolitz 8/89
*/
#ifndef _ARM32_ISA_ICU_H_
#define _ARM32_ISA_ICU_H_
#ifndef _LOCORE
/*
* Interrupt "level" mechanism variables, masks, and macros
*/
extern unsigned imen; /* interrupt mask enable */
#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IO_ICU2 + 1, imen >> 8))
#endif /* !_LOCORE */
/*
* Interrupt enable bits -- in order of priority
*/
#define IRQ_SLAVE 2
/*
* Interrupt Control offset into Interrupt descriptor table (IDT)
*/
#define ICU_OFFSET 32 /* 0-31 are processor exceptions */
#define ICU_LEN 16 /* 32-47 are ISA interrupts */
#endif /* !_ARM32_ISA_ICU_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,420 @@
/* $NetBSD: if_csvar.h,v 1.1 1998/06/08 17:49:43 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
**++
** FACILITY Crystal CS8900 Ethernet driver header file
**
** ABSTRACT
**
** This module provides CS8900 register defines in addition
** to defining the driver softc structure.
**
** AUTHORS
**
** Peter Dettori SEA - Software Engineering.
**
** CREATION DATE:
**
** 13-Feb-1997.
**
** MODIFICATION HISTORY:
**
**--
*/
#ifndef __IF_CSVAR_H__
#define __IF_CSVAR_H__
extern struct cfdriver cs_cd;
/* Individual Address (Ethernet Address) */
typedef struct
{
ushort word[3];
} ia, *pia;
/*
* Ethernet software status per interface.
*
* Each interface is referenced by a network interface structure,
* arpcom.ac_if, which the routing code uses to locate the interface.
* This structure contains the output queue for the interface,
* its address, ...
*/
struct cs_softc {
struct device sc_dev; /* base device glue */
struct ethercom sc_ethercom; /* Ethernet common */
void *sc_ih; /* interupt handler */
void *sc_sh; /* shutdown hook */
bus_space_tag_t sc_iot; /* bus space tag for IO */
bus_space_tag_t sc_memt; /* bus space tag for memory mode */
bus_space_handle_t sc_ioh; /* bus space handles */
bus_space_handle_t sc_memh;
ushort sc_iobase; /* base IO port address */
ushort sc_int; /* interrupt level */
int pPacketPagePhys; /* physical io address */
ushort mediaType; /* 10BaseT, thin wire */
ushort configFlags; /* chip configuration software flag */
int inMemoryMode; /* status */
int txInProgress; /* flags */
int resetting; /* chip in reset mode flag */
uint dmaMemSize; /* 16K or 64K if DMA being used */
char *dmaBase; /* DMA memory base */
char *dma_offset; /* offset into DMA space */
int sc_drq; /* DMA request channel : 5,6,7 */
int sc_xe_ent; /* current early-xmit table entry */
int sc_xe_togo; /* # of packets to go at this ent */
u_int8_t sc_enaddr[6]; /* MAC address */
};
/* Debug Status */
/*#define CS_DEBUG 0*/
#ifdef CS_DEBUG
#define dbg_print(x) printf x
#else
#define dbg_print(x)
#endif
/* Return Status */
#define CS_ERROR -1
#define CS_OK 1
/* Hardcoded CS8900 specific configuration information */
#define CS8900_IOSIZE 16 /* CS8900 has 8 2byte IO registers */
#define CS8900_DMA_BUFFER_SIZE 16384 /* 16Kbyte or 64Kbyte, if
* supported
*/
/* Receive buffer status */
#define RXBUF_FREE 0x0000
#define RXBUF_ALLOCATED 0x0001
#define RXBUF_LOANED 0x0002
/* Config Flags in cs_softc */
#define CFGFLG_MEM_MODE 0x0001
#define CFGFLG_USE_SA 0x0002
#define CFGFLG_IOCHRDY 0x0004
#define CFGFLG_DCDC_POL 0x0008
#define CFGFLG_FDX 0x0010
#define CFGFLG_DMA_MODE 0x0020
#define CFGFLG_NOT_EEPROM 0x8000
/* Media Type in cs_softc */
#define MEDIA_AUI 0x0001
#define MEDIA_10BASE2 0x0002
#define MEDIA_10BASET 0x0003
/* Chip Identification */
#define EISA_NUM_CRYSTAL 0x630E
#define PROD_ID_MASK 0xE000
#define PROD_ID_CS8900 0x0000
#define PROD_ID_CS8920 0x4000
#define PROD_ID_CS892X 0x6000
#define PROD_REV_MASK 0x1F00
/* IO Port Offsets */
#define PORT_RXTX_DATA 0x0000
#define PORT_RXTX_DATA_1 0x0002
#define PORT_TX_CMD 0x0004
#define PORT_TX_LENGTH 0x0006
#define PORT_ISQ 0x0008
#define PORT_PKTPG_PTR 0x000A
#define PORT_PKTPG_DATA 0x000C
#define PORT_PKTPG_DATA_1 0x000E
/* PacketPage Offsets */
#define PKTPG_EISA_NUM 0x0000
#define PKTPG_PRODUCT_ID 0x0002
#define PKTPG_IO_BASE 0x0020
#define PKTPG_INT_NUM 0x0022
#define PKTPG_DMA_CHANNEL 0x0024
#define PKTPG_DMA_START_FRAME 0x0026
#define PKTPG_DMA_FRAME_COUNT 0x0028
#define PKTPG_DMA_BYTE_COUNT 0x002A
#define PKTPG_MEM_BASE 0x002C
#define PKTPG_EEPROM_CMD 0x0040
#define PKTPG_EEPROM_DATA 0x0042
#define PKTPG_FRAME_BYTE_COUNT 0x0050
#define PKTPG_RX_CFG 0x0102
#define PKTPG_RX_CTL 0x0104
#define PKTPG_TX_CFG 0x0106
#define PKTPG_BUF_CFG 0x010A
#define PKTPG_LINE_CTL 0x0112
#define PKTPG_SELF_CTL 0x0114
#define PKTPG_BUS_CTL 0x0116
#define PKTPG_TEST_CTL 0x0118
#define PKTPG_ISQ 0x0120
#define PKTPG_RX_EVENT 0x0124
#define PKTPG_TX_EVENT 0x0128
#define PKTPG_BUF_EVENT 0x012C
#define PKTPG_RX_MISS 0x0130
#define PKTPG_TX_COL 0x0132
#define PKTPG_LINE_ST 0x0134
#define PKTPG_SELF_ST 0x0136
#define PKTPG_BUS_ST 0x0138
#define PKTPG_TX_CMD 0x0144
#define PKTPG_TX_LENGTH 0x0146
#define PKTPG_LOG_ADDR 0x0150 /* logical address filter
* (hash table)
*/
#define PKTPG_IND_ADDR 0x0158
#define PKTPG_RX_STATUS 0x0400
#define PKTPG_RX_LENGTH 0x0402
#define PKTPG_RX_FRAME 0x0404
#define PKTPG_TX_FRAME 0x0A00
/* EEPROM Offsets */
#define EEPROM_IND_ADDR_H 0x001C
#define EEPROM_IND_ADDR_M 0x001D
#define EEPROM_IND_ADDR_L 0x001E
#define EEPROM_ISA_CFG 0x001F
#define EEPROM_MEM_BASE 0x0020
#define EEPROM_XMIT_CTL 0x0023
#define EEPROM_ADPTR_CFG 0x0024
/* Register Numbers */
#define REG_NUM_MASK 0x003F
#define REG_NUM_RX_EVENT 0x0004
#define REG_NUM_TX_EVENT 0x0008
#define REG_NUM_BUF_EVENT 0x000C
#define REG_NUM_RX_MISS 0x0010
#define REG_NUM_TX_COL 0x0012
/* Self Control Register */
#define SELF_CTL_RESET 0x0040
#define SELF_CTL_HC1E 0x2000
#define SELF_CTL_HCB1 0x8000
/* Self Status Register */
#define SELF_ST_INIT_DONE 0x0080
#define SELF_ST_SI_BUSY 0x0100
#define SELF_ST_EEP_PRES 0x0200
#define SELF_ST_EEP_OK 0x0400
#define SELF_ST_EL_PRES 0x0800
/* EEPROM Command Register */
#define EEPROM_CMD_READ 0x0200
#define EEPROM_CMD_ELSEL 0x0400
/* Bus Control Register */
#define BUS_CTL_RESET_DMA 0x0040
#define BUS_CTL_USE_SA 0x0200
#define BUS_CTL_MEM_MODE 0x0400
#define BUS_CTL_DMA_BURST 0x0800
#define BUS_CTL_IOCHRDY 0x1000
#define BUS_CTL_DMA_SIZE 0x2000
#define BUS_CTL_INT_ENBL 0x8000
/* Bus Status Register */
#define BUS_ST_TX_BID_ERR 0x0080
#define BUS_ST_RDY4TXNOW 0x0100
/* Line Control Register */
#define LINE_CTL_RX_ON 0x0040
#define LINE_CTL_TX_ON 0x0080
#define LINE_CTL_AUI_ONLY 0x0100
#define LINE_CTL_10BASET 0x0000
#define LINE_CTL_AUTO_SEL 0x0200
/* Test Control Register */
#define TEST_CTL_DIS_LT 0x0080
#define TEST_CTL_ENDEC_LP 0x0200
#define TEST_CTL_AUI_LOOP 0x0400
#define TEST_CTL_DIS_BKOFF 0x0800
#define TEST_CTL_FDX 0x4000
/* Receiver Configuration Register */
#define RX_CFG_SKIP 0x0040
#define RX_CFG_RX_OK_IE 0x0100
#define RX_CFG_RX_DMA_ONLY 0x0200
#define RX_CFG_CRC_ERR_IE 0x1000
#define RX_CFG_RUNT_IE 0x2000
#define RX_CFG_X_DATA_IE 0x4000
#define RX_CFG_ALL_IE 0x7100
/* Receiver Event Register */
#define RX_EVENT_DRIBBLE 0x0080
#define RX_EVENT_RX_OK 0x0100
#define RX_EVENT_IND_ADDR 0x0400
#define RX_EVENT_BCAST 0x0800
#define RX_EVENT_CRC_ERR 0x1000
#define RX_EVENT_RUNT 0x2000
#define RX_EVENT_X_DATA 0x4000
/* Receiver Control Register */
#define RX_CTL_INDHASH_A 0x0040
#define RX_CTL_PROMISC_A 0x0080
#define RX_CTL_RX_OK_A 0x0100
#define RX_CTL_MCAST_A 0x0200
#define RX_CTL_IND_A 0x0400
#define RX_CTL_BCAST_A 0x0800
#define RX_CTL_CRC_ERR_A 0x1000
#define RX_CTL_RUNT_A 0x2000
#define RX_CTL_X_DATA_A 0x4000
/* Transmit Configuration Register */
#define TX_CFG_LOSS_CRS_IE 0x0040
#define TX_CFG_SQE_ERR_IE 0x0080
#define TX_CFG_TX_OK_IE 0x0100
#define TX_CFG_OUT_WIN_IE 0x0200
#define TX_CFG_JABBER_IE 0x0400
#define TX_CFG_16_COLL_IE 0x8000
#define TX_CFG_ALL_IE 0x8FC0
/* Transmit Configuration Register */
#define TX_EVENT_LOSS_CRS 0x0040
#define TX_EVENT_SQE_ERR 0x0080
#define TX_EVENT_TX_OK 0x0100
#define TX_EVENT_OUT_WIN 0x0200
#define TX_EVENT_JABBER 0x0400
#define TX_EVENT_COLL_MASK 0x7800
#define TX_EVENT_16_COLL 0x8000
/* Transmit Command Register */
#define TX_CMD_START_5 0x0000
#define TX_CMD_START_381 0x0080
#define TX_CMD_START_1021 0x0040
#define TX_CMD_START_ALL 0x00C0
#define TX_CMD_FORCE 0x0100
#define TX_CMD_ONE_COLL 0x0200
#define TX_CMD_NO_CRC 0x1000
#define TX_CMD_NO_PAD 0x2000
/* Buffer Configuration Register */
#define BUF_CFG_SW_INT 0x0040
#define BUF_CFG_RX_DMA_IE 0x0080
#define BUF_CFG_RDY4TX_IE 0x0100
#define BUF_CFG_RX_MISS_IE 0x0400
#define BUF_CFG_TX_UNDR_IE 0x0200
#define BUF_CFG_RX_128_IE 0x0800
#define BUF_CFG_TX_COL_OVER_IE 0x1000
#define BUF_CFG_RX_MISS_OVER_IE 0x2000
#define BUF_CFG_RX_DEST_IE 0x8000
/* Buffer Event Register */
#define BUF_EVENT_SW_INT 0x0040
#define BUF_EVENT_RX_DMA 0x0080
#define BUF_EVENT_RDY4TX 0x0100
#define BUF_EVENT_TX_UNDR 0x0200
#define BUF_EVENT_RX_MISS 0x0400
#define BUF_EVENT_RX_128 0x0800
#define BUF_EVENT_RX_DEST 0x8000
/* ISA Configuration from EEPROM */
#define ISA_CFG_IRQ_MASK 0x000F
#define ISA_CFG_USE_SA 0x0080
#define ISA_CFG_IOCHRDY 0x0100
#define ISA_CFG_MEM_MODE 0x8000
/* Memory Base from EEPROM */
#define MEM_BASE_MASK 0xFFF0
/* Adpater Configuration from EEPROM */
#define ADPTR_CFG_MEDIA 0x0060
#define ADPTR_CFG_10BASET 0x0020
#define ADPTR_CFG_AUI 0x0040
#define ADPTR_CFG_10BASE2 0x0060
#define ADPTR_CFG_DCDC_POL 0x0080
/* Transmission Control from EEPROM */
#define XMIT_CTL_FDX 0x8000
/* Miscellaneous definitions */
#define MAXLOOP 0x8888
#define CS_DMA_FRAME_HEADER_SIZE (sizeof(ushort) * 2)
#define RXBUFCOUNT 16
#define MC_LOANED 5
#endif

290
sys/arch/arm32/isa/isa_io.c Normal file
View File

@ -0,0 +1,290 @@
/* $NetBSD: isa_io.c,v 1.1 1998/06/08 17:49:44 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
* bus_space I/O functions for isa
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/pio.h>
#include <arm32/isa/isa_machdep.h>
/* Proto types for all the bus_space structure functions */
bs_protos(isa);
bs_protos(bs_notimpl);
/* Declare the isa bus space tags */
/* The IO and MEM structs are identical, except for the cookies, */
/* which contain the address space bases. */
/*
* NOTE: ASSEMBLY LANGUAGE RELIES ON THE COOKIE -- THE FIRST MEMBER OF
* THIS STRUCTURE -- TO BE THE VIRTUAL ADDRESS OF ISA/IO!
*/
struct bus_space isa_io_bs_tag = {
/* cookie */
NULL, /* initialized below */
/* mapping/unmapping */
isa_map,
isa_unmap,
isa_subregion,
/* allocation/deallocation */
isa_alloc,
isa_free,
/* barrier */
isa_barrier,
/* read (single) */
isa_r_1,
isa_r_2,
isa_r_4,
bs_notimpl_r_8,
/* read multiple */
isa_rm_1,
isa_rm_2,
isa_rm_4,
bs_notimpl_rm_8,
/* read region */
isa_rr_1,
isa_rr_2,
isa_rr_4,
bs_notimpl_rr_8,
/* write (single) */
isa_w_1,
isa_w_2,
isa_w_4,
bs_notimpl_w_8,
/* write multiple */
isa_wm_1,
isa_wm_2,
isa_wm_4,
bs_notimpl_wm_8,
/* write region */
isa_wr_1,
isa_wr_2,
isa_wr_4,
bs_notimpl_wr_8,
/* set multiple */
bs_notimpl_sm_1,
bs_notimpl_sm_2,
bs_notimpl_sm_4,
bs_notimpl_sm_8,
/* set region */
bs_notimpl_sr_1,
bs_notimpl_sr_2,
bs_notimpl_sr_4,
bs_notimpl_sr_8,
/* copy */
bs_notimpl_c_1,
bs_notimpl_c_2,
bs_notimpl_c_4,
bs_notimpl_c_8,
};
/*
* NOTE: ASSEMBLY LANGUAGE RELIES ON THE COOKIE -- THE FIRST MEMBER OF
* THIS STRUCTURE -- TO BE THE VIRTUAL ADDRESS OF ISA/MEMORY!
*/
struct bus_space isa_mem_bs_tag = {
/* cookie */
NULL, /* initialized below */
/* mapping/unmapping */
isa_map,
isa_unmap,
isa_subregion,
/* allocation/deallocation */
isa_alloc,
isa_free,
/* barrier */
isa_barrier,
/* read (single) */
isa_r_1,
isa_r_2,
isa_r_4,
bs_notimpl_r_8,
/* read multiple */
isa_rm_1,
isa_rm_2,
isa_rm_4,
bs_notimpl_rm_8,
/* read region */
isa_rr_1,
isa_rr_2,
isa_rr_4,
bs_notimpl_rr_8,
/* write (single) */
isa_w_1,
isa_w_2,
isa_w_4,
bs_notimpl_w_8,
/* write multiple */
isa_wm_1,
isa_wm_2,
isa_wm_4,
bs_notimpl_wm_8,
/* write region */
isa_wr_1,
isa_wr_2,
isa_wr_4,
bs_notimpl_wr_8,
/* set multiple */
bs_notimpl_sm_1,
bs_notimpl_sm_2,
bs_notimpl_sm_4,
bs_notimpl_sm_8,
/* set region */
bs_notimpl_sr_1,
bs_notimpl_sr_2,
bs_notimpl_sr_4,
bs_notimpl_sr_8,
/* copy */
bs_notimpl_c_1,
bs_notimpl_c_2,
bs_notimpl_c_4,
bs_notimpl_c_8,
};
/* bus space functions */
void
isa_io_init(vm_offset_t isa_io_addr, vm_offset_t isa_mem_addr)
{
isa_io_bs_tag.bs_cookie = (void *)isa_io_addr;
isa_mem_bs_tag.bs_cookie = (void *)isa_mem_addr;
}
/* break the abstraction: sometimes, other parts of the system
(e.g. X servers) need to map ISA space directly. use these
functions sparingly! */
vm_offset_t
isa_io_data_vaddr()
{
return (vm_offset_t)isa_io_bs_tag.bs_cookie;
}
vm_offset_t
isa_mem_data_vaddr()
{
return (vm_offset_t)isa_mem_bs_tag.bs_cookie;
}
int
isa_map(t, bpa, size, cacheable, bshp)
void *t;
bus_addr_t bpa;
bus_size_t size;
int cacheable;
bus_space_handle_t *bshp;
{
*bshp = bpa + (bus_addr_t)t;
return(0);
}
void
isa_unmap(t, bsh, size)
void *t;
bus_space_handle_t bsh;
bus_size_t size;
{
/* Nothing to do. */
}
int
isa_subregion(t, bsh, offset, size, nbshp)
void *t;
bus_space_handle_t bsh;
bus_size_t offset, size;
bus_space_handle_t *nbshp;
{
panic("isa_subregion(): Help!\n");
}
int
isa_alloc(t, rstart, rend, size, alignment, boundary, cacheable,
bpap, bshp)
void *t;
bus_addr_t rstart, rend;
bus_size_t size, alignment, boundary;
int cacheable;
bus_addr_t *bpap;
bus_space_handle_t *bshp;
{
panic("isa_alloc(): Help!\n");
}
void
isa_free(t, bsh, size)
void *t;
bus_space_handle_t bsh;
bus_size_t size;
{
panic("isa_free(): Help!\n");
}
void
isa_barrier(t, bsh, offset, len, flags)
void *t;
bus_space_handle_t bsh;
bus_size_t offset, len;
int flags;
{
panic("isa_barrier(): Help!\n");
}

View File

@ -0,0 +1,391 @@
/* $NetBSD: isa_io_asm.S,v 1.1 1998/06/08 17:49:44 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
* bus_space I/O functions for isa
*/
#include <machine/asm.h>
fp .req r11
ip .req r12
sp .req r13
lr .req r14
pc .req r15
.text
/*
* read single
*/
ENTRY(isa_r_1)
ldrb r0, [r1, r2]
#ifdef GPROF
nop ; nop ; nop ; nop ; nop
#endif
mov pc, lr
ENTRY(isa_r_2)
add r0, r1, r2
/* ldrh r0, [r0] */ .word 0xe1d000b0
#ifdef GPROF
nop ; nop ; nop ; nop ; nop
#endif
mov pc, lr
ENTRY(isa_r_4)
ldr r0, [r1, r2]
#ifdef GPROF
nop ; nop ; nop ; nop ; nop
#endif
mov pc, lr
/*
* read multiple.
*
* cloned from assembly generated for:
*
* void
* isa_rm_4(v, h, o, p, s)
* void *v;
* bus_space_handle_t h;
* bus_size_t o, s;
* u_int32_t *p;
* {
* u_int32_t *port, *lim;
*
* port = (u_in32_t *)(h + o);
* lim = p + s;
*
* while (p < lim)
* *p++ = *port;;
* }
*/
ENTRY(isa_rm_1)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add ip, r0, r3
cmp r0, ip
ldmcsea fp, {fp, sp, pc}
Lisa_rm_1_loop:
ldrb r3, [r1, #0]
strb r3, [r0], #1
cmp r0, ip
bcc Lisa_rm_1_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_rm_2)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add ip, r0, r3, asl #1
cmp r0, ip
ldmcsea fp, {fp, sp, pc}
Lisa_rm_2_loop:
/* ldrh r3, [r1] */ .word 0xe1d130b0
/* strh r3, [r0], #2 */ .word 0xe0c030b2
cmp r0, ip
bcc Lisa_rm_2_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_rm_4)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add ip, r0, r3, asl #2
cmp r0, ip
ldmcsea fp, {fp, sp, pc}
Lisa_rm_4_loop:
ldr r3, [r1, #0]
str r3, [r0], #4
cmp r0, ip
bcc Lisa_rm_4_loop
ldmea fp, {fp, sp, pc}
/*
* read region.
*
* cloned from assembly generated for:
*
* void
* isa_wr_4(v, h, o, p, s)
* void *v;
* bus_space_handle_t h;
* bus_size_t o, s;
* u_int32_t *p;
* {
* u_int32_t *cur, *lim;
*
* cur = (u_in32_t *)(h + o);
* lim = cur + s;
*
* while (cur < lim)
* *cur++ = *p++;
* }
*
*/
ENTRY(isa_rr_1)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add r2, r1, r3
cmp r1, r2
ldmcsea fp, {fp, sp, pc}
Lisa_rr_1_loop:
ldrb r3, [r1], #1
strb r3, [r0], #1
cmp r1, r2
bcc Lisa_rr_1_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_rr_2)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add r2, r1, r3, asl #1
cmp r1, r2
ldmcsea fp, {fp, sp, pc}
Lisa_rr_2_loop:
/* ldrh r3, [r1], #2 */ .word 0xe0d130b2
/* strh r3, [r0], #2 */ .word 0xe0c030b2
cmp r1, r2
bcc Lisa_rr_2_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_rr_4)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add r2, r1, r3, asl #2
cmp r1, r2
ldmcsea fp, {fp, sp, pc}
Lisa_rr_4_loop:
ldr r3, [r1], #4
str r3, [r0], #4
cmp r1, r2
bcc Lisa_rr_4_loop
ldmea fp, {fp, sp, pc}
/*
* write single
*/
ENTRY(isa_w_1)
strb r3, [r1, r2]
#ifdef GPROF
nop ; nop ; nop ; nop ; nop
#endif
mov pc, lr
ENTRY(isa_w_2)
add r0, r1, r2
/* strh r3, [r0] */ .word 0xe1c030b0
#ifdef GPROF
nop ; nop ; nop ; nop ; nop
#endif
mov pc, lr
ENTRY(isa_w_4)
str r3, [r1, r2]
#ifdef GPROF
nop ; nop ; nop ; nop ; nop
#endif
mov pc, lr
/* write multiple
*
* cloned from assembly generated for:
*
* void
* isa_wm_4(v, h, o, p, s)
* void *v;
* bus_space_handle_t h;
* bus_size_t o, s;
* u_int32_t *p;
* {
* u_int32_t *port, *lim;
*
* port = (u_in32_t *)(h + o);
* lim = p + s;
*
* while (p < lim)
* *port = *p++;
* }
*/
ENTRY(isa_wm_1)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add ip, r0, r3
cmp r0, ip
ldmcsea fp, {fp, sp, pc}
Lisa_wm_1_loop:
ldrb r3, [r0], #1
strb r3, [r1]
cmp r0, ip
bcc Lisa_wm_1_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_wm_2)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add ip, r0, r3, asl #1
cmp r0, ip
ldmcsea fp, {fp, sp, pc}
Lisa_wm_2_loop:
/* ldrh r3, [r0], #2 */ .word 0xe0d030b2
/* strh r3, [r1] */ .word 0xe1c130b0
cmp r0, ip
bcc Lisa_wm_2_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_wm_4)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add ip, r0, r3, asl #2
cmp r0, ip
ldmcsea fp, {fp, sp, pc}
Lisa_wm_4_loop:
ldr r3, [r0], #4
str r3, [r1]
cmp r0, ip
bcc Lisa_wm_4_loop
ldmea fp, {fp, sp, pc}
/*
* write region.
*
* cloned from assembly generated for:
*
* void
* isa_wr_4(v, h, o, p, s)
* void *v;
* bus_space_handle_t h;
* bus_size_t o, s;
* u_int32_t *p;
* {
* u_int32_t *cur, *lim;
*
* cur = (u_in32_t *)(h + o);
* lim = cur + s;
*
* while (cur < lim)
* *cur++ = *p++;
* }
*
*/
ENTRY(isa_wr_1)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add r2, r1, r3
cmp r1, r2
ldmcsea fp, {fp, sp, pc}
Lisa_wr_1_loop:
ldrb r3, [r0], #1
strb r3, [r1], #1
cmp r1, r2
bcc Lisa_wr_1_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_wr_2)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add r2, r1, r3, asl #1
cmp r1, r2
ldmcsea fp, {fp, sp, pc}
Lisa_wr_2_loop:
/* ldrh r3, [r0], #2 */ .word 0xe0d030b2
/* strh r3, [r1], #2 */ .word 0xe0c130b2
cmp r1, r2
bcc Lisa_wr_2_loop
ldmea fp, {fp, sp, pc}
ENTRY(isa_wr_4)
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
mov r0, r3
add r1, r1, r2
sub fp, ip, #4
ldr r3, [fp, #4]
add r2, r1, r3, asl #2
cmp r1, r2
ldmcsea fp, {fp, sp, pc}
Lisa_wr_4_loop:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r1, r2
bcc Lisa_wr_4_loop
ldmea fp, {fp, sp, pc}

View File

@ -0,0 +1,585 @@
/* $NetBSD: isa_irq.S,v 1.1 1998/06/08 17:49:44 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
* Copyright (c) 1994-1997 Mark Brinicombe.
* Copyright (c) 1994 Brini.
* All rights reserved.
*
* This code is derived from software written for Brini by Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Brini.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RiscBSD kernel project
*
* irq.S
*
* Low level irq and fiq handlers
*
* Created : 27/09/94
*/
#include "assym.h"
#include <machine/cpu.h>
#include <machine/frame.h>
#include <dev/isa/isareg.h>
#include <arm32/isa/icu.h>
#include <machine/asm.h>
#include <machine/irqhandler.h>
sp .req r13
lr .req r14
pc .req r15
.text
/*
*
* irq_entry
*
* Main entry point for the IRQ vector
*
* This function reads the irq request bits in the IOMD registers
* IRQRQA, IRQRQB and DMARQ
* It then calls an installed handler for each bit that is set.
* The function stray_irqhandler is called if a handler is not defined
* for a particular interrupt.
* If a interrupt handler is found then it is called with r0 containing
* the argument defined in the handler structure. If the field ih_arg
* is zero then a pointer to the IRQ frame on the stack is passed instead.
*/
Ldisabled_mask:
.word _disabled_mask
Lcurrent_spl_level:
.word _current_spl_level
Lcurrent_intr_depth:
.word _current_intr_depth
Lvam_io_data:
.word _isa_io_bs_tag
.text
.global irq_entry
/*
* Register usage
*
* r6 - Address of current handler
* r7 - Pointer to handler pointer list
* r8 - Current IRQ requests.
* r9 - Used to count through possible IRQ bits.
* r10 - Base address of IOMD
*/
/* Some documentation is in isa_machdep.c */
irq_entry:
sub lr, lr, #0x00000004 /* Adjust the lr */
PUSHFRAMEINSVC /* Push an interrupt frame */
/* mov r11, #0x00000000*/ /* Trace back stops here */
/* Load r8 with the ISA 8259 irqs */
/* r8 <- irq's pending [15:0] */
/* address of 8259 #1 */
ldr r0, Lvam_io_data
ldr r0, [r0]
ldrb r8, [r0, #IO_ICU1] /* ocw3 = irr */
/* clear the IRR bits that are currently masked. */
ldr r2, Li8259_mask
ldr r2, [r2]
mvn r2, r2 /* disabled -> enabled */
/* address of 8259 #2 */
tst r2, #(1 << IRQ_SLAVE) /* if slave is enabled */
tstne r8, #(1 << IRQ_SLAVE) /* anything from slave? */
ldrneb r1, [r0, #IO_ICU2] /* ocw3 = irr */
orrne r8, r8, r1, lsl #8
and r8, r8, r2 /* clear disabled */
/* clear IRQ 2, which is only used for slave 8259 */
bic r8, r8, #(1 << IRQ_SLAVE)
/*
* Note that we have entered the IRQ handler.
* We are in SVC mode so we cannot use the processor mode
* to determine if we are in an IRQ. Instead we will count the
* each time the interrupt handler is nested.
*/
ldr r0, Lcurrent_intr_depth
ldr r1, [r0]
add r1, r1, #1
str r1, [r0]
/* Block the current requested interrupts */
ldr r1, Ldisabled_mask
ldr r0, [r1]
stmfd sp!, {r0}
orr r0, r0, r8
str r0, [r1]
/*
* Need to block all interrupts at the IPL or lower for
* all asserted interrupts.
* This basically emulates hardware interrupt priority levels.
* Means we need to go through the interrupt mask and for
* every asserted interrupt we need to mask out all other
* interrupts at the same or lower IPL.
* If only we could wait until the main loop but we need to sort
* this out first so interrupts can be re-enabled.
*
* This would benefit from a special ffs type routine
*/
mov r9, #0x00000001
ldr r7, Lirqblock
emulate_hwipl_loop:
tst r8, r9
ldrne r6, [r7]
orrne r0, r0, r6
add r7, r7, #4
mov r9, r9, lsl #1 /* move on to next bit */
#ifdef CPU_ARM7500
teq r9, #0 /* done the last bit ? */
#else
teq r9, #(1 << 24) /* done the last bit ? */
#endif /* CPU_ARM7500 */
bne emulate_hwipl_loop /* no - loop back. */
str r0, [r1]
/* Update the IOMD irq masks */
bl _irq_setmasks
mrs r0, cpsr_all /* Enable IRQ's */
bic r0, r0, #I32_bit
msr cpsr_all, r0
ldr r7, [pc, #irqhandlers - . - 8]
mov r9, #0x00000001
stmfd sp!, {r8}
irqloop:
/* This would benefit from a special ffs type routine */
tst r8, r9 /* Is a bit set ? */
beq nextirq /* No ? try next bit */
ldr r6, [r7] /* Get address of first handler structure */
teq r6, #0x00000000 /* Do we have a handler */
moveq r0, r8 /* IRQ requests as arg 0 */
beq _stray_irqhandler /* call special handler */
ldr r0, Lcnt
ldr r1, [r0, #(V_INTR)]
add r1, r1, #0x00000001
str r1, [r0, #(V_INTR)]
irqchainloop:
add lr, pc, #nextinchain - . - 8 /* return address */
/*
* XXX: Should stats be accumlated for every interrupt routine called
* or for every physical interrupt that is serviced.
*/
#ifdef IRQSTATS
ldr r0, Lintrcnt
ldr r1, [r6, #(IH_NUM)]
add r0, r0, r1, lsl #2
ldr r1, [r0]
add r1, r1, #0x00000001
str r1, [r0]
#endif /* IRQSTATS */
ldr r0, [r6, #(IH_ARG)] /* Get argument pointer */
teq r0, #0x00000000 /* If arg is zero pass stack frame */
addeq r0, sp, #8 /* ... stack frame */
ldr pc, [r6, #(IH_FUNC)] /* Call handler */
nextinchain:
teq r0, #0x00000001 /* Was the irq serviced ? */
beq irqdone
ldr r6, [r6, #(IH_NEXT)]
teq r6, #0x00000000
bne irqchainloop
irqdone:
nextirq:
add r7, r7, #0x00000004 /* update pointer to handlers */
mov r9, r9, lsl #1 /* move on to next bit */
#ifdef CPU_ARM7500
teq r9, #0 /* done the last bit ? */
#else
teq r9, #(1 << 24) /* done the last bit ? */
#endif /* CPU_ARM7500 */
bne irqloop /* no - loop back. */
ldmfd sp!, {r8}
/* Restore previous disabled mask */
ldmfd sp!, {r2}
ldr r1, Ldisabled_mask
str r2, [r1]
bl _irq_setmasks
bl _dosoftints /* Handle the soft interrupts */
/* Manage AST's. Maybe this should be done as a soft interrupt ? */
ldr r0, [sp] /* Get the SPSR from stack */
and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the IRQ */
teq r0, #(PSR_USR32_MODE)
ldreq r0, Lastpending /* Do we have an AST pending ? */
ldreq r1, [r0]
teqeq r1, #0x00000001
beq irqast /* call the AST handler */
/* Kill IRQ's in preparation for exit */
mrs r0, cpsr_all
orr r0, r0, #(I32_bit)
msr cpsr_all, r0
/* Decrement the nest count */
ldr r0, Lcurrent_intr_depth
ldr r1, [r0]
sub r1, r1, #1
str r1, [r0]
PULLFRAMEFROMSVCANDEXIT
movs pc, lr /* Exit */
/*
* Ok, snag with current intr depth ...
* If ast() calls mi_sleep() the current_intr_depth will not be
* decremented until the process is woken up. This can result
* in the system believing it is still in the interrupt handler.
* If we are calling ast() then correct the current_intr_depth
* before the call.
*/
irqast:
mov r1, #0x00000000 /* Clear ast_pending */
str r1, [r0]
/* Kill IRQ's so we atomically decrement current_intr_depth */
mrs r2, cpsr_all
orr r3, r2, #(I32_bit)
msr cpsr_all, r3
/* Decrement the nest count */
ldr r0, Lcurrent_intr_depth
ldr r1, [r0]
sub r1, r1, #1
str r1, [r0]
/* Restore IRQ's */
msr cpsr_all, r2
mov r0, sp
bl _ast
/* Kill IRQ's in preparation for exit */
mrs r0, cpsr_all
orr r0, r0, #(I32_bit)
msr cpsr_all, r0
PULLFRAMEFROMSVCANDEXIT
movs pc, lr /* Exit */
Lspl_mask:
.word _spl_mask /* irq's allowed at current spl level */
Lcurrent_mask:
.word _current_mask /* irq's that are usable */
Lirqblock:
.word _irqblock
ENTRY(irq_setmasks)
/* Disable interrupts */
mrs r3, cpsr_all
orr r1, r3, #(I32_bit)
msr cpsr_all, r1
/* Calculate interrupt mask */
ldr r1, Lcurrent_mask /* All the enabled interrupts */
#ifdef LDRH
ldrh r1, [r1] /* get hardware bits of mask */
#else
.word 0xe0d110b0 /* hand-assembled ldrh r1, [r1] */
#endif
ldr r2, Lspl_mask /* Block due to current spl level */
ldr r2, [r2]
and r1, r1, r2
ldr r2, Ldisabled_mask /* Block due to active interrupts */
ldr r2, [r2]
bic r1, r1, r2
/* since 8259's are so slow to access, this code does everything
possible to avoid them */
/* get current mask: these are the bits */
ldr r0, Li8259_mask
ldr r2, [r0]
/* r2 = 0000.0000.0000.0000.ZZZZ.ZZZZ.ZZZZ.ZZZZ */
/* see if there's anything enabled on 8259 #2 */
tst r1, #0xff00
biceq r1, r1, #(1 << IRQ_SLAVE) /* no, so disable it */
orrne r1, r1, #(1 << IRQ_SLAVE) /* yes, so enable it */
/* eq => r1 = 0000.0000.0000.0000.0000.0000.MMMM.M0MM
ne => r1 = 0000.0000.0000.0000.MMMM.MMMM.MMMM.M1MM */
/* 8259 bit high => disable */
mvn r1, r1
/* eq => r1 = 1111.1111.1111.1111.1111.1111.YYYY.Y1YY
ne => r1 = 1111.1111.1111.1111.YYYY.YYYY.YYYY.Y0YY
(for each bit position Y = !M) */
orreq r1, r2, r1, lsl #16
/* eq => r1 = 1111.1111.YYYY.Y1YY.ZZZZ.ZZZZ.ZZZZ.ZZZZ
ne => r1 = 1111.1111.1111.1111.YYYY.YYYY.YYYY.Y0YY */
orreq r1, r1, #0x000000FF
/* eq => r1 = 1111.1111.YYYY.Y1YY.ZZZZ.ZZZZ.1111.1111
ne => r1 = 1111.1111.1111.1111.YYYY.YYYY.YYYY.Y0YY */
and r1, r1, r1, lsr #16
/* eq => r1 = 0000.0000.0000.0000.ZZZZ.ZZZZ.YYYY.Y1YY
ne => r1 = 0000.0000.0000.0000.YYYY.YYYY.YYYY.Y0YY */
/* if old = new, don't bother to set again.
fast path to exit, since 8259's are so slow anyway */
eors r2, r1, r2 /* which bits are different? */
msreq cpsr_all, r3 /* no bits are different, return */
moveq pc, lr
/* have to set at least one of the 8259's, store new mask */
str r1, [r0]
ldr r0, Lvam_io_data
ldr r0, [r0]
/* see if there's any change for 8259 #1 (master) */
tst r2, #0x00FF /* bottom 8 bits different? */
strneb r1, [r0, #(IO_ICU1 + 1)] /* icu1 / ocw1 */
/* anything for 8259 #2? */
tst r2, #0xFF00
mov r1, r1, lsr #8 /* next byte */
strneb r1, [r0, #(IO_ICU2 + 1)] /* icu2 / ocw1 */
/* Restore old cpsr and exit */
msr cpsr_all, r3
mov pc, lr
Lcnt:
.word _cnt
Lintrcnt:
.word _intrcnt
Li8259_mask:
.word _i8259_mask
irqhandlers:
.word _irqhandlers /* Pointer to array of irqhandlers */
Lastpending:
.word _astpending
#ifdef IRQSTATS
/* These symbols are used by vmstat */
.text
.global __intrnames
__intrnames:
.word _intrnames
.data
/* XXX fix */
.globl _intrnames, _eintrnames, _intrcnt, _eintrcnt
_intrnames:
.asciz "interrupt 0 "
.asciz "softnet " /* reserved0 */
.asciz "interrupt 2 "
.asciz "interrupt 3 "
.asciz "interrupt 4 "
.asciz "interrupt 5 "
.asciz "interrupt 6 "
.asciz "softclock " /* reserved1 */
.asciz "softplip " /* reserved2 */
.asciz "interrupt 9 "
.asciz "interrupt 10 "
.asciz "interrupt 11 "
.asciz "interrupt 12 "
.asciz "interrupt 13 "
.asciz "interrupt 14 "
.asciz "interrupt 15 "
.asciz "dma channel 0"
.asciz "dma channel 1"
.asciz "dma channel 2"
.asciz "dma channel 3"
.asciz "interrupt 20 "
.asciz "interrupt 21 "
.asciz "reserved 3 "
.asciz "reserved 4 "
.asciz "exp card 0 "
.asciz "exp card 1 "
.asciz "exp card 2 "
.asciz "exp card 3 "
.asciz "exp card 4 "
.asciz "exp card 5 "
.asciz "exp card 6 "
.asciz "exp card 7 "
_eintrnames:
.bss
.align 0
_intrcnt:
.space 32*4 /* XXX Should be linked to number of interrupts */
_eintrcnt:
#else /* IRQSTATS */
/* Dummy entries to keep vmstat happy */
.text
.globl _intrnames, _eintrnames, _intrcnt, _eintrcnt
_intrnames:
.long 0
_eintrnames:
_intrcnt:
.long 0
_eintrcnt:
#endif /* IRQSTATS */
/* FIQ code */
.text
.align 0
.global _fiq_setregs /* Sets up the FIQ handler */
_fiq_setregs:
mrs r2, cpsr_all
mov r3, r2
bic r2, r2, #(PSR_MODE)
orr r2, r2, #(PSR_FIQ32_MODE)
orr r2, r2, #(I32_bit | F32_bit) /* IRQs/FIQs definitely off */
msr cpsr_all, r2
ldr r8, [r0, #FH_R8] /* Update FIQ registers*/
ldr r9, [r0, #FH_R9]
ldr r10, [r0, #FH_R10]
ldr r11, [r0, #FH_R11]
ldr r12, [r0, #FH_R12]
ldr r13, [r0, #FH_R13]
msr cpsr_all, r3 /* Back to old mode */
mov pc, lr /* Exit */
.global _fiq_getregs /* Gets the FIQ registers */
_fiq_getregs:
mrs r2, cpsr_all
mov r3, r2
bic r2, r2, #(PSR_MODE)
orr r2, r2, #(PSR_FIQ32_MODE)
orr r2, r2, #(I32_bit | F32_bit) /* IRQs/FIQs definitely off */
msr cpsr_all, r2
str r8, [r0, #FH_R8] /* Update FIQ registers*/
str r9, [r0, #FH_R9]
str r10, [r0, #FH_R10]
str r11, [r0, #FH_R11]
str r12, [r0, #FH_R12]
str r13, [r0, #FH_R13]
msr cpsr_all, r3 /* Back to old mode */
mov pc, lr /* Exit */
/* End of irq.S */

View File

@ -0,0 +1,591 @@
/* $NetBSD: isa_irqhandler.c,v 1.1 1998/06/08 17:49:44 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
/*
* Copyright (c) 1994-1996 Mark Brinicombe.
* Copyright (c) 1994 Brini.
* All rights reserved.
*
* This code is derived from software written for Brini by Mark Brinicombe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Brini.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* RiscBSD kernel project
*
* irqhandler.c
*
* IRQ/FIQ initialisation, claim, release and handler routines
*
* Created : 30/09/94
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syslog.h>
#include <sys/malloc.h>
#include <vm/vm.h>
#include <net/netisr.h>
#include <machine/irqhandler.h>
#include <machine/cpu.h>
irqhandler_t *irqhandlers[NIRQS];
fiqhandler_t *fiqhandlers;
int current_intr_depth = 0;
u_int irqmasks[IPL_LEVELS];
u_int current_mask;
u_int actual_mask;
u_int disabled_mask = 0;
u_int spl_mask;
u_int soft_interrupts;
extern u_int intrcnt[];
u_int irqblock[NIRQS];
typedef struct {
vm_offset_t physical;
vm_offset_t virtual;
} pv_addr_t;
extern pv_addr_t systempage;
extern char *_intrnames;
/* Prototypes */
extern void zero_page_readonly __P((void));
extern void zero_page_readwrite __P((void));
extern int fiq_setregs __P((fiqhandler_t *));
extern int fiq_getregs __P((fiqhandler_t *));
extern void set_spl_masks __P((void));
extern void arpintr __P((void));
extern void ipintr __P((void));
extern void pppintr __P((void));
extern void plipintr __P((void));
void irq_calculatemasks __P((void));
#define WriteWord(a, b) \
*((volatile unsigned int *)(a)) = (b)
/*
* void irq_init(void)
*
* Initialise the IRQ/FIQ sub system
*/
void
irq_init()
{
int loop;
/* Clear all the IRQ handlers and the irq block masks */
for (loop = 0; loop < NIRQS; ++loop) {
irqhandlers[loop] = NULL;
irqblock[loop] = 0;
}
/* Clear the FIQ handler */
fiqhandlers = NULL;
/*
* Setup the irqmasks for the different Interrupt Priority Levels
* We will start with no bits set and these will be updated as handlers
* are installed at different IPL's.
*/
irqmasks[IPL_BIO] = 0x00000000;
irqmasks[IPL_NET] = 0x00000000;
irqmasks[IPL_TTY] = 0x00000000;
irqmasks[IPL_CLOCK] = 0x00000000;
irqmasks[IPL_IMP] = 0x00000000;
irqmasks[IPL_NONE] = 0x00000000;
current_mask = 0x00000000;
actual_mask = 0x00000000;
spl_mask = 0x00000000;
soft_interrupts = 0x00000000;
set_spl_masks();
/* Enable IRQ's and FIQ's */
enable_interrupts(I32_bit | F32_bit);
}
/*
* int irq_claim(int irq, irqhandler_t *handler)
*
* Enable an IRQ and install a handler for it.
*/
int
irq_claim(irq, handler)
int irq;
irqhandler_t *handler;
{
#ifdef DIAGNOSTIC
/* Sanity check */
if (handler == NULL)
panic("NULL interrupt handler\n");
if (handler->ih_func == NULL)
panic("Interrupt handler does not have a function\n");
#endif /* DIAGNOSTIC */
/*
* IRQ_INSTRUCT indicates that we should get the irq number
* from the irq structure
*/
if (irq == IRQ_INSTRUCT)
irq = handler->ih_num;
/* Make sure the irq number is valid */
if (irq < 0 || irq >= NIRQS)
return(-1);
/* Make sure the level is valid */
if (handler->ih_level < 0 || handler->ih_level >= IPL_LEVELS)
return(-1);
/* Attach handler at top of chain */
handler->ih_next = irqhandlers[irq];
irqhandlers[irq] = handler;
/*
* Reset the flags for this handler.
* As the handler is now in the chain mark it as active.
*/
handler->ih_flags = 0 | IRQ_FLAG_ACTIVE;
/*
* Record the interrupt number for accounting.
* Done here as the accounting number may not be the same as the IRQ number
* though for the moment they are
*/
handler->ih_num = irq;
#ifdef IRQSTATS
/* Get the interrupt name from the head of the list */
if (handler->ih_name) {
char *ptr = _intrnames + (irq * 14);
strcpy(ptr, " ");
strncpy(ptr, handler->ih_name,
min(strlen(handler->ih_name), 13));
} else {
char *ptr = _intrnames + (irq * 14);
sprintf(ptr, "irq %2d ", irq);
}
#endif /* IRQSTATS */
irq_calculatemasks();
enable_irq(irq);
set_spl_masks();
return(0);
}
/*
* int irq_release(int irq, irqhandler_t *handler)
*
* Disable an IRQ and remove a handler for it.
*/
int
irq_release(irq, handler)
int irq;
irqhandler_t *handler;
{
irqhandler_t *irqhand;
irqhandler_t **prehand;
extern char *_intrnames;
/*
* IRQ_INSTRUCT indicates that we should get the irq number
* from the irq structure
*/
if (irq == IRQ_INSTRUCT)
irq = handler->ih_num;
/* Make sure the irq number is valid */
if (irq < 0 || irq >= NIRQS)
return(-1);
/* Locate the handler */
irqhand = irqhandlers[irq];
prehand = &irqhandlers[irq];
while (irqhand && handler != irqhand) {
prehand = &irqhand;
irqhand = irqhand->ih_next;
}
/* Remove the handler if located */
if (irqhand)
*prehand = irqhand->ih_next;
else
return(-1);
/* Now the handler has been removed from the chain mark is as inactive */
irqhand->ih_flags &= ~IRQ_FLAG_ACTIVE;
/* Make sure the head of the handler list is active */
if (irqhandlers[irq])
irqhandlers[irq]->ih_flags |= IRQ_FLAG_ACTIVE;
#ifdef IRQSTATS
/* Get the interrupt name from the head of the list */
if (irqhandlers[irq] && irqhandlers[irq]->ih_name) {
char *ptr = _intrnames + (irq * 14);
strcpy(ptr, " ");
strncpy(ptr, irqhandlers[irq]->ih_name,
min(strlen(irqhandlers[irq]->ih_name), 13));
} else {
char *ptr = _intrnames + (irq * 14);
sprintf(ptr, "irq %2d ", irq);
}
#endif /* IRQSTATS */
irq_calculatemasks();
/*
* Disable the appropriate mask bit if there are no handlers left for
* this IRQ.
*/
if (irqhandlers[irq] == NULL)
disable_irq(irq);
set_spl_masks();
return(0);
}
/* adapted from .../i386/isa/isa_machdep.c */
/*
* Recalculate the interrupt masks from scratch.
* We could code special registry and deregistry versions of this function that
* would be faster, but the code would be nastier, and we don't expect this to
* happen very much anyway.
*/
void
irq_calculatemasks()
{
int irq, level;
irqhandler_t *ptr;
int irqlevel[NIRQS];
/* First, figure out which levels each IRQ uses. */
for (irq = 0; irq < NIRQS; irq++) {
register int levels = 0;
for (ptr = irqhandlers[irq]; ptr; ptr = ptr->ih_next)
levels |= 1 << ptr->ih_level;
irqlevel[irq] = levels;
}
/* Then figure out which IRQs use each level. */
for (level = 0; level < IPL_LEVELS; level++) {
register int irqs = 0;
for (irq = 0; irq < NIRQS; irq++)
if (irqlevel[irq] & (1 << level))
irqs |= 1 << irq;
irqmasks[level] = ~(irqs | IRQMASK_ALLSOFT);
}
/*
* Since run queues may be manipulated by both the statclock and tty,
* network, and disk drivers, statclock > (tty | net | bio).
*/
irqmasks[IPL_CLOCK] &= (irqmasks[IPL_TTY] & irqmasks[IPL_NET] &
irqmasks[IPL_BIO]);
/*
* There are tty, network and disk drivers that use free() at interrupt
* time, so imp > (tty | net | bio).
*/
irqmasks[IPL_IMP] &= (irqmasks[IPL_TTY] & irqmasks[IPL_NET] &
irqmasks[IPL_BIO]);
/*
* Enforce a hierarchy that gives slow devices a better chance at not
* dropping data.
*/
irqmasks[IPL_TTY] &= irqmasks[IPL_NET] & irqmasks[IPL_BIO];
irqmasks[IPL_NET] &= irqmasks[IPL_BIO];
#include "sl.h"
#include "ppp.h"
#if NSL > 0 || NPPP > 0
/* In the presence of SLIP or PPP, splimp > spltty. */
irqmasks[IPL_NET] &= irqmasks[IPL_TTY];
#endif
/*
* We now need to update the irqblock array. This array indicates
* what other interrupts should be blocked when interrupt is asserted
* This basically emulates hardware interrupt priorities e.g. by blocking
* all other IPL_BIO interrupts with an IPL_BIO interrupt is asserted.
* For each interrupt we find the highest IPL and set the block mask to
* the interrupt mask for that level.
*/
/* And eventually calculate the complete masks. */
for (irq = 0; irq < NIRQS; irq++) {
register int irqs = 1 << irq;
for (ptr = irqhandlers[irq]; ptr; ptr = ptr->ih_next)
irqs |= ~(irqmasks[ptr->ih_level]);
irqblock[irq] = irqs | IRQMASK_ALLSOFT;
}
}
void *
intr_claim(irq, level, name, ih_func, ih_arg)
int irq;
int level;
const char *name;
int (*ih_func) __P((void *));
void *ih_arg;
{
irqhandler_t *ih;
ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
if (!ih)
panic("intr_claim(): Cannot malloc handler memory\n");
ih->ih_level = level;
ih->ih_name = name;
ih->ih_func = ih_func;
ih->ih_arg = ih_arg;
ih->ih_flags = 0;
if (irq_claim(irq, ih) != 0)
return(NULL);
return(ih);
}
int
intr_release(arg)
void *arg;
{
irqhandler_t *ih = (irqhandler_t *)arg;
if (irq_release(ih->ih_num, ih) == 0) {
free(ih, M_DEVBUF);
return(0);
}
return(1);
}
/*
* void disable_irq(int irq)
*
* Disables a specific irq. The irq is removed from the master irq mask
*/
void
disable_irq(irq)
int irq;
{
register int oldirqstate;
oldirqstate = disable_interrupts(I32_bit);
current_mask &= ~(1 << irq);
irq_setmasks();
restore_interrupts(oldirqstate);
}
/*
* void enable_irq(int irq)
*
* Enables a specific irq. The irq is added to the master irq mask
* This routine should be used with caution. A handler should already
* be installed.
*/
void
enable_irq(irq)
int irq;
{
register u_int oldirqstate;
oldirqstate = disable_interrupts(I32_bit);
current_mask |= (1 << irq);
irq_setmasks();
restore_interrupts(oldirqstate);
}
/*
* void stray_irqhandler(u_int mask)
*
* Handler for stray interrupts. This gets called if a handler cannot be
* found for an interrupt.
*/
void
stray_irqhandler(mask)
u_int mask;
{
static u_int stray_irqs = 0;
if (++stray_irqs <= 8)
log(LOG_ERR, "Stray interrupt %08x%s\n", mask,
stray_irqs >= 8 ? ": stopped logging" : "");
}
/*
* int fiq_claim(fiqhandler_t *handler)
*
* Claim FIQ's and install a handler for them.
*/
int
fiq_claim(handler)
fiqhandler_t *handler;
{
/* Fail if the FIQ's are already claimed */
if (fiqhandlers)
return(-1);
if (handler->fh_size > 0xc0)
return(-1);
/* Install the handler */
fiqhandlers = handler;
/* Now we have to actually install the FIQ handler */
/* Eventually we will copy this down but for the moment ... */
zero_page_readwrite();
WriteWord(0x0000003c, (u_int) handler->fh_func);
zero_page_readonly();
cpu_cache_syncI();
/* We must now set up the FIQ registers */
fiq_setregs(handler);
/* Make sure that the FIQ's are enabled */
enable_interrupts(F32_bit);
return(0);
}
/*
* int fiq_release(fiqhandler_t *handler)
*
* Release FIQ's and remove a handler for them.
*/
int
fiq_release(handler)
fiqhandler_t *handler;
{
/* Fail if the handler is wrong */
if (fiqhandlers != handler)
return(-1);
/* Disable FIQ interrupts */
disable_interrupts(F32_bit);
/* Retrieve the FIQ registers */
fiq_getregs(handler);
/* Remove the handler */
fiqhandlers = NULL;
return(0);
}
/* End of irqhandler.c */

View File

@ -0,0 +1,65 @@
/* $NetBSD: isa_machdep.h,v 1.1 1998/06/08 17:49:44 tv Exp $ */
#ifndef _ARM32_ISA_MACHDEP_H_
#define _ARM32_ISA_MACHDEP_H_
/*
* Types provided to machine-independent ISA code.
*/
typedef void *isa_chipset_tag_t;
struct device; /* XXX */
struct isabus_attach_args; /* XXX */
/*
* ISA DMA bounce buffers.
* XXX should be made partially machine- and bus-mapping-independent.
*
* DMA_BOUNCE is the number of pages of low-addressed physical memory
* to acquire for ISA bounce buffers.
*
* isaphysmem is the location of those bounce buffers. (They are currently
* assumed to be contiguous.
*/
#ifndef DMA_BOUNCE
#define DMA_BOUNCE 8 /* one buffer per channel */
#endif
#define DMA_LARGE_BUFFER_SIZE 65536 /* 64K */
extern vm_offset_t isaphysmem;
/*
* Functions provided to machine-independent ISA code.
*/
void isa_attach_hook __P((struct device *, struct device *,
struct isabus_attach_args *));
void *isa_intr_establish __P((isa_chipset_tag_t ic, int irq, int type,
int level, int (*ih_fun)(void *), void *ih_arg));
void isa_intr_disestablish __P((isa_chipset_tag_t ic, void *handler));
/*
* ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED
* BY PORTABLE CODE.
*/
/* bus space tags */
extern struct bus_space isa_io_bs_tag;
extern struct bus_space isa_mem_bs_tag;
/* for pccons.c */
#define MONO_BASE 0x3B4
#define MONO_BUF 0x000B0000
#define CGA_BASE 0x3D4
#define CGA_BUF 0x000B8000
#define VGA_BUF 0xA0000
#define VGA_BUF_LEN (0xBFFFF - 0xA0000)
void isa_init __P((vm_offset_t, vm_offset_t));
void isa_io_init __P((vm_offset_t, vm_offset_t));
vm_offset_t isa_io_data_vaddr __P((void));
vm_offset_t isa_mem_data_vaddr __P((void));
#endif /* _ARM32_ISA_MACHDEP_H_ XXX */

432
sys/arch/arm32/isa/isadma.c Normal file
View File

@ -0,0 +1,432 @@
/* $NetBSD: isadma.c,v 1.1 1998/06/08 17:49:44 tv Exp $ */
/*
* Copyright 1997
* Digital Equipment Corporation. All rights reserved.
*
* This software is furnished under license and may be used and
* copied only in accordance with the following terms and conditions.
* Subject to these conditions, you may download, copy, install,
* use, modify and distribute this software in source and/or binary
* form. No title or ownership is transferred hereby.
*
* 1) Any source code used, modified or distributed must reproduce
* and retain this copyright notice and list of conditions as
* they appear in the source file.
*
* 2) No right is granted to use any trade name, trademark, or logo of
* Digital Equipment Corporation. Neither the "Digital Equipment
* Corporation" name nor any trademark or logo of Digital Equipment
* Corporation may be used to endorse or promote products derived
* from this software without the prior written permission of
* Digital Equipment Corporation.
*
* 3) This software is provided "AS-IS" and any express or implied
* warranties, including but not limited to, any implied warranties
* of merchantability, fitness for a particular purpose, or
* non-infringement are disclaimed. In no event shall DIGITAL be
* liable for any damages whatsoever, and in particular, DIGITAL
* shall not be liable for special, indirect, consequential, or
* incidental damages or damages for lost profits, loss of
* revenue or loss of use, whether such damages arise in contract,
* negligence, tort, under statute, in equity, at law or otherwise,
* even if advised of the possibility of such damage.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/file.h>
#include <sys/buf.h>
#include <sys/syslog.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <vm/vm.h>
#include <machine/pio.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isadmareg.h>
#include <arm32/isa/isadmavar.h>
/* region of physical memory known to be contiguous */
vm_offset_t isaphysmem;
static caddr_t dma_bounce[8]; /* XXX */
static char bounced[8]; /* XXX */
#define MAXDMASZ 512 /* XXX */
static u_int8_t dma_finished;
static u_int8_t dma_buffer_used=0;
static unsigned isa_dma_masks = 0xFF;
static int isa_dma_frozen = 0;
#define ISA_DMA_MASK_SET(CHAN) isa_dma_masks |= (1 << (CHAN))
#define ISA_DMA_MASK_CLR(CHAN) isa_dma_masks &= ~(1 << (CHAN))
/* high byte of address is stored in this port for i-th dma channel */
static int dmapageport[2][4] = {
{0x87, 0x83, 0x81, 0x82},
{0x8f, 0x8b, 0x89, 0x8a}
};
static u_int8_t dmamode[4] = {
DMA37MD_READ | DMA37MD_SINGLE,
DMA37MD_WRITE | DMA37MD_SINGLE,
DMA37MD_READ | DMA37MD_LOOP,
DMA37MD_WRITE | DMA37MD_LOOP
};
int isa_dmarangecheck __P((vm_offset_t, u_long, int));
caddr_t isa_allocphysmem __P((caddr_t, unsigned, void (*)(void)));
void isa_freephysmem __P((caddr_t, unsigned));
#ifdef SHARK
/* returns a pointer to the dma buffer if it is available,
* otherwise will return null.
*/
caddr_t isa_dmabuffer_get()
{
caddr_t buffer;
int x;
x = splhigh();
if (dma_buffer_used == 0)
{
dma_buffer_used = 1;
buffer = (caddr_t) isaphysmem;
}
else
{
/* no-can-do, already in use */
buffer = (caddr_t) NULL;
}
splx(x);
return buffer;
}
/* relinquishes the dma buffer, this does no checks
*/
void isa_dmabuffer_finish()
{
dma_buffer_used = 0;
}
#endif
/*
* isa_dmacascade(): program 8237 DMA controller channel to accept
* external dma control by a board.
*/
void
isa_dmacascade(chan)
int chan;
{
#ifdef ISADMA_DEBUG
if (chan < 0 || chan > 7)
panic("isa_dmacascade: impossible request");
#endif
/* set dma channel mode, and set dma channel mode */
if ((chan & 4) == 0) {
outb(IO_DMA1 + DMA1_MODE, chan | DMA37MD_CASCADE);
ISA_DMA_MASK_CLR(chan);
if (!isa_dma_frozen)
outb(IO_DMA1 + DMA1_SMSK, chan);
} else {
outb(IO_DMA2 + DMA2_MODE, (chan & 3) | DMA37MD_CASCADE);
ISA_DMA_MASK_CLR(chan);
if (!isa_dma_frozen)
outb(IO_DMA2 + DMA2_SMSK, (chan & 3));
}
}
/*
* isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
* problems by using a bounce buffer.
*/
void
isa_dmastart(flags, addr, nbytes, chan)
int flags;
caddr_t addr;
vm_size_t nbytes;
int chan;
{
vm_offset_t phys;
int waport;
caddr_t newaddr;
#ifdef ISADMA_DEBUG
if (chan < 0 || chan > 7 ||
((chan & 4) ? (nbytes >= (1<<17) || nbytes & 1 || (u_int)addr & 1) :
(nbytes >= (1<<16))))
panic("isa_dmastart: impossible request");
#endif
if (isa_dmarangecheck((vm_offset_t) addr, nbytes, chan)) {
if (dma_bounce[chan] == 0)
dma_bounce[chan] =
/*(caddr_t)malloc(MAXDMASZ, M_TEMP, M_WAITOK);*/
(caddr_t) isaphysmem + NBPG*chan;
bounced[chan] = 1;
newaddr = dma_bounce[chan];
*(int *) newaddr = 0; /* XXX */
/* copy bounce buffer on write */
if ((flags & DMAMODE_READ) == 0)
bcopy(addr, newaddr, nbytes);
addr = newaddr;
}
/* translate to physical */
phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr);
dma_finished &= ~(1 << chan);
if ((chan & 4) == 0) {
/*
* Program one of DMA channels 0..3. These are
* byte mode channels.
*/
/* set dma channel mode, and reset address ff */
outb(IO_DMA1 + DMA1_MODE, chan | dmamode[flags]);
outb(IO_DMA1 + DMA1_FFC, 0);
/* send start address */
waport = IO_DMA1 + DMA1_CHN(chan);
outb(dmapageport[0][chan], phys>>16);
outb(waport, phys);
outb(waport, phys>>8);
/* send count */
outb(waport + 1, --nbytes);
outb(waport + 1, nbytes>>8);
/* unmask channel */
ISA_DMA_MASK_CLR(chan);
if (!isa_dma_frozen)
outb(IO_DMA1 + DMA1_SMSK, chan | DMA37SM_CLEAR);
} else {
/*
* Program one of DMA channels 4..7. These are
* word mode channels.
*/
/* set dma channel mode, and reset address ff */
outb(IO_DMA2 + DMA2_MODE, (chan & 3) | dmamode[flags]);
outb(IO_DMA2 + DMA2_FFC, 0);
/* send start address */
waport = IO_DMA2 + DMA2_CHN(chan & 3);
outb(dmapageport[1][chan & 3], phys>>16);
phys >>= 1;
outb(waport, phys);
outb(waport, phys>>8);
/* send count */
nbytes >>= 1;
outb(waport + 2, --nbytes);
outb(waport + 2, nbytes>>8);
/* unmask channel */
ISA_DMA_MASK_CLR(chan);
if (!isa_dma_frozen)
outb(IO_DMA2 + DMA2_SMSK, (chan & 3) | DMA37SM_CLEAR);
}
}
void
isa_dmaabort(chan)
int chan;
{
#ifdef ISADMA_DEBUG
if (chan < 0 || chan > 7)
panic("isa_dmaabort: impossible request");
#endif
bounced[chan] = 0;
/* mask channel */
ISA_DMA_MASK_SET(chan);
if ((chan & 4) == 0)
if (!isa_dma_frozen)
outb(IO_DMA1 + DMA1_SMSK, DMA37SM_SET | chan);
else
if (!isa_dma_frozen)
outb(IO_DMA2 + DMA2_SMSK, DMA37SM_SET | (chan & 3));
}
int
isa_dmafinished(chan)
int chan;
{
#ifdef ISADMA_DEBUG
if (chan < 0 || chan > 7)
panic("isa_dmafinished: impossible request");
#endif
/* check that the terminal count was reached */
if ((chan & 4) == 0)
dma_finished |= inb(IO_DMA1 + DMA1_SR) & 0x0f;
else
dma_finished |= (inb(IO_DMA2 + DMA2_SR) & 0x0f) << 4;
return ((dma_finished & (1 << chan)) != 0);
}
void
isa_dmadone(flags, addr, nbytes, chan)
int flags;
caddr_t addr;
vm_size_t nbytes;
int chan;
{
#ifdef ISADMA_DEBUG
if (chan < 0 || chan > 7)
panic("isa_dmadone: impossible request");
#endif
if (!isa_dmafinished(chan))
printf("isa_dmadone: channel %d not finished\n", chan);
/* mask channel */
ISA_DMA_MASK_SET(chan);
if ((chan & 4) == 0)
if (!isa_dma_frozen)
outb(IO_DMA1 + DMA1_SMSK, DMA37SM_SET | chan);
else
if (!isa_dma_frozen)
outb(IO_DMA2 + DMA2_SMSK, DMA37SM_SET | (chan & 3));
/* copy bounce buffer on read */
if (bounced[chan]) {
bcopy(dma_bounce[chan], addr, nbytes);
bounced[chan] = 0;
}
}
/*
* Check for problems with the address range of a DMA transfer
* (non-contiguous physical pages, outside of bus address space,
* crossing DMA page boundaries).
* Return true if special handling needed.
*/
int
isa_dmarangecheck(va, length, chan)
vm_offset_t va;
u_long length;
int chan;
{
vm_offset_t phys, priorpage = 0, endva;
u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1);
endva = round_page(va + length);
for (; va < endva ; va += NBPG) {
phys = trunc_page(pmap_extract(pmap_kernel(), va));
if (phys == 0)
panic("isa_dmacheck: no physical page present");
#ifdef ISA_MACHDEP_DMARANGECHECK
if (isa_machdep_dmarangecheck(phys, NBPG))
#else
if (phys >= (1<<24))
#endif
return 1;
if (priorpage) {
if (priorpage + NBPG != phys)
return 1;
/* check if crossing a DMA page boundary */
if ((priorpage ^ phys) & dma_pgmsk)
return 1;
}
priorpage = phys;
}
return 0;
}
/* head of queue waiting for physmem to become available */
struct buf isa_physmemq;
/* blocked waiting for resource to become free for exclusive use */
static int isaphysmemflag;
/* if waited for and call requested when free (B_CALL) */
static void (*isaphysmemunblock) __P((void)); /* needs to be a list */
/*
* Allocate contiguous physical memory for transfer, returning
* a *virtual* address to region. May block waiting for resource.
* (assumed to be called at splbio())
*/
caddr_t
isa_allocphysmem(ca, length, func)
caddr_t ca;
unsigned length;
void (*func) __P((void));
{
isaphysmemunblock = func;
while (isaphysmemflag & B_BUSY) {
isaphysmemflag |= B_WANTED;
sleep((caddr_t)&isaphysmemflag, PRIBIO);
}
isaphysmemflag |= B_BUSY;
return((caddr_t)isaphysmem);
}
/*
* Free contiguous physical memory used for transfer.
* (assumed to be called at splbio())
*/
void
isa_freephysmem(va, length)
caddr_t va;
unsigned length;
{
isaphysmemflag &= ~B_BUSY;
if (isaphysmemflag & B_WANTED) {
isaphysmemflag &= B_WANTED;
wakeup((caddr_t)&isaphysmemflag);
if (isaphysmemunblock)
(*isaphysmemunblock)();
}
}
void
isa_dmafreeze()
{
int x;
x = splhigh();
if (!isa_dma_frozen) {
outb(IO_DMA1 + DMA1_MASK, 0xF);
outb(IO_DMA2 + DMA2_MASK, 0xF);
/* blam! */
}
isa_dma_frozen++;
splx(x);
}
void
isa_dmathaw()
{
int x;
x = splhigh();
isa_dma_frozen--;
if (isa_dma_frozen == 0) {
outb(IO_DMA1 + DMA1_MASK, isa_dma_masks & 0xF);
outb(IO_DMA2 + DMA2_MASK, (isa_dma_masks >> 4) & 0xF);
} else if (isa_dma_frozen < 0) {
isa_dma_frozen = 0;
}
splx(x);
}

View File

@ -0,0 +1,18 @@
/* $NetBSD: isadmavar.h,v 1.1 1998/06/08 17:49:44 tv Exp $ */
#define DMAMODE_WRITE 0
#define DMAMODE_READ 1
#define DMAMODE_LOOP 2
void isa_dmacascade __P((int));
void isa_dmastart __P((int, caddr_t, vm_size_t, int));
void isa_dmaabort __P((int));
int isa_dmafinished __P((int));
void isa_dmadone __P((int, caddr_t, vm_size_t, int));
#ifdef SHARK
caddr_t isa_dmabuffer_get __P(());
void isa_dmabuffer_finish __P(());
void isa_dmafreeze __P((void));
void isa_dmathaw __P((void));
#endif

View File

@ -0,0 +1,86 @@
/* $NetBSD: nvram.h,v 1.1 1998/06/08 17:49:44 tv Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)rtc.h 8.1 (Berkeley) 6/11/93
*/
/*
* The following information is found in the non-volatile RAM in the
* MC146818A (or DS1287A or other compatible) RTC on AT-compatible PCs.
*/
/* NVRAM byte 0: bios diagnostic */
#define NVRAM_DIAG (MC_NVRAM_START + 0) /* RTC offset 0xe */
#define NVRAM_DIAG_BITS "\020\010clock_battery\007ROM_cksum\006config_unit\005memory_size\004fixed_disk\003invalid_time"
/* NVRAM byte 1: reset code */
#define NVRAM_RESET (MC_NVRAM_START + 1) /* RTC offset 0xf */
#define NVRAM_RESET_RST 0x00 /* normal reset */
#define NVRAM_RESET_LOAD 0x04 /* load system */
/* NVRAM byte 2: diskette drive type in upper/lower nibble */
#define NVRAM_DISKETTE (MC_NVRAM_START + 2) /* RTC offset 0x10 */
#define NVRAM_DISKETTE_NONE 0 /* none present */
#define NVRAM_DISKETTE_360K 0x10 /* 360K */
#define NVRAM_DISKETTE_12M 0x20 /* 1.2M */
#define NVRAM_DISKETTE_720K 0x30 /* 720K */
#define NVRAM_DISKETTE_144M 0x40 /* 1.44M */
#define NVRAM_DISKETTE_TYPE5 0x50 /* 2.88M, presumably */
#define NVRAM_DISKETTE_TYPE6 0x60 /* 2.88M */
/* NVRAM byte 6: equipment type */
#define NVRAM_EQUIPMENT (MC_NVRAM_START + 6)
#define NVRAM_EQUIPMENT_EGAVGA 0x00 /* EGA or VGA */
#define NVRAM_EQUIPMENT_COLOR40 0x10 /* 40 column color */
#define NVRAM_EQUIPMENT_COLOR80 0x20 /* 80 column color */
#define NVRAM_EQUIPMENT_MONO80 0x30 /* 80 column mono */
#define NVRAM_EQUIPMENT_MONITOR 0x30 /* mask for monitor type */
/* NVRAM bytes 7 & 8: base memory size */
#define NVRAM_BASELO (MC_NVRAM_START + 7) /* low byte; RTC off. 0x15 */
#define NVRAM_BASEHI (MC_NVRAM_START + 8) /* high byte; RTC off. 0x16 */
/* NVRAM bytes 9 & 10: extended memory size */
#define NVRAM_EXTLO (MC_NVRAM_START + 9) /* low byte; RTC off. 0x17 */
#define NVRAM_EXTHI (MC_NVRAM_START + 10) /* high byte; RTC off. 0x18 */
/* NVRAM byte 36: current century. (please increment in Dec99!) */
#define NVRAM_CENTURY (MC_NVRAM_START + 36) /* RTC offset 0x32 */

View File

@ -0,0 +1,11 @@
/* $NetBSD: spkrreg.h,v 1.1 1998/06/08 17:49:44 tv Exp $ */
/*
* PIT port addresses and speaker control values
*/
#define PITAUX_PORT 0x61 /* port of Programmable Peripheral Interface */
#define PIT_ENABLETMR2 0x01 /* Enable timer/counter 2 */
#define PIT_SPKRDATA 0x02 /* Direct to speaker */
#define PIT_SPKR (PIT_ENABLETMR2|PIT_SPKRDATA)

View File

@ -0,0 +1,100 @@
/* $NetBSD: timerreg.h,v 1.1 1998/06/08 17:49:45 tv Exp $ */
/*-
* Copyright (c) 1993 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Register definitions for the Intel 8253 Programmable Interval Timer.
*
* This chip has three independent 16-bit down counters that can be
* read on the fly. There are three mode registers and three countdown
* registers. The countdown registers are addressed directly, via the
* first three I/O ports. The three mode registers are accessed via
* the fourth I/O port, with two bits in the mode byte indicating the
* register. (Why are hardware interfaces always so braindead?).
*
* To write a value into the countdown register, the mode register
* is first programmed with a command indicating the which byte of
* the two byte register is to be modified. The three possibilities
* are load msb (TMR_MR_MSB), load lsb (TMR_MR_LSB), or load lsb then
* msb (TMR_MR_BOTH).
*
* To read the current value ("on the fly") from the countdown register,
* you write a "latch" command into the mode register, then read the stable
* value from the corresponding I/O port. For example, you write
* TMR_MR_LATCH into the corresponding mode register. Presumably,
* after doing this, a write operation to the I/O port would result
* in undefined behavior (but hopefully not fry the chip).
* Reading in this manner has no side effects.
*
* The outputs of the three timers are connected as follows:
*
* timer 0 -> irq 0
* timer 1 -> dma chan 0 (for dram refresh)
* timer 2 -> speaker (via keyboard controller)
*
* Timer 0 is used to call hardclock.
* Timer 2 is used to generate console beeps.
*/
/*
* Frequency of all three count-down timers; (TIMER_FREQ/freq) is the
* appropriate count to generate a frequency of freq hz.
*/
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182
#endif
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
/*
* Macros for specifying values to be written into a mode register.
*/
#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
#define TIMER_SEL0 0x00 /* select counter 0 */
#define TIMER_SEL1 0x40 /* select counter 1 */
#define TIMER_SEL2 0x80 /* select counter 2 */
#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */
#define TIMER_ONESHOT 0x02 /* mode 1, one shot */
#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */
#define TIMER_SQWAVE 0x06 /* mode 3, square wave */
#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */
#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */
#define TIMER_LATCH 0x00 /* latch counter for reading */
#define TIMER_LSB 0x10 /* r/w counter LSB */
#define TIMER_MSB 0x20 /* r/w counter MSB */
#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */
#define TIMER_BCD 0x01 /* count in BCD */