/* $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); }