Coherent4.2.10/i386/md.c
/* $Header: /ker/i386/RCS/md.c,v 2.5 93/10/29 00:57:11 nigel Exp Locker: nigel $ */
/* (lgl-
* The information contained herein is a trade secret of Mark Williams
* Company, and is confidential information. It is provided under a
* license agreement, and may be copied or disclosed only under the
* terms of that agreement. Any reproduction or disclosure of this
* material without the express written authorization of Mark Williams
* Company or persuant to the license agreement is unlawful.
*
* COHERENT Version 2.3.37
* Copyright (c) 1982, 1983, 1984.
* An unpublished work by Mark Williams Company, Chicago.
* All rights reserved.
-lgl) */
/*
* Coherent 386
* IBM PC
* Machine dependent stuff.
*
* $Log: md.c,v $
* Revision 2.5 93/10/29 00:57:11 nigel
* R98 (aka 4.2 Beta) prior to removing System Global memory
*
* Revision 2.4 93/09/02 18:11:23 nigel
* Minor edits to prepare for DDI/DKI integration
*
* Revision 2.3 93/08/19 03:40:04 nigel
* Nigel's R83
*/
#define _DDI_DKI 1
#include <common/_tricks.h>
#include <sys/types.h>
#include <sys/inline.h>
#include <sys/confinfo.h>
#include <stddef.h>
#include <kernel/trace.h>
#include <kernel/reg.h>
#include <kernel/ddi_cpu.h>
#include <kernel/intr.h>
#include <sys/coherent.h>
/* The following must be nonzero to run MWC X11r5 Xfree1.2's window manager. */
extern int X00_fix;
#if __USE_PROTO__
__LOCAL__
void spurious_interrupt (int intr, __int_control_t * __NOTUSED (intrp))
#else
__LOCAL__ void
spurious_interrupt (intr, intrp)
int intr;
__int_control_t * intrp;
#endif
{
}
__int_control_t __interrupts [16] = {
__DECLARE_INT (-1, spurious_interrupt, 0),
__DECLARE_INT (-1, spurious_interrupt, 1),
__DECLARE_INT (-1, spurious_interrupt, 2), /* not used */
__DECLARE_INT (-1, spurious_interrupt, 3),
__DECLARE_INT (-1, spurious_interrupt, 4),
__DECLARE_INT (-1, spurious_interrupt, 5),
__DECLARE_INT (-1, spurious_interrupt, 6),
__DECLARE_INT (-1, spurious_interrupt, 7),
__DECLARE_INT (-1, spurious_interrupt, 8),
__DECLARE_INT (-1, spurious_interrupt, 9),
__DECLARE_INT (-1, spurious_interrupt, 10),
__DECLARE_INT (-1, spurious_interrupt, 11),
__DECLARE_INT (-1, spurious_interrupt, 12),
__DECLARE_INT (-1, spurious_interrupt, 13),
__DECLARE_INT (-1, spurious_interrupt, 14),
__DECLARE_INT (-1, spurious_interrupt, 15)
};
/*
*/
#if __USE_PROTO__
void __set_interrupt (intr_t * intrp)
#else
void
__set_interrupt (intrp)
intr_t * intrp;
#endif
{
int vector;
short s;
ASSERT (intrp != NULL);
vector = intrp->int_vector;
ASSERT (vector >= 0 && vector < __ARRAY_LENGTH (__interrupts));
ASSERT ((intrp->int_mask & (1 << vector)) != 0);
s = sphi ();
__interrupts [vector]._int_mask = intrp->int_mask;
__interrupts [vector]._int_func = (__int_func_t) intrp->int_handler;
__interrupts [vector]._int_arg = intrp->int_unit;
if (__interrupts [vector]._int_func != NULL)
__SET_BASE_MASK (__GET_BASE_MASK () & ~ (1 << vector));
else {
__interrupts [vector]._int_func = spurious_interrupt;
__SET_BASE_MASK (__GET_BASE_MASK () | (1 << vector));
}
spl (s);
}
#if __USE_PROTO__
int setivec (unsigned int level, int (*fun)())
#else
int
setivec (level, fun)
unsigned int level;
int (* fun)();
#endif
{
intr_t newint;
if (level < 1 || level > __ARRAY_LENGTH (__interrupts))
return 0;
/*
* Create a fake entry for on-the-fly interrupts, at IPL 6 just to
* leave some room for manuevering.
*/
newint.int_vector = level == 2 ? 9 : level;
newint.int_handler = fun;
newint.int_unit = level;
newint.int_mask = _masktab [6] | (1 << level);
__set_interrupt (& newint);
return 1;
}
#if __USE_PROTO__
void clrivec (int level)
#else
void
clrivec (level)
int level;
#endif
{
intr_t newint;
newint.int_vector = level == 2 ? 9 : level;
newint.int_handler = NULL;
newint.int_unit = level;
newint.int_mask = -1;
__set_interrupt (& newint);
}
/*
* Convert an array of filesystem 3 byte
* numbers to longs. This routine, unlike the old one,
* is independent of the order of bytes in a long.
* Bytes have 8 bits, though.
*/
#if __USE_PROTO__
void l3tol (long * lp, unsigned char * cp, unsigned int nl)
#else
void
l3tol (lp, cp, nl)
long * lp;
unsigned char * cp;
unsigned int nl;
#endif
{
long l;
if (nl != 0) {
do {
l = (long) cp [0] << 16;
l |= (long) cp [1];
l |= (long) cp [2] << 8;
cp += 3;
* lp ++ = l;
} while (-- nl);
}
}
/*
* Convert an array of longs into an array
* of filesystem 3 byte numbers. This routine, unlike
* the old one, is independent of the order of bytes in
* a long. Bytes have 8 bits.
*/
#if __USE_PROTO__
void ltol3(char * cp, long * lp, unsigned int nl)
#else
void
ltol3(cp, lp, nl)
char * cp;
long * lp;
unsigned int nl;
#endif
{
long l;
if (nl != 0) {
do {
l = * lp ++;
cp [0] = l >> 16;
cp [1] = l;
cp [2] = l >> 8;
cp += 3;
} while (-- nl);
}
}
/*
* Given a port number and a bit value, write the bit value into
* the tss iomap.
*
* Bit value of 0 enables user I / O for that port.
* Bit value of 1 disables user I / O for that port.
*
* Return 1 if port number is valid for the bitmap, else 0.
*/
#if __USE_PROTO__
int kiopriv(unsigned int port, unsigned int bit)
#else
int
kiopriv (port, bit)
unsigned int port, bit;
#endif
{
extern long tssIoMap;
extern long tssIoEnd;
int ret = 0;
long * ip;
unsigned int offset = port >> 5;
int shift = port & 0x1f;
long mask = 1 << shift;
long val = (bit & 1) << shift;
if (offset < (& tssIoEnd - & tssIoMap)) {
ip = (& tssIoMap) + offset;
* ip &= ~ mask; /* clear old bit value */
* ip |= val; /* or in desired new bit value */
ret = 1;
}
return ret;
}
/*
* Given a 32 bit mask and a word offset into the tss io map,
* bitwise or the mask into the map.
* Offset of 0 covers ports 0..31, offset of 1 covers ports 32..63, etc.
* Current valid range for offset is 0..63, covering ports 0..7ff.
*
* Return the new map word.
*/
#if __USE_PROTO__
long iomapOr (long val, unsigned int offset)
#else
long
iomapOr (val, offset)
long val;
unsigned offset;
#endif
{
extern long tssIoMap;
extern long tssIoEnd;
long ret = -1;
long * ip;
if (offset < (& tssIoEnd - & tssIoMap)) {
ip = (& tssIoMap) + offset;
ret = * ip |= val;
}
return ret;
}
/*
* Given a 32 bit mask and a word offset into the tss io map,
* bitwise and the mask into the map.
* Offset of 0 covers ports 0..31, offset of 1 covers ports 32..63, etc.
* Current valid range for offset is 0..63, covering ports 0..7ff.
*
* Return the new map word.
*/
#if __USE_PROTO__
long iomapAnd (long val, unsigned int offset)
#else
long
iomapAnd (val, offset)
long val;
unsigned int offset;
#endif
{
extern long tssIoMap;
extern long tssIoEnd;
long ret = -1;
long * ip;
if (offset < (& tssIoEnd - & tssIoMap)) {
ip = (& tssIoMap) + offset;
ret = * ip &= val;
}
return ret;
}
/*
* Enable user i/o to all ports in iomap.
* This is support for console ioctl KDENABIO, which takes no arguments.
*/
#if __USE_PROTO__
void __kdenabio(void)
#else
void
__kdenabio()
#endif
{
extern long tssIoMap;
extern long tssIoEnd;
long * ip;
for (ip = & tssIoMap; ip < & tssIoEnd; ip++)
*ip = 0;
}
/*
* Disable user i/o to all ports in iomap.
* This is support for console ioctl KDDISABIO, which takes no arguments.
*/
#if __USE_PROTO__
void __kddisabio(void)
#else
void
__kddisabio()
#endif
{
extern long tssIoMap;
extern long tssIoEnd;
long * ip;
if(!X00_fix)
for (ip = & tssIoMap; ip < & tssIoEnd; ip++)
*ip = 0xffffffff;
}
/*
* Enable user i/o to a single port in iomap.
* This is support for console ioctl KDADDIO, which takes as argument
* an unsigned short port number.
*/
#if __USE_PROTO__
void __kdaddio(unsigned short port)
#else
void
__kdaddio(port)
unsigned short port;
#endif
{
kiopriv(port, 0);
}
/*
* Disable user i/o to a single port in iomap.
* This is support for console ioctl KDDELIO, which takes as argument
* an unsigned short port number.
*/
#if __USE_PROTO__
void __kddelio(unsigned short port)
#else
void
__kddelio(port)
unsigned short port;
#endif
{
if(!X00_fix)
kiopriv(port, 1);
}