mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-05 03:39:02 +00:00
Change a directory layout for pc98.
- Move MD files into <arch>/<arch>. - Move bus dependent files into <arch>/<bus>. Rename some files to more suitable names. Repo-copied by: peter Discussed with: imp
This commit is contained in:
parent
671adc85da
commit
d1725ef7ff
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146049
@ -32,7 +32,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "boot.h"
|
||||
#include <machine/cpufunc.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
|
||||
static int getchar(int in_buf);
|
||||
|
||||
|
@ -347,29 +347,29 @@ libkern/ucmpdi2.c standard
|
||||
libkern/udivdi3.c standard
|
||||
libkern/umoddi3.c standard
|
||||
pc98/apm/apm_bioscall.S optional apm
|
||||
pc98/i386/busio.s standard
|
||||
pc98/i386/busiosubr.c standard
|
||||
pc98/i386/machdep.c standard
|
||||
pc98/cbus/cbus_dma.c optional isa
|
||||
pc98/cbus/clock.c standard
|
||||
pc98/cbus/fdc.c optional fdc
|
||||
pc98/cbus/fdc_cbus.c optional fdc isa
|
||||
pc98/cbus/gdc.c optional gdc
|
||||
pc98/cbus/nmi.c standard
|
||||
pc98/cbus/olpt.c optional olpt
|
||||
pc98/cbus/pckbd.c optional pckbd
|
||||
pc98/cbus/pmc.c optional pmc
|
||||
pc98/cbus/ppc.c optional ppc
|
||||
pc98/cbus/scgdcrndr.c optional sc gdc
|
||||
pc98/cbus/scterm-sck.c optional sc
|
||||
pc98/cbus/scvtb.c optional sc
|
||||
pc98/cbus/sio.c optional sio
|
||||
pc98/cbus/sio_cbus.c optional sio isa
|
||||
pc98/cbus/syscons_cbus.c optional sc
|
||||
pc98/pc98/busio.s standard
|
||||
pc98/pc98/busiosubr.c standard
|
||||
pc98/pc98/canbepm.c optional canbepm
|
||||
pc98/pc98/canbus.c optional canbus
|
||||
pc98/pc98/canbus_if.m optional canbus
|
||||
pc98/pc98/clock.c standard
|
||||
pc98/pc98/fd.c optional fdc
|
||||
pc98/pc98/fdc_cbus.c optional fdc isa
|
||||
pc98/pc98/isa_dma.c optional isa
|
||||
pc98/pc98/nmi.c standard
|
||||
pc98/pc98/olpt.c optional olpt
|
||||
pc98/pc98/machdep.c standard
|
||||
pc98/pc98/pc98_machdep.c standard
|
||||
pc98/pc98/pc98gdc.c optional gdc
|
||||
pc98/pc98/pc98kbd.c optional pckbd
|
||||
pc98/pc98/pmc.c optional pmc
|
||||
pc98/pc98/ppc.c optional ppc
|
||||
pc98/pc98/scgdcrndr.c optional sc gdc
|
||||
pc98/pc98/scterm-sck.c optional sc
|
||||
pc98/pc98/scvtbpc98.c optional sc
|
||||
pc98/pc98/sio.c optional sio
|
||||
pc98/pc98/sio_cbus.c optional sio isa
|
||||
pc98/pc98/syscons_pc98.c optional sc
|
||||
pccard/pccard.c optional card
|
||||
pccard/pccard_beep.c optional card
|
||||
pccard/pccard_nbk.c optional card
|
||||
|
@ -78,7 +78,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#include <compat/netbsd/dvcfg.h>
|
||||
|
@ -20,7 +20,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <isa/isavar.h>
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
/* machine-dependent part of the header */
|
||||
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/sc_machdep.h>
|
||||
#include <pc98/cbus/sc_machdep.h>
|
||||
#elif defined(__i386__)
|
||||
/* nothing for the moment */
|
||||
#elif defined(__alpha__)
|
||||
|
@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef DEV_ISA
|
||||
#include <isa/isavar.h>
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
@ -91,7 +91,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ic/i8259.h>
|
||||
#include <i386/isa/icu.h>
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/ucontext.h>
|
||||
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/asmacros.h>
|
||||
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <isa/isavar.h>
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
@ -4,8 +4,8 @@ KMOD= fdc
|
||||
WARNS?= 2
|
||||
|
||||
.if ${MACHINE} == "pc98"
|
||||
.PATH: ${.CURDIR}/../../pc98/pc98
|
||||
SRCS= fd.c fdc_cbus.c
|
||||
.PATH: ${.CURDIR}/../../pc98/cbus
|
||||
SRCS= fdc.c fdc_cbus.c
|
||||
.else
|
||||
.PATH: ${.CURDIR}/../../dev/fdc
|
||||
SRCS= fdc.c fdc_isa.c fdc_pccard.c
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../pc98/pc98
|
||||
.PATH: ${.CURDIR}/../../pc98/cbus
|
||||
|
||||
KMOD= pmc
|
||||
SRCS= pmc.c
|
||||
|
@ -1,7 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.if ${MACHINE} == "pc98"
|
||||
.PATH: ${.CURDIR}/../../pc98/pc98
|
||||
.PATH: ${.CURDIR}/../../pc98/cbus
|
||||
.endif
|
||||
.PATH: ${.CURDIR}/../../dev/sio
|
||||
|
||||
|
@ -60,9 +60,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <dev/ic/i8237.h>
|
||||
#include <isa/isavar.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
|
||||
/*
|
||||
** Register definitions for DMA controller 1 (channels 0..3):
|
||||
|
@ -81,7 +81,7 @@
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#ifdef DEV_ISA
|
||||
#include <isa/isavar.h>
|
||||
|
@ -78,11 +78,11 @@
|
||||
|
||||
#ifdef PC98
|
||||
#include <isa/isavar.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <pc98/cbus/fdcreg.h>
|
||||
#include <pc98/cbus/fdcvar.h>
|
||||
#include <pc98/pc98/epsonio.h>
|
||||
#include <pc98/pc98/fdreg.h>
|
||||
#include <pc98/pc98/fdcvar.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#else
|
||||
#include <isa/isavar.h>
|
||||
#include <isa/isareg.h>
|
||||
|
@ -39,11 +39,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <pc98/pc98/fdcvar.h>
|
||||
#include <pc98/pc98/fdreg.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <pc98/cbus/fdcreg.h>
|
||||
#include <pc98/cbus/fdcvar.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
|
||||
static bus_addr_t fdc_iat[] = {0, 2, 4};
|
||||
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include <dev/fb/fbreg.h>
|
||||
|
||||
#ifdef LINE30
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#endif
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#include <isa/isavar.h>
|
||||
@ -423,7 +423,7 @@ DRIVER_MODULE(gdc, isa, gdcdriver, gdc_devclass, 0, 0);
|
||||
/* LOW-LEVEL */
|
||||
|
||||
|
||||
#include <pc98/pc98/30line.h>
|
||||
#include <pc98/cbus/30line.h>
|
||||
|
||||
#define TEXT_BUF_BASE 0x000a0000
|
||||
#define TEXT_BUF_SIZE 0x00008000
|
||||
|
@ -43,8 +43,7 @@
|
||||
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#define DRIVER_NAME "pckbd"
|
||||
|
@ -81,7 +81,7 @@
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#ifdef DEV_ISA
|
||||
#include <isa/isavar.h>
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <sys/rman.h>
|
||||
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <isa/isareg.h>
|
||||
#endif
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
#include <dev/ppc/ppcvar.h>
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/ppcreg.h>
|
||||
#include <pc98/cbus/ppcreg.h>
|
||||
#else
|
||||
#include <dev/ppc/ppcreg.h>
|
||||
#endif
|
||||
|
@ -111,7 +111,7 @@
|
||||
#include <dev/sio/siovar.h>
|
||||
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#endif
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
|
||||
#include <dev/syscons/syscons.h>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,281 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $ */
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*-
|
||||
* [NetBSD for NEC PC-98 series]
|
||||
* Copyright (c) 1996, 1997, 1998
|
||||
* NetBSD/pc98 porting staff. All rights reserved.
|
||||
*
|
||||
* [Ported for FreeBSD]
|
||||
* Copyright (c) 2001
|
||||
* TAKAHASHI Yoshihiro. 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997, 1998
|
||||
* Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
|
||||
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int8_t,1)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int16_t,2)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int32_t,4)
|
||||
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int8_t,1)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int16_t,2)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int32_t,4)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int8_t,1)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4)
|
||||
|
||||
struct bus_space_tag SBUS_io_space_tag = {
|
||||
BUS_SPACE_IO,
|
||||
|
||||
/* direct bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int32_t,4),
|
||||
},
|
||||
|
||||
/* relocate bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int32_t,4),
|
||||
}
|
||||
};
|
||||
|
||||
struct bus_space_tag SBUS_mem_space_tag = {
|
||||
BUS_SPACE_MEM,
|
||||
|
||||
/* direct bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
|
||||
},
|
||||
|
||||
/* relocate bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#include "opt_mecia.h"
|
||||
#ifdef DEV_MECIA
|
||||
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int16_t,2)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int32_t,4)
|
||||
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2)
|
||||
_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4)
|
||||
|
||||
struct bus_space_tag NEPC_io_space_tag = {
|
||||
BUS_SPACE_IO,
|
||||
|
||||
/* direct bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int32_t,4),
|
||||
},
|
||||
|
||||
/* relocate bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int32_t,4),
|
||||
}
|
||||
};
|
||||
|
||||
struct bus_space_tag NEPC_mem_space_tag = {
|
||||
BUS_SPACE_MEM,
|
||||
|
||||
/* direct bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
|
||||
},
|
||||
|
||||
/* relocate bus access methods */
|
||||
{
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2),
|
||||
_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4),
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DEV_MECIA */
|
||||
|
||||
/*************************************************************************
|
||||
* map init
|
||||
*************************************************************************/
|
||||
static __inline void
|
||||
bus_space_iat_init(bus_space_handle_t bsh)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bsh->bsh_maxiatsz; i++)
|
||||
bsh->bsh_iat[i] = bsh->bsh_base + i;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* handle allocation
|
||||
*************************************************************************/
|
||||
int
|
||||
i386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
|
||||
bus_space_handle_t *bshp)
|
||||
{
|
||||
bus_space_handle_t bsh;
|
||||
|
||||
bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (bsh == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
|
||||
bsh->bsh_iatsz = 0;
|
||||
bsh->bsh_base = bpa;
|
||||
bsh->bsh_sz = size;
|
||||
bsh->bsh_res = NULL;
|
||||
bsh->bsh_ressz = 0;
|
||||
bus_space_iat_init(bsh);
|
||||
|
||||
bsh->bsh_bam = t->bs_da; /* default: direct access */
|
||||
|
||||
*bshp = bsh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
i386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh,
|
||||
size_t size)
|
||||
{
|
||||
|
||||
free(bsh, M_BUSSPACEHANDLE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* map
|
||||
*************************************************************************/
|
||||
int
|
||||
i386_memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
|
||||
bus_space_handle_t *bshp)
|
||||
{
|
||||
|
||||
return i386_bus_space_handle_alloc(t, bpa, size, bshp);
|
||||
}
|
||||
|
||||
void
|
||||
i386_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
|
||||
{
|
||||
|
||||
i386_bus_space_handle_free(t, bsh, bsh->bsh_sz);
|
||||
}
|
||||
|
||||
void
|
||||
i386_memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
|
||||
{
|
||||
|
||||
/* i386_memio_unmap() does all that we need to do. */
|
||||
i386_memio_unmap(t, bsh, bsh->bsh_sz);
|
||||
}
|
||||
|
||||
int
|
||||
i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh,
|
||||
bus_size_t offset, bus_size_t size,
|
||||
bus_space_handle_t *tbshp)
|
||||
{
|
||||
int i, error = 0;
|
||||
bus_space_handle_t bsh;
|
||||
bus_addr_t pbase;
|
||||
|
||||
pbase = pbsh->bsh_base + offset;
|
||||
switch (t->bs_tag) {
|
||||
case BUS_SPACE_IO:
|
||||
if (pbsh->bsh_iatsz > 0) {
|
||||
if (offset >= pbsh->bsh_iatsz ||
|
||||
offset + size > pbsh->bsh_iatsz)
|
||||
return EINVAL;
|
||||
pbase = pbsh->bsh_base;
|
||||
}
|
||||
break;
|
||||
|
||||
case BUS_SPACE_MEM:
|
||||
if (pbsh->bsh_iatsz > 0)
|
||||
return EINVAL;
|
||||
if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz)
|
||||
return EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("i386_memio_subregion: bad bus space tag");
|
||||
break;
|
||||
}
|
||||
|
||||
error = i386_bus_space_handle_alloc(t, pbase, size, &bsh);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
switch (t->bs_tag) {
|
||||
case BUS_SPACE_IO:
|
||||
if (pbsh->bsh_iatsz > 0) {
|
||||
for (i = 0; i < size; i ++)
|
||||
bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset];
|
||||
bsh->bsh_iatsz = size;
|
||||
} else if (pbsh->bsh_base > bsh->bsh_base ||
|
||||
pbsh->bsh_base + pbsh->bsh_sz <
|
||||
bsh->bsh_base + bsh->bsh_sz) {
|
||||
i386_bus_space_handle_free(t, bsh, size);
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case BUS_SPACE_MEM:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pbsh->bsh_iatsz > 0)
|
||||
bsh->bsh_bam = t->bs_ra; /* relocate access */
|
||||
*tbshp = bsh;
|
||||
return error;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,130 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1994, 1995, 1996. FreeBSD(98) porting team.
|
||||
* 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __PC98_PC98_30LINE_H__
|
||||
#define __PC98_PC98_30LINE_H__
|
||||
|
||||
#define LINE30_ROW 30
|
||||
#define _HS 1 + 1
|
||||
#define _VS 2
|
||||
#define _HFP 3 + 1
|
||||
#define _HBP 14 + 1
|
||||
#define _VFP 11
|
||||
#define _VBP 44
|
||||
|
||||
#define _CR 80
|
||||
#define _LF LINE30_ROW*16
|
||||
|
||||
#define _GDC_RESET 0x00
|
||||
#define _GDC_SYNC 0x0e
|
||||
#define _GDC_MASTER 0x6f
|
||||
#define _GDC_SLAVE 0x6e
|
||||
#define _GDC_START 0x0d
|
||||
#define _GDC_STOP 0x0c
|
||||
#define _GDC_SCROLL 0x70
|
||||
#define _GDC_PITCH 0x47
|
||||
|
||||
#define GDC_CR 0
|
||||
#define GDC_VS 1
|
||||
#define GDC_HS 2
|
||||
#define GDC_HFP 3
|
||||
#define GDC_HBP 4
|
||||
#define GDC_VFP 5
|
||||
#define GDC_VBP 6
|
||||
#define GDC_LF 7
|
||||
|
||||
|
||||
#define _24KHZ 0
|
||||
#define _31KHZ 1
|
||||
|
||||
#define _2_5MHZ 0
|
||||
#define _5MHZ 1
|
||||
|
||||
#define _25L 0
|
||||
#define _30L 1
|
||||
|
||||
#define T25_G400 0
|
||||
#define T30_G400 1
|
||||
#define T30_G480 2
|
||||
|
||||
static void master_gdc_cmd(unsigned int);
|
||||
static void master_gdc_prm(unsigned int);
|
||||
static void master_gdc_word_prm(unsigned int);
|
||||
#ifdef LINE30
|
||||
static void master_gdc_fifo_empty(void);
|
||||
#endif
|
||||
static void master_gdc_wait_vsync(void);
|
||||
|
||||
static void gdc_cmd(unsigned int);
|
||||
#ifdef LINE30
|
||||
static void gdc_prm(unsigned int);
|
||||
static void gdc_word_prm(unsigned int);
|
||||
static void gdc_fifo_empty(void);
|
||||
#endif
|
||||
static void gdc_wait_vsync(void);
|
||||
|
||||
#ifdef LINE30
|
||||
static int check_gdc_clock(void);
|
||||
|
||||
static int gdc_INFO = _25L;
|
||||
#endif
|
||||
static int gdc_FH = _24KHZ;
|
||||
static void initialize_gdc(unsigned int, int);
|
||||
|
||||
#ifdef LINE30
|
||||
static unsigned int master_param[2][2][8] = {
|
||||
{{78, 8, 7, 9, 7, 7, 25, 400}, /* 400/24k */
|
||||
{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}}, /* 480/24k */
|
||||
{{78, 2, 7, 3, 7, 13, 34, 400}, /* 400/31k */
|
||||
{78, 2, 11, 3, 3, 6, 37, 480}}}; /* 480/31k */
|
||||
|
||||
static unsigned int slave_param[2][6][8] = {
|
||||
{{38, 8, 3, 4, 3, 7, 25, 400}, /* normal */
|
||||
{78, 8, 7, 9, 7, 7, 25, 400},
|
||||
{_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
|
||||
_VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400}, /* 30 & 400 */
|
||||
{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1,
|
||||
_VFP+(_LF-400)/2+8, _VBP+(_LF-400)/2-8, 400},
|
||||
{_CR/2-2, _VS, (_HS)/2-1, (_HFP)/2-1, (_HBP)/2-1,
|
||||
_VFP, _VBP, _LF}, /* 30 & 480 */
|
||||
{_CR-2, _VS, _HS-1, _HFP-1, _HBP-1, _VFP, _VBP, _LF}},
|
||||
{{38, 2, 3, 1, 3, 13, 34, 400}, /* normal */
|
||||
{78, 2, 7, 3, 7, 13, 34, 400},
|
||||
{38, 2, 5, 1, 1, 6+48, 37+32, 400}, /* 30 & 400 */
|
||||
{78, 2, 11, 3, 3, 6+48, 37+32, 400},
|
||||
{38, 2, 5, 1, 1, 6, 37, 480}, /* 30 & 480 */
|
||||
{78, 2, 11, 3, 3, 6, 37, 480}}};
|
||||
|
||||
static int SlavePCH[2] = {40,80};
|
||||
static int MasterPCH = 80;
|
||||
static int SlaveScrlLF[3] = {400,400,_LF};
|
||||
#endif
|
||||
|
||||
#endif /* __PC98_PC98_30LINE_H__ */
|
@ -1,885 +0,0 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Routines to handle clock hardware.
|
||||
*/
|
||||
|
||||
/*
|
||||
* inittodr, settodr and support routines written
|
||||
* by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
|
||||
*
|
||||
* reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* modified for PC98 by Kakefuda
|
||||
*/
|
||||
|
||||
#include "opt_apic.h"
|
||||
#include "opt_clock.h"
|
||||
#include "opt_isa.h"
|
||||
#include "opt_mca.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/power.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
#include <machine/cputypes.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/psl.h>
|
||||
#ifdef DEV_APIC
|
||||
#include <machine/apicvar.h>
|
||||
#endif
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
#include <i386/isa/icu.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#ifdef DEV_ISA
|
||||
#include <isa/isavar.h>
|
||||
#endif
|
||||
#include <i386/isa/timerreg.h>
|
||||
|
||||
/*
|
||||
* 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
|
||||
* can use a simple formula for leap years.
|
||||
*/
|
||||
#define LEAPYEAR(y) (((u_int)(y) % 4 == 0) ? 1 : 0)
|
||||
#define DAYSPERYEAR (31+28+31+30+31+30+31+31+30+31+30+31)
|
||||
|
||||
#define TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
|
||||
|
||||
int adjkerntz; /* local offset from GMT in seconds */
|
||||
int clkintr_pending;
|
||||
int disable_rtc_set; /* disable resettodr() if != 0 */
|
||||
int pscnt = 1;
|
||||
int psdiv = 1;
|
||||
int statclock_disable;
|
||||
#ifndef TIMER_FREQ
|
||||
#define TIMER_FREQ 2457600
|
||||
#endif
|
||||
u_int timer_freq = TIMER_FREQ;
|
||||
int timer0_max_count;
|
||||
int wall_cmos_clock; /* wall CMOS clock assumed if != 0 */
|
||||
struct mtx clock_lock;
|
||||
|
||||
static int beeping = 0;
|
||||
static const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
|
||||
static u_int hardclock_max_count;
|
||||
static struct intsrc *i8254_intsrc;
|
||||
static u_int32_t i8254_lastcount;
|
||||
static u_int32_t i8254_offset;
|
||||
static int (*i8254_pending)(struct intsrc *);
|
||||
static int i8254_ticked;
|
||||
static int using_lapic_timer;
|
||||
|
||||
/* Values for timerX_state: */
|
||||
#define RELEASED 0
|
||||
#define RELEASE_PENDING 1
|
||||
#define ACQUIRED 2
|
||||
#define ACQUIRE_PENDING 3
|
||||
|
||||
static u_char timer1_state;
|
||||
static u_char timer2_state;
|
||||
static void rtc_serialcombit(int);
|
||||
static void rtc_serialcom(int);
|
||||
static int rtc_inb(void);
|
||||
static void rtc_outb(int);
|
||||
|
||||
static unsigned i8254_get_timecount(struct timecounter *tc);
|
||||
static void set_timer_freq(u_int freq, int intr_freq);
|
||||
|
||||
static struct timecounter i8254_timecounter = {
|
||||
i8254_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
~0u, /* counter_mask */
|
||||
0, /* frequency */
|
||||
"i8254", /* name */
|
||||
0 /* quality */
|
||||
};
|
||||
|
||||
static void
|
||||
clkintr(struct clockframe *frame)
|
||||
{
|
||||
|
||||
if (timecounter->tc_get_timecount == i8254_get_timecount) {
|
||||
mtx_lock_spin(&clock_lock);
|
||||
if (i8254_ticked)
|
||||
i8254_ticked = 0;
|
||||
else {
|
||||
i8254_offset += timer0_max_count;
|
||||
i8254_lastcount = 0;
|
||||
}
|
||||
clkintr_pending = 0;
|
||||
mtx_unlock_spin(&clock_lock);
|
||||
}
|
||||
if (!using_lapic_timer)
|
||||
hardclock(frame);
|
||||
}
|
||||
|
||||
int
|
||||
acquire_timer1(int mode)
|
||||
{
|
||||
|
||||
if (timer1_state != RELEASED)
|
||||
return (-1);
|
||||
timer1_state = ACQUIRED;
|
||||
|
||||
/*
|
||||
* This access to the timer registers is as atomic as possible
|
||||
* because it is a single instruction. We could do better if we
|
||||
* knew the rate. Use of splclock() limits glitches to 10-100us,
|
||||
* and this is probably good enough for timer2, so we aren't as
|
||||
* careful with it as with timer0.
|
||||
*/
|
||||
outb(TIMER_MODE, TIMER_SEL1 | (mode & 0x3f));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
acquire_timer2(int mode)
|
||||
{
|
||||
|
||||
if (timer2_state != RELEASED)
|
||||
return (-1);
|
||||
timer2_state = ACQUIRED;
|
||||
|
||||
/*
|
||||
* This access to the timer registers is as atomic as possible
|
||||
* because it is a single instruction. We could do better if we
|
||||
* knew the rate. Use of splclock() limits glitches to 10-100us,
|
||||
* and this is probably good enough for timer2, so we aren't as
|
||||
* careful with it as with timer0.
|
||||
*/
|
||||
outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
release_timer1()
|
||||
{
|
||||
|
||||
if (timer1_state != ACQUIRED)
|
||||
return (-1);
|
||||
timer1_state = RELEASED;
|
||||
outb(TIMER_MODE, TIMER_SEL1 | TIMER_SQWAVE | TIMER_16BIT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
release_timer2()
|
||||
{
|
||||
|
||||
if (timer2_state != ACQUIRED)
|
||||
return (-1);
|
||||
timer2_state = RELEASED;
|
||||
outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getit(void)
|
||||
{
|
||||
int high, low;
|
||||
|
||||
mtx_lock_spin(&clock_lock);
|
||||
|
||||
/* Select timer0 and latch counter value. */
|
||||
outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
|
||||
|
||||
low = inb(TIMER_CNTR0);
|
||||
high = inb(TIMER_CNTR0);
|
||||
|
||||
mtx_unlock_spin(&clock_lock);
|
||||
return ((high << 8) | low);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait "n" microseconds.
|
||||
* Relies on timer 1 counting down from (timer_freq / hz)
|
||||
* Note: timer had better have been programmed before this is first used!
|
||||
*/
|
||||
void
|
||||
DELAY(int n)
|
||||
{
|
||||
int delta, prev_tick, tick, ticks_left;
|
||||
|
||||
#ifdef DELAYDEBUG
|
||||
int getit_calls = 1;
|
||||
int n1;
|
||||
static int state = 0;
|
||||
|
||||
if (state == 0) {
|
||||
state = 1;
|
||||
for (n1 = 1; n1 <= 10000000; n1 *= 10)
|
||||
DELAY(n1);
|
||||
state = 2;
|
||||
}
|
||||
if (state == 1)
|
||||
printf("DELAY(%d)...", n);
|
||||
#endif
|
||||
/*
|
||||
* Guard against the timer being uninitialized if we are called
|
||||
* early for console i/o.
|
||||
*/
|
||||
if (timer0_max_count == 0)
|
||||
set_timer_freq(timer_freq, hz);
|
||||
|
||||
/*
|
||||
* Read the counter first, so that the rest of the setup overhead is
|
||||
* counted. Guess the initial overhead is 20 usec (on most systems it
|
||||
* takes about 1.5 usec for each of the i/o's in getit(). The loop
|
||||
* takes about 6 usec on a 486/33 and 13 usec on a 386/20. The
|
||||
* multiplications and divisions to scale the count take a while).
|
||||
*
|
||||
* However, if ddb is active then use a fake counter since reading
|
||||
* the i8254 counter involves acquiring a lock. ddb must not do
|
||||
* locking for many reasons, but it calls here for at least atkbd
|
||||
* input.
|
||||
*/
|
||||
#ifdef KDB
|
||||
if (kdb_active)
|
||||
prev_tick = 1;
|
||||
else
|
||||
#endif
|
||||
prev_tick = getit();
|
||||
n -= 0; /* XXX actually guess no initial overhead */
|
||||
/*
|
||||
* Calculate (n * (timer_freq / 1e6)) without using floating point
|
||||
* and without any avoidable overflows.
|
||||
*/
|
||||
if (n <= 0)
|
||||
ticks_left = 0;
|
||||
else if (n < 256)
|
||||
/*
|
||||
* Use fixed point to avoid a slow division by 1000000.
|
||||
* 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
|
||||
* 2^15 is the first power of 2 that gives exact results
|
||||
* for n between 0 and 256.
|
||||
*/
|
||||
ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
|
||||
else
|
||||
/*
|
||||
* Don't bother using fixed point, although gcc-2.7.2
|
||||
* generates particularly poor code for the long long
|
||||
* division, since even the slow way will complete long
|
||||
* before the delay is up (unless we're interrupted).
|
||||
*/
|
||||
ticks_left = ((u_int)n * (long long)timer_freq + 999999)
|
||||
/ 1000000;
|
||||
|
||||
while (ticks_left > 0) {
|
||||
#ifdef KDB
|
||||
if (kdb_active) {
|
||||
outb(0x5f, 0);
|
||||
tick = prev_tick - 1;
|
||||
if (tick <= 0)
|
||||
tick = timer0_max_count;
|
||||
} else
|
||||
#endif
|
||||
tick = getit();
|
||||
#ifdef DELAYDEBUG
|
||||
++getit_calls;
|
||||
#endif
|
||||
delta = prev_tick - tick;
|
||||
prev_tick = tick;
|
||||
if (delta < 0) {
|
||||
delta += timer0_max_count;
|
||||
/*
|
||||
* Guard against timer0_max_count being wrong.
|
||||
* This shouldn't happen in normal operation,
|
||||
* but it may happen if set_timer_freq() is
|
||||
* traced.
|
||||
*/
|
||||
if (delta < 0)
|
||||
delta = 0;
|
||||
}
|
||||
ticks_left -= delta;
|
||||
}
|
||||
#ifdef DELAYDEBUG
|
||||
if (state == 1)
|
||||
printf(" %d calls to getit() at %d usec each\n",
|
||||
getit_calls, (n + 5) / getit_calls);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
sysbeepstop(void *chan)
|
||||
{
|
||||
outb(IO_PPI, inb(IO_PPI)|0x08); /* disable counter1 output to speaker */
|
||||
release_timer1();
|
||||
beeping = 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysbeep(int pitch, int period)
|
||||
{
|
||||
int x = splclock();
|
||||
|
||||
if (acquire_timer1(TIMER_SQWAVE|TIMER_16BIT))
|
||||
if (!beeping) {
|
||||
/* Something else owns it. */
|
||||
splx(x);
|
||||
return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
|
||||
}
|
||||
disable_intr();
|
||||
outb(0x3fdb, pitch);
|
||||
outb(0x3fdb, (pitch>>8));
|
||||
enable_intr();
|
||||
if (!beeping) {
|
||||
/* enable counter1 output to speaker */
|
||||
outb(IO_PPI, (inb(IO_PPI) & 0xf7));
|
||||
beeping = period;
|
||||
timeout(sysbeepstop, (void *)NULL, period);
|
||||
}
|
||||
splx(x);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
unsigned int delaycount;
|
||||
#define FIRST_GUESS 0x2000
|
||||
static void findcpuspeed(void)
|
||||
{
|
||||
int i;
|
||||
int remainder;
|
||||
|
||||
/* Put counter in count down mode */
|
||||
outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
|
||||
outb(TIMER_CNTR0, 0xff);
|
||||
outb(TIMER_CNTR0, 0xff);
|
||||
for (i = FIRST_GUESS; i; i--)
|
||||
;
|
||||
remainder = getit();
|
||||
delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff - remainder);
|
||||
}
|
||||
|
||||
static u_int
|
||||
calibrate_clocks(void)
|
||||
{
|
||||
int timeout;
|
||||
u_int count, prev_count, tot_count;
|
||||
u_short sec, start_sec;
|
||||
|
||||
if (bootverbose)
|
||||
printf("Calibrating clock(s) ... ");
|
||||
/* Check ARTIC. */
|
||||
if (!(PC98_SYSTEM_PARAMETER(0x458) & 0x80) &&
|
||||
!(PC98_SYSTEM_PARAMETER(0x45b) & 0x04))
|
||||
goto fail;
|
||||
timeout = 100000000;
|
||||
|
||||
/* Read the ARTIC. */
|
||||
sec = inw(0x5e);
|
||||
|
||||
/* Wait for the ARTIC to changes. */
|
||||
start_sec = sec;
|
||||
for (;;) {
|
||||
sec = inw(0x5e);
|
||||
if (sec != start_sec)
|
||||
break;
|
||||
if (--timeout == 0)
|
||||
goto fail;
|
||||
}
|
||||
prev_count = getit();
|
||||
if (prev_count == 0 || prev_count > timer0_max_count)
|
||||
goto fail;
|
||||
tot_count = 0;
|
||||
|
||||
start_sec = sec;
|
||||
for (;;) {
|
||||
sec = inw(0x5e);
|
||||
count = getit();
|
||||
if (count == 0 || count > timer0_max_count)
|
||||
goto fail;
|
||||
if (count > prev_count)
|
||||
tot_count += prev_count - (count - timer0_max_count);
|
||||
else
|
||||
tot_count += prev_count - count;
|
||||
prev_count = count;
|
||||
if ((sec == start_sec + 1200) || /* 1200 = 307.2KHz >> 8 */
|
||||
(sec < start_sec &&
|
||||
(u_int)sec + 0x10000 == (u_int)start_sec + 1200))
|
||||
break;
|
||||
if (--timeout == 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (bootverbose) {
|
||||
printf("i8254 clock: %u Hz\n", tot_count);
|
||||
}
|
||||
return (tot_count);
|
||||
|
||||
fail:
|
||||
if (bootverbose)
|
||||
printf("failed, using default i8254 clock of %u Hz\n",
|
||||
timer_freq);
|
||||
return (timer_freq);
|
||||
}
|
||||
|
||||
static void
|
||||
set_timer_freq(u_int freq, int intr_freq)
|
||||
{
|
||||
int new_timer0_max_count;
|
||||
|
||||
mtx_lock_spin(&clock_lock);
|
||||
timer_freq = freq;
|
||||
new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq);
|
||||
if (new_timer0_max_count != timer0_max_count) {
|
||||
timer0_max_count = new_timer0_max_count;
|
||||
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
|
||||
outb(TIMER_CNTR0, timer0_max_count & 0xff);
|
||||
outb(TIMER_CNTR0, timer0_max_count >> 8);
|
||||
}
|
||||
mtx_unlock_spin(&clock_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
i8254_restore(void)
|
||||
{
|
||||
|
||||
mtx_lock_spin(&clock_lock);
|
||||
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
|
||||
outb(TIMER_CNTR0, timer0_max_count & 0xff);
|
||||
outb(TIMER_CNTR0, timer0_max_count >> 8);
|
||||
mtx_unlock_spin(&clock_lock);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Restore all the timers non-atomically (XXX: should be atomically).
|
||||
*
|
||||
* This function is called from pmtimer_resume() to restore all the timers.
|
||||
* This should not be necessary, but there are broken laptops that do not
|
||||
* restore all the timers on resume.
|
||||
*/
|
||||
void
|
||||
timer_restore(void)
|
||||
{
|
||||
|
||||
i8254_restore(); /* restore timer_freq and hz */
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize 8254 timer 0 early so that it can be used in DELAY().
|
||||
* XXX initialization of other timers is unintentionally left blank.
|
||||
*/
|
||||
void
|
||||
startrtclock()
|
||||
{
|
||||
u_int delta, freq;
|
||||
|
||||
findcpuspeed();
|
||||
if (pc98_machine_type & M_8M)
|
||||
timer_freq = 1996800L; /* 1.9968 MHz */
|
||||
else
|
||||
timer_freq = 2457600L; /* 2.4576 MHz */
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
freq = calibrate_clocks();
|
||||
#ifdef CLK_CALIBRATION_LOOP
|
||||
if (bootverbose) {
|
||||
printf(
|
||||
"Press a key on the console to abort clock calibration\n");
|
||||
while (cncheckc() == -1)
|
||||
calibrate_clocks();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use the calibrated i8254 frequency if it seems reasonable.
|
||||
* Otherwise use the default, and don't use the calibrated i586
|
||||
* frequency.
|
||||
*/
|
||||
delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq;
|
||||
if (delta < timer_freq / 100) {
|
||||
#ifndef CLK_USE_I8254_CALIBRATION
|
||||
if (bootverbose)
|
||||
printf(
|
||||
"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n");
|
||||
freq = timer_freq;
|
||||
#endif
|
||||
timer_freq = freq;
|
||||
} else {
|
||||
if (bootverbose)
|
||||
printf(
|
||||
"%d Hz differs from default of %d Hz by more than 1%%\n",
|
||||
freq, timer_freq);
|
||||
}
|
||||
|
||||
set_timer_freq(timer_freq, hz);
|
||||
i8254_timecounter.tc_frequency = timer_freq;
|
||||
tc_init(&i8254_timecounter);
|
||||
|
||||
init_TSC();
|
||||
}
|
||||
|
||||
static void
|
||||
rtc_serialcombit(int i)
|
||||
{
|
||||
outb(IO_RTC, ((i&0x01)<<5)|0x07);
|
||||
DELAY(1);
|
||||
outb(IO_RTC, ((i&0x01)<<5)|0x17);
|
||||
DELAY(1);
|
||||
outb(IO_RTC, ((i&0x01)<<5)|0x07);
|
||||
DELAY(1);
|
||||
}
|
||||
|
||||
static void
|
||||
rtc_serialcom(int i)
|
||||
{
|
||||
rtc_serialcombit(i&0x01);
|
||||
rtc_serialcombit((i&0x02)>>1);
|
||||
rtc_serialcombit((i&0x04)>>2);
|
||||
rtc_serialcombit((i&0x08)>>3);
|
||||
outb(IO_RTC, 0x07);
|
||||
DELAY(1);
|
||||
outb(IO_RTC, 0x0f);
|
||||
DELAY(1);
|
||||
outb(IO_RTC, 0x07);
|
||||
DELAY(1);
|
||||
}
|
||||
|
||||
static void
|
||||
rtc_outb(int val)
|
||||
{
|
||||
int s;
|
||||
int sa = 0;
|
||||
|
||||
for (s=0;s<8;s++) {
|
||||
sa = ((val >> s) & 0x01) ? 0x27 : 0x07;
|
||||
outb(IO_RTC, sa); /* set DI & CLK 0 */
|
||||
DELAY(1);
|
||||
outb(IO_RTC, sa | 0x10); /* CLK 1 */
|
||||
DELAY(1);
|
||||
}
|
||||
outb(IO_RTC, sa & 0xef); /* CLK 0 */
|
||||
}
|
||||
|
||||
static int
|
||||
rtc_inb(void)
|
||||
{
|
||||
int s;
|
||||
int sa = 0;
|
||||
|
||||
for (s=0;s<8;s++) {
|
||||
sa |= ((inb(0x33) & 0x01) << s);
|
||||
outb(IO_RTC, 0x17); /* CLK 1 */
|
||||
DELAY(1);
|
||||
outb(IO_RTC, 0x07); /* CLK 0 */
|
||||
DELAY(2);
|
||||
}
|
||||
return sa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the time of day register, based on the time base which is, e.g.
|
||||
* from a filesystem.
|
||||
*/
|
||||
void
|
||||
inittodr(time_t base)
|
||||
{
|
||||
unsigned long sec, days;
|
||||
int year, month;
|
||||
int y, m, s;
|
||||
struct timespec ts;
|
||||
int second, min, hour;
|
||||
|
||||
if (base) {
|
||||
s = splclock();
|
||||
ts.tv_sec = base;
|
||||
ts.tv_nsec = 0;
|
||||
tc_setclock(&ts);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
rtc_serialcom(0x03); /* Time Read */
|
||||
rtc_serialcom(0x01); /* Register shift command. */
|
||||
DELAY(20);
|
||||
|
||||
second = bcd2bin(rtc_inb() & 0xff); /* sec */
|
||||
min = bcd2bin(rtc_inb() & 0xff); /* min */
|
||||
hour = bcd2bin(rtc_inb() & 0xff); /* hour */
|
||||
days = bcd2bin(rtc_inb() & 0xff) - 1; /* date */
|
||||
|
||||
month = (rtc_inb() >> 4) & 0x0f; /* month */
|
||||
for (m = 1; m < month; m++)
|
||||
days += daysinmonth[m-1];
|
||||
year = bcd2bin(rtc_inb() & 0xff) + 1900; /* year */
|
||||
/* 2000 year problem */
|
||||
if (year < 1995)
|
||||
year += 100;
|
||||
if (year < 1970)
|
||||
goto wrong_time;
|
||||
for (y = 1970; y < year; y++)
|
||||
days += DAYSPERYEAR + LEAPYEAR(y);
|
||||
if ((month > 2) && LEAPYEAR(year))
|
||||
days ++;
|
||||
sec = ((( days * 24 +
|
||||
hour) * 60 +
|
||||
min) * 60 +
|
||||
second);
|
||||
/* sec now contains the number of seconds, since Jan 1 1970,
|
||||
in the local time zone */
|
||||
|
||||
s = splhigh();
|
||||
|
||||
sec += tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
|
||||
|
||||
y = time_second - sec;
|
||||
if (y <= -2 || y >= 2) {
|
||||
/* badly off, adjust it */
|
||||
ts.tv_sec = sec;
|
||||
ts.tv_nsec = 0;
|
||||
tc_setclock(&ts);
|
||||
}
|
||||
splx(s);
|
||||
return;
|
||||
|
||||
wrong_time:
|
||||
printf("Invalid time in real time clock.\n");
|
||||
printf("Check and reset the date immediately!\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Write system time back to RTC
|
||||
*/
|
||||
void
|
||||
resettodr()
|
||||
{
|
||||
unsigned long tm;
|
||||
int y, m, s;
|
||||
int wd;
|
||||
|
||||
if (disable_rtc_set)
|
||||
return;
|
||||
|
||||
s = splclock();
|
||||
tm = time_second;
|
||||
splx(s);
|
||||
|
||||
rtc_serialcom(0x01); /* Register shift command. */
|
||||
|
||||
/* Calculate local time to put in RTC */
|
||||
|
||||
tm -= tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0);
|
||||
|
||||
rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Seconds */
|
||||
rtc_outb(bin2bcd(tm%60)); tm /= 60; /* Write back Minutes */
|
||||
rtc_outb(bin2bcd(tm%24)); tm /= 24; /* Write back Hours */
|
||||
|
||||
/* We have now the days since 01-01-1970 in tm */
|
||||
wd = (tm + 4) % 7 + 1; /* Write back Weekday */
|
||||
for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
|
||||
tm >= m;
|
||||
y++, m = DAYSPERYEAR + LEAPYEAR(y))
|
||||
tm -= m;
|
||||
|
||||
/* Now we have the years in y and the day-of-the-year in tm */
|
||||
for (m = 0; ; m++) {
|
||||
int ml;
|
||||
|
||||
ml = daysinmonth[m];
|
||||
if (m == 1 && LEAPYEAR(y))
|
||||
ml++;
|
||||
if (tm < ml)
|
||||
break;
|
||||
tm -= ml;
|
||||
}
|
||||
|
||||
m++;
|
||||
rtc_outb(bin2bcd(tm+1)); /* Write back Day */
|
||||
rtc_outb((m << 4) | wd); /* Write back Month & Weekday */
|
||||
rtc_outb(bin2bcd(y%100)); /* Write back Year */
|
||||
|
||||
rtc_serialcom(0x02); /* Time set & Counter hold command. */
|
||||
rtc_serialcom(0x00); /* Register hold command. */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Start both clocks running.
|
||||
*/
|
||||
void
|
||||
cpu_initclocks()
|
||||
{
|
||||
|
||||
#ifdef DEV_APIC
|
||||
using_lapic_timer = lapic_setup_clock();
|
||||
#endif
|
||||
/*
|
||||
* If we aren't using the local APIC timer to drive the kernel
|
||||
* clocks, setup the interrupt handler for the 8254 timer 0 so
|
||||
* that it can drive hardclock().
|
||||
*/
|
||||
if (!using_lapic_timer) {
|
||||
intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL,
|
||||
INTR_TYPE_CLK | INTR_FAST, NULL);
|
||||
i8254_intsrc = intr_lookup_source(0);
|
||||
if (i8254_intsrc != NULL)
|
||||
i8254_pending =
|
||||
i8254_intsrc->is_pic->pic_source_pending;
|
||||
}
|
||||
|
||||
init_TSC_tc();
|
||||
}
|
||||
|
||||
void
|
||||
cpu_startprofclock(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
cpu_stopprofclock(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
int error;
|
||||
u_int freq;
|
||||
|
||||
/*
|
||||
* Use `i8254' instead of `timer' in external names because `timer'
|
||||
* is is too generic. Should use it everywhere.
|
||||
*/
|
||||
freq = timer_freq;
|
||||
error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
|
||||
if (error == 0 && req->newptr != NULL) {
|
||||
set_timer_freq(freq, hz);
|
||||
i8254_timecounter.tc_frequency = freq;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
|
||||
0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
|
||||
|
||||
static unsigned
|
||||
i8254_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
u_int count;
|
||||
u_int high, low;
|
||||
u_int eflags;
|
||||
|
||||
eflags = read_eflags();
|
||||
mtx_lock_spin(&clock_lock);
|
||||
|
||||
/* Select timer0 and latch counter value. */
|
||||
outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
|
||||
|
||||
low = inb(TIMER_CNTR0);
|
||||
high = inb(TIMER_CNTR0);
|
||||
count = timer0_max_count - ((high << 8) | low);
|
||||
if (count < i8254_lastcount ||
|
||||
(!i8254_ticked && (clkintr_pending ||
|
||||
((count < 20 || (!(eflags & PSL_I) && count < timer0_max_count / 2u)) &&
|
||||
i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
|
||||
i8254_ticked = 1;
|
||||
i8254_offset += timer0_max_count;
|
||||
}
|
||||
i8254_lastcount = count;
|
||||
count += i8254_offset;
|
||||
mtx_unlock_spin(&clock_lock);
|
||||
return (count);
|
||||
}
|
||||
|
||||
#ifdef DEV_ISA
|
||||
/*
|
||||
* Attach to the ISA PnP descriptors for the timer and realtime clock.
|
||||
*/
|
||||
static struct isa_pnp_id attimer_ids[] = {
|
||||
{ 0x0001d041 /* PNP0100 */, "AT timer" },
|
||||
{ 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
attimer_probe(device_t dev)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0)
|
||||
device_quiet(dev);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int
|
||||
attimer_attach(device_t dev)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
static device_method_t attimer_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, attimer_probe),
|
||||
DEVMETHOD(device_attach, attimer_attach),
|
||||
DEVMETHOD(device_detach, bus_generic_detach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX stop statclock? */
|
||||
DEVMETHOD(device_resume, bus_generic_resume), /* XXX restart statclock? */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t attimer_driver = {
|
||||
"attimer",
|
||||
attimer_methods,
|
||||
1, /* no softc */
|
||||
};
|
||||
|
||||
static devclass_t attimer_devclass;
|
||||
|
||||
DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
|
||||
#endif /* DEV_ISA */
|
2794
sys/pc98/pc98/fd.c
2794
sys/pc98/pc98/fd.c
File diff suppressed because it is too large
Load Diff
@ -1,174 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Yoshihiro TAKAHASHI
|
||||
* 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,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <pc98/pc98/fdcvar.h>
|
||||
#include <pc98/pc98/fdreg.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
|
||||
static bus_addr_t fdc_iat[] = {0, 2, 4};
|
||||
|
||||
static int
|
||||
fdc_cbus_alloc_resources(device_t dev, struct fdc_data *fdc)
|
||||
{
|
||||
int rid;
|
||||
|
||||
fdc->fdc_dev = dev;
|
||||
fdc->rid_ioport = 0;
|
||||
fdc->rid_irq = 0;
|
||||
fdc->rid_drq = 0;
|
||||
fdc->res_irq = 0;
|
||||
fdc->res_drq = 0;
|
||||
|
||||
fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
|
||||
&fdc->rid_ioport, fdc_iat,
|
||||
3, RF_ACTIVE);
|
||||
if (fdc->res_ioport == 0) {
|
||||
device_printf(dev, "cannot reserve I/O port range\n");
|
||||
return ENXIO;
|
||||
}
|
||||
isa_load_resourcev(fdc->res_ioport, fdc_iat, 3);
|
||||
fdc->portt = rman_get_bustag(fdc->res_ioport);
|
||||
fdc->porth = rman_get_bushandle(fdc->res_ioport);
|
||||
|
||||
rid = 3;
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, rid, IO_FDPORT, 1);
|
||||
fdc->res_fdsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
|
||||
RF_ACTIVE);
|
||||
if (fdc->res_fdsio == 0)
|
||||
return ENXIO;
|
||||
fdc->sc_fdsiot = rman_get_bustag(fdc->res_fdsio);
|
||||
fdc->sc_fdsioh = rman_get_bushandle(fdc->res_fdsio);
|
||||
|
||||
rid = 4;
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4be, 1);
|
||||
fdc->res_fdemsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
|
||||
RF_ACTIVE);
|
||||
if (fdc->res_fdemsio == 0)
|
||||
return ENXIO;
|
||||
fdc->sc_fdemsiot = rman_get_bustag(fdc->res_fdemsio);
|
||||
fdc->sc_fdemsioh = rman_get_bushandle(fdc->res_fdemsio);
|
||||
|
||||
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
|
||||
RF_ACTIVE);
|
||||
if (fdc->res_irq == 0) {
|
||||
device_printf(dev, "cannot reserve interrupt line\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
if ((fdc->flags & FDC_NODMA) == 0) {
|
||||
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
|
||||
&fdc->rid_drq, RF_ACTIVE);
|
||||
if (fdc->res_drq == 0) {
|
||||
device_printf(dev, "cannot reserve DMA request line\n");
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->dmachan = rman_get_start(fdc->res_drq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
fdc_cbus_probe(device_t dev)
|
||||
{
|
||||
int error;
|
||||
struct fdc_data *fdc;
|
||||
|
||||
fdc = device_get_softc(dev);
|
||||
|
||||
/* Check pnp ids */
|
||||
if (isa_get_vendorid(dev))
|
||||
return (ENXIO);
|
||||
|
||||
/* Attempt to allocate our resources for the duration of the probe */
|
||||
error = fdc_cbus_alloc_resources(dev, fdc);
|
||||
if (!error)
|
||||
error = fdc_initial_reset(fdc);
|
||||
|
||||
fdc_release_resources(fdc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
fdc_cbus_attach(device_t dev)
|
||||
{
|
||||
struct fdc_data *fdc;
|
||||
int error;
|
||||
|
||||
fdc = device_get_softc(dev);
|
||||
|
||||
if ((error = fdc_cbus_alloc_resources(dev, fdc)) != 0 ||
|
||||
(error = fdc_attach(dev)) != 0 ||
|
||||
(error = fdc_hints_probe(dev)) != 0) {
|
||||
fdc_release_resources(fdc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t fdc_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, fdc_cbus_probe),
|
||||
DEVMETHOD(device_attach, fdc_cbus_attach),
|
||||
DEVMETHOD(device_detach, fdc_detach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, fdc_print_child),
|
||||
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, fdc_write_ivar),
|
||||
/* Our children never use any other bus interface methods. */
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t fdc_driver = {
|
||||
"fdc",
|
||||
fdc_methods,
|
||||
sizeof(struct fdc_data)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
|
@ -1,167 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 M. Warner Losh.
|
||||
* 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,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* XXX should audit this file to see if additional copyrights needed */
|
||||
|
||||
enum fdc_type
|
||||
{
|
||||
FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
|
||||
};
|
||||
|
||||
enum fdc_states {
|
||||
DEVIDLE,
|
||||
FINDWORK,
|
||||
DOSEEK,
|
||||
SEEKCOMPLETE ,
|
||||
IOCOMPLETE,
|
||||
RECALCOMPLETE,
|
||||
STARTRECAL,
|
||||
RESETCTLR,
|
||||
SEEKWAIT,
|
||||
RECALWAIT,
|
||||
MOTORWAIT,
|
||||
IOTIMEDOUT,
|
||||
RESETCOMPLETE,
|
||||
PIOREAD
|
||||
};
|
||||
|
||||
#ifdef FDC_DEBUG
|
||||
static char const * const fdstates[] = {
|
||||
"DEVIDLE",
|
||||
"FINDWORK",
|
||||
"DOSEEK",
|
||||
"SEEKCOMPLETE",
|
||||
"IOCOMPLETE",
|
||||
"RECALCOMPLETE",
|
||||
"STARTRECAL",
|
||||
"RESETCTLR",
|
||||
"SEEKWAIT",
|
||||
"RECALWAIT",
|
||||
"MOTORWAIT",
|
||||
"IOTIMEDOUT",
|
||||
"RESETCOMPLETE",
|
||||
"PIOREAD"
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Per controller structure (softc).
|
||||
*/
|
||||
struct fdc_data
|
||||
{
|
||||
int fdcu; /* our unit number */
|
||||
int dmacnt;
|
||||
int dmachan;
|
||||
int flags;
|
||||
#define FDC_STAT_VALID 0x08
|
||||
#define FDC_HAS_FIFO 0x10
|
||||
#define FDC_NEEDS_RESET 0x20
|
||||
#define FDC_NODMA 0x40
|
||||
#define FDC_ISPNP 0x80
|
||||
#define FDC_ISPCMCIA 0x100
|
||||
struct fd_data *fd;
|
||||
int fdu; /* the active drive */
|
||||
enum fdc_states state;
|
||||
int retry;
|
||||
#ifndef PC98
|
||||
int fdout; /* mirror of the w/o digital output reg */
|
||||
#endif
|
||||
u_int status[7]; /* copy of the registers */
|
||||
enum fdc_type fdct; /* chip version of FDC */
|
||||
int fdc_errs; /* number of logged errors */
|
||||
int dma_overruns; /* number of DMA overruns */
|
||||
struct bio_queue_head head;
|
||||
struct bio *bp; /* active buffer */
|
||||
#ifdef PC98
|
||||
struct resource *res_ioport, *res_fdsio, *res_fdemsio;
|
||||
struct resource *res_irq, *res_drq;
|
||||
int rid_ioport, rid_irq, rid_drq;
|
||||
#else
|
||||
struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
|
||||
int rid_ioport, rid_ctl, rid_irq, rid_drq;
|
||||
#endif
|
||||
int port_off;
|
||||
bus_space_tag_t portt;
|
||||
bus_space_handle_t porth;
|
||||
#ifdef PC98
|
||||
bus_space_tag_t sc_fdsiot;
|
||||
bus_space_handle_t sc_fdsioh;
|
||||
bus_space_tag_t sc_fdemsiot;
|
||||
bus_space_handle_t sc_fdemsioh;
|
||||
#else
|
||||
bus_space_tag_t ctlt;
|
||||
bus_space_handle_t ctlh;
|
||||
#endif
|
||||
void *fdc_intr;
|
||||
struct device *fdc_dev;
|
||||
#ifndef PC98
|
||||
void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef int fdu_t;
|
||||
typedef int fdcu_t;
|
||||
typedef int fdsu_t;
|
||||
typedef struct fd_data *fd_p;
|
||||
typedef struct fdc_data *fdc_p;
|
||||
typedef enum fdc_type fdc_t;
|
||||
|
||||
/* error returns for fd_cmd() */
|
||||
#define FD_FAILED -1
|
||||
#define FD_NOT_VALID -2
|
||||
#define FDC_ERRMAX 100 /* do not log more */
|
||||
|
||||
extern devclass_t fdc_devclass;
|
||||
|
||||
enum fdc_device_ivars {
|
||||
FDC_IVAR_FDUNIT,
|
||||
FDC_IVAR_FDTYPE,
|
||||
};
|
||||
|
||||
__BUS_ACCESSOR(fdc, fdunit, FDC, FDUNIT, int);
|
||||
__BUS_ACCESSOR(fdc, fdtype, FDC, FDTYPE, int);
|
||||
|
||||
int fdc_alloc_resources(struct fdc_data *);
|
||||
#ifndef PC98
|
||||
void fdout_wr(fdc_p, u_int8_t);
|
||||
#endif
|
||||
int fd_cmd(struct fdc_data *, int, ...);
|
||||
void fdc_release_resources(struct fdc_data *);
|
||||
int fdc_attach(device_t);
|
||||
int fdc_hints_probe(device_t);
|
||||
int fdc_detach(device_t dev);
|
||||
device_t fdc_add_child(device_t, const char *, int);
|
||||
int fdc_initial_reset(struct fdc_data *);
|
||||
int fdc_print_child(device_t, device_t);
|
||||
int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
|
||||
int fdc_write_ivar(device_t, device_t, int, uintptr_t);
|
||||
#ifndef PC98
|
||||
int fdc_isa_alloc_resources(device_t, struct fdc_data *);
|
||||
#endif
|
@ -1,88 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 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.
|
||||
* 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.
|
||||
*
|
||||
* from: @(#)fdreg.h 7.1 (Berkeley) 5/9/91
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* AT floppy controller registers and bitfields
|
||||
*/
|
||||
|
||||
/* uses NEC765 controller */
|
||||
#include <dev/ic/nec765.h>
|
||||
|
||||
#ifdef PC98
|
||||
/* registers */
|
||||
#define FDSTS 0 /* NEC 765 Main Status Register (R) */
|
||||
#define FDDATA 1 /* NEC 765 Data Register (R/W) */
|
||||
#define FDCTL 2 /* FD Control Register */
|
||||
#define FDC_RST 0x80 /* FDC RESET */
|
||||
#define FDC_RDY 0x40 /* force READY */
|
||||
#define FDC_DD 0x20 /* FDD Mode Exchange 0:1M 1:640K */
|
||||
#define FDC_DMAE 0x10 /* enable floppy DMA */
|
||||
#define FDC_MTON 0x08 /* MOTOR ON (when EMTON=1)*/
|
||||
#define FDC_TMSK 0x04 /* TIMER MASK */
|
||||
#define FDC_TTRG 0x01 /* TIMER TRIGER */
|
||||
|
||||
#define FDP_EMTON 0x04 /* enable MTON */
|
||||
#define FDP_FDDEXC 0x02 /* FDD Mode Exchange 1:1M 0:640K */
|
||||
#define FDP_PORTEXC 0x01 /* PORT Exchane 1:1M 0:640K */
|
||||
|
||||
#else
|
||||
/* registers */
|
||||
#define FDOUT 2 /* Digital Output Register (W) */
|
||||
#define FDO_FDSEL 0x03 /* floppy device select */
|
||||
#define FDO_FRST 0x04 /* floppy controller reset */
|
||||
#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */
|
||||
#define FDO_MOEN0 0x10 /* motor enable drive 0 */
|
||||
#define FDO_MOEN1 0x20 /* motor enable drive 1 */
|
||||
#define FDO_MOEN2 0x40 /* motor enable drive 2 */
|
||||
#define FDO_MOEN3 0x80 /* motor enable drive 3 */
|
||||
|
||||
#define FDSTS 4 /* NEC 765 Main Status Register (R) */
|
||||
#define FDDATA 5 /* NEC 765 Data Register (R/W) */
|
||||
#define FDCTL 7 /* Control Register (W) */
|
||||
#endif /* PC98 */
|
||||
|
||||
/*
|
||||
* The definitions for FDC_500KBPS etc. have been moved out to <sys/fdcio.h>
|
||||
* since they need to be visible in userland. They cover the lower two bits
|
||||
* of FDCTL when used for output.
|
||||
*/
|
||||
/*
|
||||
* this is the secret PIO data port (offset from base)
|
||||
*/
|
||||
#define FDC_YE_DATAPORT 6
|
||||
|
||||
#ifndef PC98
|
||||
#define FDIN 7 /* Digital Input Register (R) */
|
||||
#define FDI_DCHG 0x80 /* diskette has been changed */
|
||||
/* requires drive and motor being selected */
|
||||
/* is cleared by any step pulse to drive */
|
||||
#endif
|
@ -1,497 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 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.
|
||||
* 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.
|
||||
*
|
||||
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* code to manage AT bus
|
||||
*
|
||||
* 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com):
|
||||
* Fixed uninitialized variable problem and added code to deal
|
||||
* with DMA page boundaries in isa_dmarangecheck(). Fixed word
|
||||
* mode DMA count compution and reorganized DMA setup code in
|
||||
* isa_dmastart()
|
||||
*/
|
||||
|
||||
#include "opt_pc98.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/module.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <dev/ic/i8237.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
/*
|
||||
** Register definitions for DMA controller 1 (channels 0..3):
|
||||
*/
|
||||
#define DMA1_CHN(c) (IO_DMA + (4*(c))) /* addr reg for channel c */
|
||||
#define DMA1_STATUS (IO_DMA + 0x10) /* status register */
|
||||
#define DMA1_SMSK (IO_DMA + 0x14) /* single mask register */
|
||||
#define DMA1_MODE (IO_DMA + 0x16) /* mode register */
|
||||
#define DMA1_FFC (IO_DMA + 0x18) /* clear first/last FF */
|
||||
|
||||
static int isa_dmarangecheck(caddr_t va, u_int length, int chan);
|
||||
|
||||
static caddr_t dma_bouncebuf[4];
|
||||
static u_int dma_bouncebufsize[4];
|
||||
static u_int8_t dma_bounced = 0;
|
||||
static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */
|
||||
static u_int8_t dma_inuse = 0; /* User for acquire/release */
|
||||
static u_int8_t dma_auto_mode = 0;
|
||||
|
||||
#define VALID_DMA_MASK (3)
|
||||
|
||||
/* high byte of address is stored in this port for i-th dma channel */
|
||||
static int dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
|
||||
|
||||
/*
|
||||
* Setup a DMA channel's bounce buffer.
|
||||
*/
|
||||
int
|
||||
isa_dma_init(int chan, u_int bouncebufsize, int flag)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (chan & ~VALID_DMA_MASK)
|
||||
panic("isa_dma_init: channel out of range");
|
||||
if (dma_bouncebuf[chan] != NULL)
|
||||
panic("isa_dma_init: impossible request");
|
||||
#endif
|
||||
|
||||
dma_bouncebufsize[chan] = bouncebufsize;
|
||||
|
||||
/* Try malloc() first. It works better if it works. */
|
||||
buf = malloc(bouncebufsize, M_DEVBUF, flag);
|
||||
if (buf != NULL) {
|
||||
if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) {
|
||||
dma_bouncebuf[chan] = buf;
|
||||
return (0);
|
||||
}
|
||||
free(buf, M_DEVBUF);
|
||||
}
|
||||
buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful,
|
||||
1ul, chan & 4 ? 0x20000ul : 0x10000ul);
|
||||
if (buf == NULL)
|
||||
return (ENOMEM);
|
||||
dma_bouncebuf[chan] = buf;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a DMA channel's usage. Usually called from a device driver
|
||||
* in open() or during its initialization.
|
||||
*/
|
||||
int
|
||||
isa_dma_acquire(chan)
|
||||
int chan;
|
||||
{
|
||||
#ifdef DIAGNOSTIC
|
||||
if (chan & ~VALID_DMA_MASK)
|
||||
panic("isa_dma_acquire: channel out of range");
|
||||
#endif
|
||||
|
||||
if (dma_inuse & (1 << chan)) {
|
||||
printf("isa_dma_acquire: channel %d already in use\n", chan);
|
||||
return (EBUSY);
|
||||
}
|
||||
dma_inuse |= (1 << chan);
|
||||
dma_auto_mode &= ~(1 << chan);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unregister a DMA channel's usage. Usually called from a device driver
|
||||
* during close() or during its shutdown.
|
||||
*/
|
||||
void
|
||||
isa_dma_release(chan)
|
||||
int chan;
|
||||
{
|
||||
#ifdef DIAGNOSTIC
|
||||
if (chan & ~VALID_DMA_MASK)
|
||||
panic("isa_dma_release: channel out of range");
|
||||
|
||||
if ((dma_inuse & (1 << chan)) == 0)
|
||||
printf("isa_dma_release: channel %d not in use\n", chan);
|
||||
#endif
|
||||
|
||||
if (dma_busy & (1 << chan)) {
|
||||
dma_busy &= ~(1 << chan);
|
||||
/*
|
||||
* XXX We should also do "dma_bounced &= (1 << chan);"
|
||||
* because we are acting on behalf of isa_dmadone() which
|
||||
* was not called to end the last DMA operation. This does
|
||||
* not matter now, but it may in the future.
|
||||
*/
|
||||
}
|
||||
|
||||
dma_inuse &= ~(1 << chan);
|
||||
dma_auto_mode &= ~(1 << chan);
|
||||
}
|
||||
|
||||
/*
|
||||
* isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
|
||||
* problems by using a bounce buffer.
|
||||
*/
|
||||
void
|
||||
isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)
|
||||
{
|
||||
vm_paddr_t phys;
|
||||
int waport;
|
||||
caddr_t newaddr;
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (chan & ~VALID_DMA_MASK)
|
||||
panic("isa_dmastart: channel out of range");
|
||||
|
||||
if ((chan < 4 && nbytes > (1<<16))
|
||||
|| (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1)))
|
||||
panic("isa_dmastart: impossible request");
|
||||
|
||||
if ((dma_inuse & (1 << chan)) == 0)
|
||||
printf("isa_dmastart: channel %d not acquired\n", chan);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* XXX This should be checked, but drivers like ad1848 only call
|
||||
* isa_dmastart() once because they use Auto DMA mode. If we
|
||||
* leave this in, drivers that do this will print this continuously.
|
||||
*/
|
||||
if (dma_busy & (1 << chan))
|
||||
printf("isa_dmastart: channel %d busy\n", chan);
|
||||
#endif
|
||||
|
||||
dma_busy |= (1 << chan);
|
||||
|
||||
if (isa_dmarangecheck(addr, nbytes, chan)) {
|
||||
if (dma_bouncebuf[chan] == NULL
|
||||
|| dma_bouncebufsize[chan] < nbytes)
|
||||
panic("isa_dmastart: bad bounce buffer");
|
||||
dma_bounced |= (1 << chan);
|
||||
newaddr = dma_bouncebuf[chan];
|
||||
|
||||
/* copy bounce buffer on write */
|
||||
if (!(flags & ISADMA_READ))
|
||||
bcopy(addr, newaddr, nbytes);
|
||||
addr = newaddr;
|
||||
}
|
||||
|
||||
/* translate to physical */
|
||||
phys = pmap_extract(kernel_pmap, (vm_offset_t)addr);
|
||||
|
||||
if (flags & ISADMA_RAW) {
|
||||
dma_auto_mode |= (1 << chan);
|
||||
} else {
|
||||
dma_auto_mode &= ~(1 << chan);
|
||||
}
|
||||
|
||||
if (need_pre_dma_flush)
|
||||
wbinvd(); /* wbinvd (WB cache flush) */
|
||||
|
||||
/* set dma channel mode, and reset address ff */
|
||||
|
||||
/* If ISADMA_RAW flag is set, then use autoinitialise mode */
|
||||
if (flags & ISADMA_RAW) {
|
||||
if (flags & ISADMA_READ)
|
||||
outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan);
|
||||
else
|
||||
outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan);
|
||||
} else {
|
||||
if (flags & ISADMA_READ)
|
||||
outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan);
|
||||
else
|
||||
outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan);
|
||||
}
|
||||
outb(DMA1_FFC, 0);
|
||||
|
||||
/* send start address */
|
||||
waport = DMA1_CHN(chan);
|
||||
outb(waport, phys);
|
||||
outb(waport, phys>>8);
|
||||
outb(dmapageport[chan], phys>>16);
|
||||
|
||||
/* send count */
|
||||
outb(waport + 2, --nbytes);
|
||||
outb(waport + 2, nbytes>>8);
|
||||
|
||||
/* unmask channel */
|
||||
outb(DMA1_SMSK, chan);
|
||||
}
|
||||
|
||||
void
|
||||
isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)
|
||||
{
|
||||
|
||||
if (flags & ISADMA_READ) {
|
||||
/* cache flush only after reading 92/12/9 by A.Kojima */
|
||||
if (need_post_dma_flush)
|
||||
invd();
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (chan & ~VALID_DMA_MASK)
|
||||
panic("isa_dmadone: channel out of range");
|
||||
|
||||
if ((dma_inuse & (1 << chan)) == 0)
|
||||
printf("isa_dmadone: channel %d not acquired\n", chan);
|
||||
#endif
|
||||
|
||||
if (((dma_busy & (1 << chan)) == 0) &&
|
||||
(dma_auto_mode & (1 << chan)) == 0 )
|
||||
printf("isa_dmadone: channel %d not busy\n", chan);
|
||||
|
||||
if ((dma_auto_mode & (1 << chan)) == 0)
|
||||
outb(DMA1_SMSK, (chan & 3) | 4);
|
||||
|
||||
if (dma_bounced & (1 << chan)) {
|
||||
/* copy bounce buffer on read */
|
||||
if (flags & ISADMA_READ)
|
||||
bcopy(dma_bouncebuf[chan], addr, nbytes);
|
||||
|
||||
dma_bounced &= ~(1 << chan);
|
||||
}
|
||||
dma_busy &= ~(1 << chan);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
static int
|
||||
isa_dmarangecheck(caddr_t va, u_int length, int chan)
|
||||
{
|
||||
vm_paddr_t phys, priorpage = 0;
|
||||
vm_offset_t endva;
|
||||
u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1);
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
endva = (vm_offset_t)round_page((vm_offset_t)va + length);
|
||||
for (; va < (caddr_t) endva ; va += PAGE_SIZE) {
|
||||
phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va));
|
||||
#ifdef EPSON_BOUNCEDMA
|
||||
#define ISARAM_END 0xf00000
|
||||
#else
|
||||
#define ISARAM_END RAM_END
|
||||
#endif
|
||||
if (phys == 0)
|
||||
panic("isa_dmacheck: no physical page present");
|
||||
if (phys >= ISARAM_END)
|
||||
return (1);
|
||||
if (priorpage) {
|
||||
if (priorpage + PAGE_SIZE != phys)
|
||||
return (1);
|
||||
/* check if crossing a DMA page boundary */
|
||||
if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk)
|
||||
return (1);
|
||||
}
|
||||
priorpage = phys;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Query the progress of a transfer on a DMA channel.
|
||||
*
|
||||
* To avoid having to interrupt a transfer in progress, we sample
|
||||
* each of the high and low databytes twice, and apply the following
|
||||
* logic to determine the correct count.
|
||||
*
|
||||
* Reads are performed with interrupts disabled, thus it is to be
|
||||
* expected that the time between reads is very small. At most
|
||||
* one rollover in the low count byte can be expected within the
|
||||
* four reads that are performed.
|
||||
*
|
||||
* There are three gaps in which a rollover can occur :
|
||||
*
|
||||
* - read low1
|
||||
* gap1
|
||||
* - read high1
|
||||
* gap2
|
||||
* - read low2
|
||||
* gap3
|
||||
* - read high2
|
||||
*
|
||||
* If a rollover occurs in gap1 or gap2, the low2 value will be
|
||||
* greater than the low1 value. In this case, low2 and high2 are a
|
||||
* corresponding pair.
|
||||
*
|
||||
* In any other case, low1 and high1 can be considered to be correct.
|
||||
*
|
||||
* The function returns the number of bytes remaining in the transfer,
|
||||
* or -1 if the channel requested is not active.
|
||||
*
|
||||
*/
|
||||
int
|
||||
isa_dmastatus(int chan)
|
||||
{
|
||||
u_long cnt = 0;
|
||||
int ffport, waport;
|
||||
u_long low1, high1, low2, high2;
|
||||
|
||||
/* channel active? */
|
||||
if ((dma_inuse & (1 << chan)) == 0) {
|
||||
printf("isa_dmastatus: channel %d not active\n", chan);
|
||||
return(-1);
|
||||
}
|
||||
/* channel busy? */
|
||||
|
||||
if (((dma_busy & (1 << chan)) == 0) &&
|
||||
(dma_auto_mode & (1 << chan)) == 0 ) {
|
||||
printf("chan %d not busy\n", chan);
|
||||
return -2 ;
|
||||
}
|
||||
ffport = DMA1_FFC;
|
||||
waport = DMA1_CHN(chan) + 2;
|
||||
|
||||
disable_intr(); /* no interrupts Mr Jones! */
|
||||
outb(ffport, 0); /* clear register LSB flipflop */
|
||||
low1 = inb(waport);
|
||||
high1 = inb(waport);
|
||||
outb(ffport, 0); /* clear again */
|
||||
low2 = inb(waport);
|
||||
high2 = inb(waport);
|
||||
enable_intr(); /* enable interrupts again */
|
||||
|
||||
/*
|
||||
* Now decide if a wrap has tried to skew our results.
|
||||
* Note that after TC, the count will read 0xffff, while we want
|
||||
* to return zero, so we add and then mask to compensate.
|
||||
*/
|
||||
if (low1 >= low2) {
|
||||
cnt = (low1 + (high1 << 8) + 1) & 0xffff;
|
||||
} else {
|
||||
cnt = (low2 + (high2 << 8) + 1) & 0xffff;
|
||||
}
|
||||
|
||||
if (chan >= 4) /* high channels move words */
|
||||
cnt *= 2;
|
||||
return(cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reached terminal count yet ?
|
||||
*/
|
||||
int
|
||||
isa_dmatc(int chan)
|
||||
{
|
||||
|
||||
return(inb(DMA1_STATUS) & (1 << chan));
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop a DMA transfer currently in progress.
|
||||
*/
|
||||
int
|
||||
isa_dmastop(int chan)
|
||||
{
|
||||
if ((dma_inuse & (1 << chan)) == 0)
|
||||
printf("isa_dmastop: channel %d not acquired\n", chan);
|
||||
|
||||
if (((dma_busy & (1 << chan)) == 0) &&
|
||||
((dma_auto_mode & (1 << chan)) == 0)) {
|
||||
printf("chan %d not busy\n", chan);
|
||||
return -2 ;
|
||||
}
|
||||
|
||||
if ((chan & 4) == 0)
|
||||
outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */);
|
||||
|
||||
return(isa_dmastatus(chan));
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach to the ISA PnP descriptor for the AT DMA controller
|
||||
*/
|
||||
static struct isa_pnp_id atdma_ids[] = {
|
||||
{ 0x0002d041 /* PNP0200 */, "AT DMA controller" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
atdma_probe(device_t dev)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, atdma_ids)) <= 0)
|
||||
device_quiet(dev);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int
|
||||
atdma_attach(device_t dev)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
static device_method_t atdma_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, atdma_probe),
|
||||
DEVMETHOD(device_attach, atdma_attach),
|
||||
DEVMETHOD(device_detach, bus_generic_detach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t atdma_driver = {
|
||||
"atdma",
|
||||
atdma_methods,
|
||||
1, /* no softc */
|
||||
};
|
||||
|
||||
static devclass_t atdma_devclass;
|
||||
|
||||
DRIVER_MODULE(atdma, isa, atdma_driver, atdma_devclass, 0, 0);
|
@ -103,7 +103,7 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
|
||||
#include <net/netisr.h>
|
||||
|
||||
|
@ -1,74 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1991 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.
|
||||
* 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.
|
||||
*
|
||||
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <pc98/pc98/epsonio.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
|
||||
#define NMI_PARITY 0x04
|
||||
#define NMI_EPARITY 0x02
|
||||
|
||||
/*
|
||||
* Handle a NMI, possibly a machine check.
|
||||
* return true to panic system, false to ignore.
|
||||
*/
|
||||
int
|
||||
isa_nmi(int cd)
|
||||
{
|
||||
int retval = 0;
|
||||
int port = inb(0x33);
|
||||
|
||||
log(LOG_CRIT, "NMI PC98 port = %x\n", port);
|
||||
if (epson_machine_id == 0x20)
|
||||
epson_outb(0xc16, epson_inb(0xc16) | 0x1);
|
||||
if (port & NMI_PARITY) {
|
||||
log(LOG_CRIT, "BASE RAM parity error, likely hardware failure.");
|
||||
retval = 1;
|
||||
} else if (port & NMI_EPARITY) {
|
||||
log(LOG_CRIT, "EXTENDED RAM parity error, likely hardware failure.");
|
||||
retval = 1;
|
||||
} else {
|
||||
log(LOG_CRIT, "\nNMI Resume ??\n");
|
||||
}
|
||||
|
||||
return(retval);
|
||||
}
|
@ -1,653 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1990 William F. Jolitz, TeleMuse
|
||||
* 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 software is a component of "386BSD" developed by
|
||||
* William F. Jolitz, TeleMuse.
|
||||
* 4. Neither the name of the developer nor the name "386BSD"
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
|
||||
* AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
|
||||
* SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
|
||||
* THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
|
||||
* NOT MAKE USE OF THIS WORK.
|
||||
*
|
||||
* FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
|
||||
* BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
|
||||
* REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
|
||||
* (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
|
||||
* JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
|
||||
* LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
|
||||
* ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
|
||||
* OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``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 DEVELOPER 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.
|
||||
*
|
||||
* from: unknown origin, 386BSD 0.1
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Device Driver for AT parallel printer port
|
||||
* Written by William Jolitz 12/18/90
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parallel port TCP/IP interfaces added. I looked at the driver from
|
||||
* MACH but this is a complete rewrite, and btw. incompatible, and it
|
||||
* should perform better too. I have never run the MACH driver though.
|
||||
*
|
||||
* This driver sends two bytes (0x08, 0x00) in front of each packet,
|
||||
* to allow us to distinguish another format later.
|
||||
*
|
||||
* Now added a Linux/Crynwr compatibility mode which is enabled using
|
||||
* IF_LINK0 - Tim Wilkinson.
|
||||
*
|
||||
* TODO:
|
||||
* Make HDLC/PPP mode, use IF_LLC1 to enable.
|
||||
*
|
||||
* Connect the two computers using a Laplink parallel cable to use this
|
||||
* feature:
|
||||
*
|
||||
* +----------------------------------------+
|
||||
* |A-name A-End B-End Descr. Port/Bit |
|
||||
* +----------------------------------------+
|
||||
* |DATA0 2 15 Data 0/0x01 |
|
||||
* |-ERROR 15 2 1/0x08 |
|
||||
* +----------------------------------------+
|
||||
* |DATA1 3 13 Data 0/0x02 |
|
||||
* |+SLCT 13 3 1/0x10 |
|
||||
* +----------------------------------------+
|
||||
* |DATA2 4 12 Data 0/0x04 |
|
||||
* |+PE 12 4 1/0x20 |
|
||||
* +----------------------------------------+
|
||||
* |DATA3 5 10 Strobe 0/0x08 |
|
||||
* |-ACK 10 5 1/0x40 |
|
||||
* +----------------------------------------+
|
||||
* |DATA4 6 11 Data 0/0x10 |
|
||||
* |BUSY 11 6 1/~0x80 |
|
||||
* +----------------------------------------+
|
||||
* |GND 18-25 18-25 GND - |
|
||||
* +----------------------------------------+
|
||||
*
|
||||
* Expect transfer-rates up to 75 kbyte/sec.
|
||||
*
|
||||
* If GCC could correctly grok
|
||||
* register int port asm("edx")
|
||||
* the code would be cleaner
|
||||
*
|
||||
* Poul-Henning Kamp <phk@freebsd.org>
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#include <i386/isa/lptreg.h>
|
||||
#include <dev/ppbus/lptio.h>
|
||||
|
||||
#define LPINITRDY 4 /* wait up to 4 seconds for a ready */
|
||||
#define LPTOUTINITIAL 10 /* initial timeout to wait for ready 1/10 s */
|
||||
#define LPTOUTMAX 1 /* maximal timeout 1 s */
|
||||
#define LPPRI (PZERO+8)
|
||||
#define BUFSIZE 1024
|
||||
|
||||
#ifndef DEBUG
|
||||
#define lprintf(args)
|
||||
#else
|
||||
#define lprintf(args) do { \
|
||||
if (lptflag) \
|
||||
printf args; \
|
||||
} while (0)
|
||||
static int volatile lptflag = 1;
|
||||
#endif
|
||||
|
||||
#define LPTUNIT(s) ((s)&0x03)
|
||||
#define LPTFLAGS(s) ((s)&0xfc)
|
||||
|
||||
struct lpt_softc {
|
||||
struct resource *res_port;
|
||||
struct resource *res_irq;
|
||||
void *sc_ih;
|
||||
|
||||
int sc_port;
|
||||
short sc_state;
|
||||
/* default case: negative prime, negative ack, handshake strobe,
|
||||
prime once */
|
||||
u_char sc_control;
|
||||
char sc_flags;
|
||||
#define LP_POS_INIT 0x04 /* if we are a postive init signal */
|
||||
#define LP_POS_ACK 0x08 /* if we are a positive going ack */
|
||||
#define LP_NO_PRIME 0x10 /* don't prime the printer at all */
|
||||
#define LP_PRIMEOPEN 0x20 /* prime on every open */
|
||||
#define LP_AUTOLF 0x40 /* tell printer to do an automatic lf */
|
||||
#define LP_BYPASS 0x80 /* bypass printer ready checks */
|
||||
void *sc_inbuf;
|
||||
short sc_xfercnt ;
|
||||
char sc_primed;
|
||||
char *sc_cp ;
|
||||
u_char sc_irq ; /* IRQ status of port */
|
||||
#define LP_HAS_IRQ 0x01 /* we have an irq available */
|
||||
#define LP_USE_IRQ 0x02 /* we are using our irq */
|
||||
#define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */
|
||||
u_char sc_backoff ; /* time to call lptout() again */
|
||||
};
|
||||
|
||||
/* bits for state */
|
||||
#define OPEN (1<<0) /* device is open */
|
||||
#define ASLP (1<<1) /* awaiting draining of printer */
|
||||
#define ERROR (1<<2) /* error was received from printer */
|
||||
#define OBUSY (1<<3) /* printer is busy doing output */
|
||||
#define LPTOUT (1<<4) /* timeout while not selected */
|
||||
#define TOUT (1<<5) /* timeout while not selected */
|
||||
#define INIT (1<<6) /* waiting to initialize for open */
|
||||
#define INTERRUPTED (1<<7) /* write call was interrupted */
|
||||
|
||||
|
||||
/* status masks to interrogate printer status */
|
||||
#define RDY_MASK (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR) /* ready ? */
|
||||
#define LP_READY (LPS_SEL|LPS_NBSY|LPS_NERR)
|
||||
|
||||
/* Printer Ready condition - from lpa.c */
|
||||
/* Only used in polling code */
|
||||
#define NOT_READY(x) ((inb(x) & LPS_NBSY) != LPS_NBSY)
|
||||
|
||||
#define MAX_SLEEP (hz*5) /* Timeout while waiting for device ready */
|
||||
#define MAX_SPIN 20 /* Max delay for device ready in usecs */
|
||||
|
||||
static timeout_t lptout;
|
||||
static int lpt_probe(device_t);
|
||||
static int lpt_attach(device_t);
|
||||
static void lpt_intr(void *);
|
||||
|
||||
static devclass_t olpt_devclass;
|
||||
|
||||
static device_method_t olpt_methods[] = {
|
||||
DEVMETHOD(device_probe, lpt_probe),
|
||||
DEVMETHOD(device_attach, lpt_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t olpt_driver = {
|
||||
"olpt",
|
||||
olpt_methods,
|
||||
sizeof (struct lpt_softc),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(olpt, isa, olpt_driver, olpt_devclass, 0, 0);
|
||||
|
||||
static d_open_t lptopen;
|
||||
static d_close_t lptclose;
|
||||
static d_write_t lptwrite;
|
||||
static d_ioctl_t lptioctl;
|
||||
|
||||
static struct cdevsw lpt_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_flags = D_NEEDGIANT,
|
||||
.d_open = lptopen,
|
||||
.d_close = lptclose,
|
||||
.d_write = lptwrite,
|
||||
.d_ioctl = lptioctl,
|
||||
.d_name = "lpt",
|
||||
};
|
||||
|
||||
static bus_addr_t lpt_iat[] = {0, 2, 4, 6};
|
||||
|
||||
/*
|
||||
* New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
|
||||
* Based partially on Rod Grimes' printer probe
|
||||
*
|
||||
* Logic:
|
||||
* 1) If no port address was given, use the bios detected ports
|
||||
* and autodetect what ports the printers are on.
|
||||
* 2) Otherwise, probe the data port at the address given,
|
||||
* using the method in Rod Grimes' port probe.
|
||||
* (Much code ripped off directly from Rod's probe.)
|
||||
*
|
||||
* Comments from Rod's probe:
|
||||
* Logic:
|
||||
* 1) You should be able to write to and read back the same value
|
||||
* to the data port. Do an alternating zeros, alternating ones,
|
||||
* walking zero, and walking one test to check for stuck bits.
|
||||
*
|
||||
* 2) You should be able to write to and read back the same value
|
||||
* to the control port lower 5 bits, the upper 3 bits are reserved
|
||||
* per the IBM PC technical reference manauls and different boards
|
||||
* do different things with them. Do an alternating zeros, alternating
|
||||
* ones, walking zero, and walking one test to check for stuck bits.
|
||||
*
|
||||
* Some printers drag the strobe line down when the are powered off
|
||||
* so this bit has been masked out of the control port test.
|
||||
*
|
||||
* XXX Some printers may not like a fast pulse on init or strobe, I
|
||||
* don't know at this point, if that becomes a problem these bits
|
||||
* should be turned off in the mask byte for the control port test.
|
||||
*
|
||||
* We are finally left with a mask of 0x14, due to some printers
|
||||
* being adamant about holding other bits high ........
|
||||
*
|
||||
* Before probing the control port, we write a 0 to the data port -
|
||||
* If not, some printers chuck out garbage when the strobe line
|
||||
* gets toggled.
|
||||
*
|
||||
* 3) Set the data and control ports to a value of 0
|
||||
*
|
||||
* This probe routine has been tested on Epson Lx-800, HP LJ3P,
|
||||
* Epson FX-1170 and C.Itoh 8510RM
|
||||
* printers.
|
||||
* Quick exit on fail added.
|
||||
*/
|
||||
|
||||
int
|
||||
lpt_probe(device_t dev)
|
||||
{
|
||||
#define PC98_OLD_LPT 0x40
|
||||
#define PC98_IEEE_1284_FUNCTION 0x149
|
||||
int rid;
|
||||
struct resource *res;
|
||||
|
||||
/* Check isapnp ids */
|
||||
if (isa_get_vendorid(dev))
|
||||
return ENXIO;
|
||||
|
||||
rid = 0;
|
||||
res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, lpt_iat, 4,
|
||||
RF_ACTIVE);
|
||||
if (res == NULL)
|
||||
return ENXIO;
|
||||
isa_load_resourcev(res, lpt_iat, 4);
|
||||
|
||||
if (isa_get_port(dev) == PC98_OLD_LPT) {
|
||||
unsigned int pc98_ieee_mode, tmp;
|
||||
|
||||
tmp = inb(PC98_IEEE_1284_FUNCTION);
|
||||
pc98_ieee_mode = tmp;
|
||||
if ((tmp & 0x10) == 0x10) {
|
||||
outb(PC98_IEEE_1284_FUNCTION, tmp & ~0x10);
|
||||
tmp = inb(PC98_IEEE_1284_FUNCTION);
|
||||
if ((tmp & 0x10) != 0x10) {
|
||||
outb(PC98_IEEE_1284_FUNCTION, pc98_ieee_mode);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, rid,
|
||||
res);
|
||||
return ENXIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX Todo - try and detect if interrupt is working */
|
||||
int
|
||||
lpt_attach(device_t dev)
|
||||
{
|
||||
int rid, unit;
|
||||
struct lpt_softc *sc;
|
||||
|
||||
unit = device_get_unit(dev);
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
rid = 0;
|
||||
sc->res_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
|
||||
lpt_iat, 4, RF_ACTIVE);
|
||||
if (sc->res_port == NULL)
|
||||
return ENXIO;
|
||||
isa_load_resourcev(sc->res_port, lpt_iat, 4);
|
||||
|
||||
sc->sc_port = rman_get_start(sc->res_port);
|
||||
sc->sc_primed = 0; /* not primed yet */
|
||||
|
||||
outb(sc->sc_port+lpt_pstb_ctrl, LPC_DIS_PSTB); /* PSTB disable */
|
||||
outb(sc->sc_port+lpt_control, LPC_MODE8255); /* 8255 mode set */
|
||||
outb(sc->sc_port+lpt_control, LPC_NIRQ8); /* IRQ8 inactive */
|
||||
outb(sc->sc_port+lpt_control, LPC_NPSTB); /* PSTB inactive */
|
||||
outb(sc->sc_port+lpt_pstb_ctrl, LPC_EN_PSTB); /* PSTB enable */
|
||||
|
||||
sc->sc_irq = 0;
|
||||
if (isa_get_irq(dev) != -1) {
|
||||
rid = 0;
|
||||
sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->res_irq == NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0,
|
||||
sc->res_port);
|
||||
return ENXIO;
|
||||
}
|
||||
if (bus_setup_intr(dev, sc->res_irq, INTR_TYPE_TTY, lpt_intr,
|
||||
sc, &sc->sc_ih)) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0,
|
||||
sc->res_port);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0,
|
||||
sc->res_irq);
|
||||
return ENXIO;
|
||||
}
|
||||
sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ;
|
||||
device_printf(dev, "Interrupt-driven port");
|
||||
}
|
||||
|
||||
/* XXX what to do about the flags in the minor number? */
|
||||
make_dev(&lpt_cdevsw, unit, UID_ROOT, GID_WHEEL, 0600, "lpt%d", unit);
|
||||
make_dev(&lpt_cdevsw, unit | LP_BYPASS,
|
||||
UID_ROOT, GID_WHEEL, 0600, "lpctl%d", unit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* lptopen -- reset the printer, then wait until it's selected and not busy.
|
||||
* If LP_BYPASS flag is selected, then we do not try to select the
|
||||
* printer -- this is just used for passing ioctls.
|
||||
*/
|
||||
|
||||
static int
|
||||
lptopen (struct cdev *dev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
struct lpt_softc *sc;
|
||||
int s;
|
||||
int port;
|
||||
|
||||
sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev)));
|
||||
if (sc->sc_port == 0)
|
||||
return (ENXIO);
|
||||
|
||||
if (sc->sc_state) {
|
||||
lprintf(("lp: still open %x\n", sc->sc_state));
|
||||
return(EBUSY);
|
||||
} else
|
||||
sc->sc_state |= INIT;
|
||||
|
||||
sc->sc_flags = LPTFLAGS(minor(dev));
|
||||
|
||||
/* Check for open with BYPASS flag set. */
|
||||
if (sc->sc_flags & LP_BYPASS) {
|
||||
sc->sc_state = OPEN;
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = spltty();
|
||||
lprintf(("lp flags 0x%x\n", sc->sc_flags));
|
||||
port = sc->sc_port;
|
||||
|
||||
/* set IRQ status according to ENABLE_IRQ flag */
|
||||
if (sc->sc_irq & LP_ENABLE_IRQ)
|
||||
sc->sc_irq |= LP_USE_IRQ;
|
||||
else
|
||||
sc->sc_irq &= ~LP_USE_IRQ;
|
||||
|
||||
/* init printer */
|
||||
sc->sc_state = OPEN;
|
||||
sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
|
||||
sc->sc_xfercnt = 0;
|
||||
splx(s);
|
||||
|
||||
/* only use timeout if using interrupt */
|
||||
lprintf(("irq %x\n", sc->sc_irq));
|
||||
if (sc->sc_irq & LP_USE_IRQ) {
|
||||
sc->sc_state |= TOUT;
|
||||
timeout (lptout, (caddr_t)sc,
|
||||
(sc->sc_backoff = hz/LPTOUTINITIAL));
|
||||
}
|
||||
|
||||
lprintf(("opened.\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
lptout (void *arg)
|
||||
{
|
||||
struct lpt_softc *sc = arg;
|
||||
int pl;
|
||||
|
||||
lprintf(("T %x ", inb(sc->sc_port+lpt_status)));
|
||||
if (sc->sc_state & OPEN) {
|
||||
sc->sc_backoff++;
|
||||
if (sc->sc_backoff > hz/LPTOUTMAX)
|
||||
sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX;
|
||||
timeout (lptout, (caddr_t)sc, sc->sc_backoff);
|
||||
} else
|
||||
sc->sc_state &= ~TOUT;
|
||||
|
||||
if (sc->sc_state & ERROR)
|
||||
sc->sc_state &= ~ERROR;
|
||||
|
||||
/*
|
||||
* Avoid possible hangs do to missed interrupts
|
||||
*/
|
||||
if (sc->sc_xfercnt) {
|
||||
pl = spltty();
|
||||
lpt_intr(sc);
|
||||
splx(pl);
|
||||
} else {
|
||||
sc->sc_state &= ~OBUSY;
|
||||
wakeup(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* lptclose -- close the device, free the local line buffer.
|
||||
*
|
||||
* Check for interrupted write call added.
|
||||
*/
|
||||
|
||||
static int
|
||||
lptclose(struct cdev *dev, int flags, int fmt, struct thread *td)
|
||||
{
|
||||
struct lpt_softc *sc;
|
||||
|
||||
sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev)));
|
||||
if(sc->sc_flags & LP_BYPASS)
|
||||
goto end_close;
|
||||
|
||||
sc->sc_state &= ~OPEN;
|
||||
free(sc->sc_inbuf, M_DEVBUF);
|
||||
|
||||
end_close:
|
||||
sc->sc_state = 0;
|
||||
sc->sc_xfercnt = 0;
|
||||
lprintf(("closed.\n"));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* pushbytes()
|
||||
* Workhorse for actually spinning and writing bytes to printer
|
||||
* Derived from lpa.c
|
||||
* Originally by ?
|
||||
*
|
||||
* This code is only used when we are polling the port
|
||||
*/
|
||||
static int
|
||||
pushbytes(struct lpt_softc * sc)
|
||||
{
|
||||
int spin, err, tic;
|
||||
char ch;
|
||||
int port = sc->sc_port;
|
||||
|
||||
lprintf(("p"));
|
||||
/* loop for every character .. */
|
||||
while (sc->sc_xfercnt > 0) {
|
||||
/* printer data */
|
||||
ch = *(sc->sc_cp);
|
||||
sc->sc_cp++;
|
||||
sc->sc_xfercnt--;
|
||||
|
||||
/*
|
||||
* Wait for printer ready.
|
||||
* Loop 20 usecs testing BUSY bit, then sleep
|
||||
* for exponentially increasing timeout. (vak)
|
||||
*/
|
||||
for (spin=0; NOT_READY(port+lpt_status) && spin<MAX_SPIN; ++spin)
|
||||
DELAY(1); /* XXX delay is NOT this accurate! */
|
||||
if (spin >= MAX_SPIN) {
|
||||
tic = 0;
|
||||
while (NOT_READY(port+lpt_status)) {
|
||||
/*
|
||||
* Now sleep, every cycle a
|
||||
* little longer ..
|
||||
*/
|
||||
tic = tic + tic + 1;
|
||||
/*
|
||||
* But no more than 10 seconds. (vak)
|
||||
*/
|
||||
if (tic > MAX_SLEEP)
|
||||
tic = MAX_SLEEP;
|
||||
err = tsleep(sc, LPPRI,
|
||||
"lptpoll", tic);
|
||||
if (err != EWOULDBLOCK) {
|
||||
return (err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* output data */
|
||||
outb(port+lpt_data, ch);
|
||||
DELAY(1);
|
||||
outb(port+lpt_control, LPC_PSTB);
|
||||
DELAY(1);
|
||||
outb(port+lpt_control, LPC_NPSTB);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* lptwrite --copy a line from user space to a local buffer, then call
|
||||
* putc to get the chars moved to the output queue.
|
||||
*
|
||||
* Flagging of interrupted write added.
|
||||
*/
|
||||
|
||||
static int
|
||||
lptwrite(struct cdev *dev, struct uio * uio, int ioflag)
|
||||
{
|
||||
register unsigned n;
|
||||
int pl, err;
|
||||
struct lpt_softc *sc;
|
||||
|
||||
sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev)));
|
||||
if(sc->sc_flags & LP_BYPASS) {
|
||||
/* we can't do writes in bypass mode */
|
||||
return(EPERM);
|
||||
}
|
||||
|
||||
sc->sc_state &= ~INTERRUPTED;
|
||||
while ((n = min(BUFSIZE, uio->uio_resid)) != 0) {
|
||||
sc->sc_cp = sc->sc_inbuf;
|
||||
uiomove(sc->sc_cp, n, uio);
|
||||
sc->sc_xfercnt = n ;
|
||||
while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) {
|
||||
lprintf(("i"));
|
||||
/* if the printer is ready for a char, */
|
||||
/* give it one */
|
||||
if ((sc->sc_state & OBUSY) == 0){
|
||||
lprintf(("\nC %d. ", sc->sc_xfercnt));
|
||||
pl = spltty();
|
||||
lpt_intr(sc);
|
||||
(void) splx(pl);
|
||||
}
|
||||
lprintf(("W "));
|
||||
if (sc->sc_state & OBUSY)
|
||||
if ((err = tsleep (sc,
|
||||
LPPRI|PCATCH, "lpwrite", 0))) {
|
||||
sc->sc_state |= INTERRUPTED;
|
||||
return(err);
|
||||
}
|
||||
}
|
||||
/* check to see if we must do a polled write */
|
||||
if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) {
|
||||
lprintf(("p"));
|
||||
if((err = pushbytes(sc)))
|
||||
return(err);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* lptintr -- handle printer interrupts which occur when the printer is
|
||||
* ready to accept another char.
|
||||
*
|
||||
* do checking for interrupted write call.
|
||||
*/
|
||||
|
||||
static void
|
||||
lpt_intr(void *arg)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
lptioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td)
|
||||
{
|
||||
int error = 0;
|
||||
struct lpt_softc *sc;
|
||||
u_int unit = LPTUNIT(minor(dev));
|
||||
u_char old_sc_irq; /* old printer IRQ status */
|
||||
|
||||
sc = devclass_get_softc(olpt_devclass, unit);
|
||||
|
||||
switch (cmd) {
|
||||
case LPT_IRQ :
|
||||
if(sc->sc_irq & LP_HAS_IRQ) {
|
||||
/*
|
||||
* NOTE:
|
||||
* If the IRQ status is changed,
|
||||
* this will only be visible on the
|
||||
* next open.
|
||||
*
|
||||
* If interrupt status changes,
|
||||
* this gets syslog'd.
|
||||
*/
|
||||
old_sc_irq = sc->sc_irq;
|
||||
if(*(int*)data == 0)
|
||||
sc->sc_irq &= (~LP_ENABLE_IRQ);
|
||||
else
|
||||
sc->sc_irq |= LP_ENABLE_IRQ;
|
||||
if (old_sc_irq != sc->sc_irq )
|
||||
log(LOG_NOTICE, "lpt%c switched to %s mode\n",
|
||||
(char)unit+'0',
|
||||
(sc->sc_irq & LP_ENABLE_IRQ)?
|
||||
"interrupt-driven":"polled");
|
||||
} else /* polled port */
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
default:
|
||||
error = ENODEV;
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* from: @(#)isa.h 5.7 (Berkeley) 5/9/91
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _PC98_PC98_PC98_H_
|
||||
#define _PC98_PC98_PC98_H_
|
||||
|
||||
/* BEWARE: Included in both assembler and C code */
|
||||
|
||||
/*
|
||||
* PC98 Bus conventions
|
||||
* modified for PC9801 by A.Kojima F.Ukai M.Ishii
|
||||
* Kyoto University Microcomputer Club (KMC)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Input / Output Port Assignments
|
||||
*/
|
||||
#ifndef IO_ISABEGIN
|
||||
#define IO_ISABEGIN 0x000 /* 0x000 - Beginning of I/O Registers */
|
||||
|
||||
/* PC98 IO address ... very dirty (^_^; */
|
||||
|
||||
#define IO_ICU1 0x000 /* 8259A Interrupt Controller #1 */
|
||||
#define IO_DMA 0x001 /* 8237A DMA Controller */
|
||||
#define IO_ICU2 0x008 /* 8259A Interrupt Controller #2 */
|
||||
#define IO_RTC 0x020 /* 4990A RTC */
|
||||
#define IO_SYSPORT 0x031 /* 8255A System Port */
|
||||
#define IO_PPI 0x035 /* Programmable Peripheral Interface */
|
||||
#define IO_KBD 0x041 /* 8251A Keyboard */
|
||||
#define IO_TIMER1 0x071 /* 8253C Timer */
|
||||
#define IO_COM2 0x0B1 /* 8251A RS232C serial I/O (ext) */
|
||||
#define IO_COM3 0x0B9 /* 8251A RS232C serial I/O (ext) */
|
||||
#define IO_FDPORT 0x0BE /* FD I/F port (1M<->640K,EMTON) */
|
||||
#define IO_NPX 0x0F8 /* Numeric Coprocessor */
|
||||
#define IO_WD1_EPSON 0x80 /* 386note Hard disk controller */
|
||||
#define IO_ISAEND 0xFFFF /* - 0x3FF End of I/O Registers */
|
||||
#endif /* !IO_ISABEGIN */
|
||||
|
||||
/*
|
||||
* Input / Output Port Sizes - these are from several sources, and tend
|
||||
* to be the larger of what was found, ie COM ports can be 4, but some
|
||||
* boards do not fully decode the address, thus 8 ports are used.
|
||||
*/
|
||||
#ifndef IO_ISASIZES
|
||||
#define IO_ISASIZES
|
||||
|
||||
#define IO_KBDSIZE 16 /* 8042 Keyboard controllers */
|
||||
#define IO_LPTSIZE 8 /* LPT controllers, some use only 4 */
|
||||
#define IO_LPTSIZE_EXTENDED 8 /* "Extended" LPT controllers */
|
||||
#define IO_LPTSIZE_NORMAL 4 /* "Normal" LPT controllers */
|
||||
#define IO_NPXSIZE 8 /* 80387/80487 NPX registers */
|
||||
|
||||
#endif /* !IO_ISASIZES */
|
||||
|
||||
/*
|
||||
* Input / Output Memory Physical Addresses
|
||||
*/
|
||||
#ifndef IOM_BEGIN
|
||||
#define IOM_BEGIN 0x0A0000 /* Start of I/O Memory "hole" */
|
||||
#define IOM_END 0x100000 /* End of I/O Memory "hole" */
|
||||
#define IOM_SIZE (IOM_END - IOM_BEGIN)
|
||||
#endif /* !IOM_BEGIN */
|
||||
|
||||
/*
|
||||
* RAM Physical Address Space (ignoring the above mentioned "hole")
|
||||
*/
|
||||
#ifndef RAM_BEGIN
|
||||
#define RAM_BEGIN 0x0000000 /* Start of RAM Memory */
|
||||
#ifdef EPSON_BOUNCEDMA
|
||||
#define RAM_END 0x0f00000 /* End of EPSON GR?? RAM Memory */
|
||||
#else
|
||||
#define RAM_END 0x1000000 /* End of RAM Memory */
|
||||
#endif
|
||||
#define RAM_SIZE (RAM_END - RAM_BEGIN)
|
||||
#endif /* !RAM_BEGIN */
|
||||
|
||||
/*
|
||||
* IRQs
|
||||
*/
|
||||
#define IRQ_NPX 8
|
||||
|
||||
/*
|
||||
* Npx MD defines
|
||||
*/
|
||||
/* full reset of npx: not needed on pc98 */
|
||||
#define npx_full_reset()
|
||||
|
||||
#define M_NEC_PC98 0x0001
|
||||
#define M_EPSON_PC98 0x0002
|
||||
#define M_NOT_H98 0x0010
|
||||
#define M_H98 0x0020
|
||||
#define M_NOTE 0x0040
|
||||
#define M_NORMAL 0x1000
|
||||
#define M_8M 0x8000
|
||||
|
||||
#endif /* !_PC98_PC98_PC98_H_ */
|
@ -39,7 +39,7 @@
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#ifdef EPSON_MEMWIN
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#endif
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,964 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 FreeBSD(98) port team.
|
||||
* 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_kbd.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/kbio.h>
|
||||
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#define DRIVER_NAME "pckbd"
|
||||
|
||||
/* device configuration flags */
|
||||
#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */
|
||||
|
||||
static devclass_t pckbd_devclass;
|
||||
|
||||
static int pckbdprobe(device_t dev);
|
||||
static int pckbdattach(device_t dev);
|
||||
static int pckbdresume(device_t dev);
|
||||
static void pckbd_isa_intr(void *arg);
|
||||
|
||||
static device_method_t pckbd_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, pckbdprobe),
|
||||
DEVMETHOD(device_attach, pckbdattach),
|
||||
DEVMETHOD(device_resume, pckbdresume),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t pckbd_driver = {
|
||||
DRIVER_NAME,
|
||||
pckbd_methods,
|
||||
1,
|
||||
};
|
||||
|
||||
DRIVER_MODULE(pckbd, isa, pckbd_driver, pckbd_devclass, 0, 0);
|
||||
|
||||
static bus_addr_t pckbd_iat[] = {0, 2};
|
||||
|
||||
static int pckbd_probe_unit(int unit, int port, int irq,
|
||||
int flags);
|
||||
static int pckbd_attach_unit(int unit, keyboard_t **kbd,
|
||||
int port, int irq, int flags);
|
||||
static timeout_t pckbd_timeout;
|
||||
|
||||
|
||||
static int
|
||||
pckbdprobe(device_t dev)
|
||||
{
|
||||
struct resource *res;
|
||||
int error, rid;
|
||||
|
||||
/* Check isapnp ids */
|
||||
if (isa_get_vendorid(dev))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "PC-98 Keyboard");
|
||||
|
||||
rid = 0;
|
||||
res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2,
|
||||
RF_ACTIVE);
|
||||
if (res == NULL)
|
||||
return ENXIO;
|
||||
isa_load_resourcev(res, pckbd_iat, 2);
|
||||
|
||||
error = pckbd_probe_unit(device_get_unit(dev),
|
||||
isa_get_port(dev),
|
||||
(1 << isa_get_irq(dev)),
|
||||
device_get_flags(dev));
|
||||
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
pckbdattach(device_t dev)
|
||||
{
|
||||
keyboard_t *kbd;
|
||||
void *ih;
|
||||
struct resource *res;
|
||||
int error, rid;
|
||||
|
||||
rid = 0;
|
||||
res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2,
|
||||
RF_ACTIVE);
|
||||
if (res == NULL)
|
||||
return ENXIO;
|
||||
isa_load_resourcev(res, pckbd_iat, 2);
|
||||
|
||||
error = pckbd_attach_unit(device_get_unit(dev), &kbd,
|
||||
isa_get_port(dev),
|
||||
(1 << isa_get_irq(dev)),
|
||||
device_get_flags(dev));
|
||||
|
||||
rid = 0;
|
||||
res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||
if (res == NULL)
|
||||
return ENXIO;
|
||||
BUS_SETUP_INTR(device_get_parent(dev), dev, res, INTR_TYPE_TTY,
|
||||
pckbd_isa_intr, kbd, &ih);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pckbdresume(device_t dev)
|
||||
{
|
||||
keyboard_t *kbd;
|
||||
|
||||
kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME,
|
||||
device_get_unit(dev)));
|
||||
if (kbd)
|
||||
(*kbdsw[kbd->kb_index]->clear_state)(kbd);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
pckbd_isa_intr(void *arg)
|
||||
{
|
||||
keyboard_t *kbd = arg;
|
||||
|
||||
(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
pckbd_probe_unit(int unit, int port, int irq, int flags)
|
||||
{
|
||||
keyboard_switch_t *sw;
|
||||
int args[2];
|
||||
int error;
|
||||
|
||||
sw = kbd_get_switch(DRIVER_NAME);
|
||||
if (sw == NULL)
|
||||
return ENXIO;
|
||||
|
||||
args[0] = port;
|
||||
args[1] = irq;
|
||||
error = (*sw->probe)(unit, args, flags);
|
||||
if (error)
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pckbd_attach_unit(int unit, keyboard_t **kbd, int port, int irq, int flags)
|
||||
{
|
||||
keyboard_switch_t *sw;
|
||||
int args[2];
|
||||
int error;
|
||||
|
||||
sw = kbd_get_switch(DRIVER_NAME);
|
||||
if (sw == NULL)
|
||||
return ENXIO;
|
||||
|
||||
/* reset, initialize and enable the device */
|
||||
args[0] = port;
|
||||
args[1] = irq;
|
||||
*kbd = NULL;
|
||||
error = (*sw->probe)(unit, args, flags);
|
||||
if (error)
|
||||
return error;
|
||||
error = (*sw->init)(unit, kbd, args, flags);
|
||||
if (error)
|
||||
return error;
|
||||
(*sw->enable)(*kbd);
|
||||
|
||||
#ifdef KBD_INSTALL_CDEV
|
||||
/* attach a virtual keyboard cdev */
|
||||
error = kbd_attach(*kbd);
|
||||
if (error)
|
||||
return error;
|
||||
#endif /* KBD_INSTALL_CDEV */
|
||||
|
||||
/*
|
||||
* This is a kludge to compensate for lost keyboard interrupts.
|
||||
* A similar code used to be in syscons. See below. XXX
|
||||
*/
|
||||
pckbd_timeout(*kbd);
|
||||
|
||||
if (bootverbose)
|
||||
(*sw->diag)(*kbd, bootverbose);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pckbd_timeout(void *arg)
|
||||
{
|
||||
keyboard_t *kbd;
|
||||
int s;
|
||||
|
||||
/* The following comments are extracted from syscons.c (1.287) */
|
||||
/*
|
||||
* With release 2.1 of the Xaccel server, the keyboard is left
|
||||
* hanging pretty often. Apparently an interrupt from the
|
||||
* keyboard is lost, and I don't know why (yet).
|
||||
* This ugly hack calls scintr if input is ready for the keyboard
|
||||
* and conveniently hides the problem. XXX
|
||||
*/
|
||||
/*
|
||||
* Try removing anything stuck in the keyboard controller; whether
|
||||
* it's a keyboard scan code or mouse data. `scintr()' doesn't
|
||||
* read the mouse data directly, but `kbdio' routines will, as a
|
||||
* side effect.
|
||||
*/
|
||||
s = spltty();
|
||||
kbd = (keyboard_t *)arg;
|
||||
if ((*kbdsw[kbd->kb_index]->lock)(kbd, TRUE)) {
|
||||
/*
|
||||
* We have seen the lock flag is not set. Let's reset
|
||||
* the flag early, otherwise the LED update routine fails
|
||||
* which may want the lock during the interrupt routine.
|
||||
*/
|
||||
(*kbdsw[kbd->kb_index]->lock)(kbd, FALSE);
|
||||
if ((*kbdsw[kbd->kb_index]->check_char)(kbd))
|
||||
(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
|
||||
}
|
||||
splx(s);
|
||||
timeout(pckbd_timeout, arg, hz/10);
|
||||
}
|
||||
|
||||
/* LOW-LEVEL */
|
||||
|
||||
#include <sys/limits.h>
|
||||
|
||||
#define PC98KBD_DEFAULT 0
|
||||
|
||||
typedef caddr_t KBDC;
|
||||
|
||||
typedef struct pckbd_state {
|
||||
KBDC kbdc; /* keyboard controller */
|
||||
int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
|
||||
int ks_flags; /* flags */
|
||||
#define COMPOSE (1 << 0)
|
||||
int ks_state; /* shift/lock key state */
|
||||
int ks_accents; /* accent key index (> 0) */
|
||||
u_int ks_composed_char; /* composed char code (> 0) */
|
||||
} pckbd_state_t;
|
||||
|
||||
/* keyboard driver declaration */
|
||||
static int pckbd_configure(int flags);
|
||||
static kbd_probe_t pckbd_probe;
|
||||
static kbd_init_t pckbd_init;
|
||||
static kbd_term_t pckbd_term;
|
||||
static kbd_intr_t pckbd_intr;
|
||||
static kbd_test_if_t pckbd_test_if;
|
||||
static kbd_enable_t pckbd_enable;
|
||||
static kbd_disable_t pckbd_disable;
|
||||
static kbd_read_t pckbd_read;
|
||||
static kbd_check_t pckbd_check;
|
||||
static kbd_read_char_t pckbd_read_char;
|
||||
static kbd_check_char_t pckbd_check_char;
|
||||
static kbd_ioctl_t pckbd_ioctl;
|
||||
static kbd_lock_t pckbd_lock;
|
||||
static kbd_clear_state_t pckbd_clear_state;
|
||||
static kbd_get_state_t pckbd_get_state;
|
||||
static kbd_set_state_t pckbd_set_state;
|
||||
static kbd_poll_mode_t pckbd_poll;
|
||||
|
||||
keyboard_switch_t pckbdsw = {
|
||||
pckbd_probe,
|
||||
pckbd_init,
|
||||
pckbd_term,
|
||||
pckbd_intr,
|
||||
pckbd_test_if,
|
||||
pckbd_enable,
|
||||
pckbd_disable,
|
||||
pckbd_read,
|
||||
pckbd_check,
|
||||
pckbd_read_char,
|
||||
pckbd_check_char,
|
||||
pckbd_ioctl,
|
||||
pckbd_lock,
|
||||
pckbd_clear_state,
|
||||
pckbd_get_state,
|
||||
pckbd_set_state,
|
||||
genkbd_get_fkeystr,
|
||||
pckbd_poll,
|
||||
genkbd_diag,
|
||||
};
|
||||
|
||||
KEYBOARD_DRIVER(pckbd, pckbdsw, pckbd_configure);
|
||||
|
||||
struct kbdc_softc {
|
||||
int port; /* base port address */
|
||||
int lock; /* FIXME: XXX not quite a semaphore... */
|
||||
};
|
||||
|
||||
/* local functions */
|
||||
static int probe_keyboard(KBDC kbdc, int flags);
|
||||
static int init_keyboard(KBDC kbdc, int *type, int flags);
|
||||
static KBDC kbdc_open(int port);
|
||||
static int kbdc_lock(KBDC kbdc, int lock);
|
||||
static int kbdc_data_ready(KBDC kbdc);
|
||||
static int read_kbd_data(KBDC kbdc);
|
||||
static int read_kbd_data_no_wait(KBDC kbdc);
|
||||
static int wait_for_kbd_data(struct kbdc_softc *kbdc);
|
||||
|
||||
/* local variables */
|
||||
|
||||
/* the initial key map, accent map and fkey strings */
|
||||
#include <dev/kbd/kbdtables.h>
|
||||
|
||||
/* structures for the default keyboard */
|
||||
static keyboard_t default_kbd;
|
||||
static pckbd_state_t default_kbd_state;
|
||||
static keymap_t default_keymap;
|
||||
static accentmap_t default_accentmap;
|
||||
static fkeytab_t default_fkeytab[NUM_FKEYS];
|
||||
|
||||
/*
|
||||
* The back door to the keyboard driver!
|
||||
* This function is called by the console driver, via the kbdio module,
|
||||
* to tickle keyboard drivers when the low-level console is being initialized.
|
||||
* Almost nothing in the kernel has been initialied yet. Try to probe
|
||||
* keyboards if possible.
|
||||
* NOTE: because of the way the low-level conole is initialized, this routine
|
||||
* may be called more than once!!
|
||||
*/
|
||||
static int
|
||||
pckbd_configure(int flags)
|
||||
{
|
||||
keyboard_t *kbd;
|
||||
int arg[2];
|
||||
int i;
|
||||
|
||||
/* XXX: a kludge to obtain the device configuration flags */
|
||||
if (resource_int_value(DRIVER_NAME, 0, "flags", &i) == 0) {
|
||||
flags |= i;
|
||||
/* if the driver is disabled, unregister the keyboard if any */
|
||||
if (resource_disabled(DRIVER_NAME, 0)) {
|
||||
i = kbd_find_keyboard(DRIVER_NAME, PC98KBD_DEFAULT);
|
||||
if (i >= 0) {
|
||||
kbd = kbd_get_keyboard(i);
|
||||
kbd_unregister(kbd);
|
||||
kbd->kb_flags &= ~KB_REGISTERED;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* probe the default keyboard */
|
||||
arg[0] = -1;
|
||||
arg[1] = -1;
|
||||
kbd = NULL;
|
||||
if (pckbd_probe(PC98KBD_DEFAULT, arg, flags))
|
||||
return 0;
|
||||
if (pckbd_init(PC98KBD_DEFAULT, &kbd, arg, flags))
|
||||
return 0;
|
||||
|
||||
/* return the number of found keyboards */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* low-level functions */
|
||||
|
||||
/* detect a keyboard */
|
||||
static int
|
||||
pckbd_probe(int unit, void *arg, int flags)
|
||||
{
|
||||
KBDC kbdc;
|
||||
int *data = (int *)arg;
|
||||
|
||||
if (unit != PC98KBD_DEFAULT)
|
||||
return ENXIO;
|
||||
if (KBD_IS_PROBED(&default_kbd))
|
||||
return 0;
|
||||
|
||||
kbdc = kbdc_open(data[0]);
|
||||
if (kbdc == NULL)
|
||||
return ENXIO;
|
||||
if (probe_keyboard(kbdc, flags)) {
|
||||
if (flags & KB_CONF_FAIL_IF_NO_KBD)
|
||||
return ENXIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reset and initialize the device */
|
||||
static int
|
||||
pckbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
|
||||
{
|
||||
keyboard_t *kbd;
|
||||
pckbd_state_t *state;
|
||||
keymap_t *keymap;
|
||||
accentmap_t *accmap;
|
||||
fkeytab_t *fkeymap;
|
||||
int fkeymap_size;
|
||||
int *data = (int *)arg;
|
||||
|
||||
if (unit != PC98KBD_DEFAULT) /* shouldn't happen */
|
||||
return ENXIO;
|
||||
|
||||
*kbdp = kbd = &default_kbd;
|
||||
state = &default_kbd_state;
|
||||
if (!KBD_IS_PROBED(kbd)) {
|
||||
keymap = &default_keymap;
|
||||
accmap = &default_accentmap;
|
||||
fkeymap = default_fkeytab;
|
||||
fkeymap_size =
|
||||
sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
|
||||
|
||||
state->kbdc = kbdc_open(data[0]);
|
||||
if (state->kbdc == NULL)
|
||||
return ENXIO;
|
||||
kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags,
|
||||
data[0], IO_KBDSIZE);
|
||||
bcopy(&key_map, keymap, sizeof(key_map));
|
||||
bcopy(&accent_map, accmap, sizeof(accent_map));
|
||||
bcopy(fkey_tab, fkeymap,
|
||||
imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
|
||||
kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
|
||||
kbd->kb_data = (void *)state;
|
||||
|
||||
if (probe_keyboard(state->kbdc, flags)) {/* shouldn't happen */
|
||||
if (flags & KB_CONF_FAIL_IF_NO_KBD)
|
||||
return ENXIO;
|
||||
} else {
|
||||
KBD_FOUND_DEVICE(kbd);
|
||||
}
|
||||
pckbd_clear_state(kbd);
|
||||
state->ks_mode = K_XLATE;
|
||||
KBD_PROBE_DONE(kbd);
|
||||
}
|
||||
if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
|
||||
if (KBD_HAS_DEVICE(kbd)
|
||||
&& init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
|
||||
&& (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
|
||||
return ENXIO;
|
||||
pckbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
|
||||
KBD_INIT_DONE(kbd);
|
||||
}
|
||||
if (!KBD_IS_CONFIGURED(kbd)) {
|
||||
if (kbd_register(kbd) < 0)
|
||||
return ENXIO;
|
||||
KBD_CONFIG_DONE(kbd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* finish using this keyboard */
|
||||
static int
|
||||
pckbd_term(keyboard_t *kbd)
|
||||
{
|
||||
kbd_unregister(kbd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* keyboard interrupt routine */
|
||||
static int
|
||||
pckbd_intr(keyboard_t *kbd, void *arg)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
|
||||
/* let the callback function to process the input */
|
||||
(*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
|
||||
kbd->kb_callback.kc_arg);
|
||||
} else {
|
||||
/* read and discard the input; no one is waiting for input */
|
||||
do {
|
||||
c = pckbd_read_char(kbd, FALSE);
|
||||
} while (c != NOKEY);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* test the interface to the device */
|
||||
static int
|
||||
pckbd_test_if(keyboard_t *kbd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the access to the device; until this function is called,
|
||||
* the client cannot read from the keyboard.
|
||||
*/
|
||||
static int
|
||||
pckbd_enable(keyboard_t *kbd)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = spltty();
|
||||
KBD_ACTIVATE(kbd);
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* disallow the access to the device */
|
||||
static int
|
||||
pckbd_disable(keyboard_t *kbd)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = spltty();
|
||||
KBD_DEACTIVATE(kbd);
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read one byte from the keyboard if it's allowed */
|
||||
static int
|
||||
pckbd_read(keyboard_t *kbd, int wait)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (wait)
|
||||
c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc);
|
||||
else
|
||||
c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc);
|
||||
if (c != -1)
|
||||
++kbd->kb_count;
|
||||
return (KBD_IS_ACTIVE(kbd) ? c : -1);
|
||||
}
|
||||
|
||||
/* check if data is waiting */
|
||||
static int
|
||||
pckbd_check(keyboard_t *kbd)
|
||||
{
|
||||
if (!KBD_IS_ACTIVE(kbd))
|
||||
return FALSE;
|
||||
return kbdc_data_ready(((pckbd_state_t *)kbd->kb_data)->kbdc);
|
||||
}
|
||||
|
||||
/* read char from the keyboard */
|
||||
static u_int
|
||||
pckbd_read_char(keyboard_t *kbd, int wait)
|
||||
{
|
||||
pckbd_state_t *state;
|
||||
u_int action;
|
||||
int scancode;
|
||||
int keycode;
|
||||
|
||||
state = (pckbd_state_t *)kbd->kb_data;
|
||||
next_code:
|
||||
/* do we have a composed char to return? */
|
||||
if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
|
||||
action = state->ks_composed_char;
|
||||
state->ks_composed_char = 0;
|
||||
if (action > UCHAR_MAX)
|
||||
return ERRKEY;
|
||||
return action;
|
||||
}
|
||||
|
||||
/* see if there is something in the keyboard port */
|
||||
if (wait) {
|
||||
do {
|
||||
scancode = read_kbd_data(state->kbdc);
|
||||
} while (scancode == -1);
|
||||
} else {
|
||||
scancode = read_kbd_data_no_wait(state->kbdc);
|
||||
if (scancode == -1)
|
||||
return NOKEY;
|
||||
}
|
||||
++kbd->kb_count;
|
||||
|
||||
#if 0
|
||||
printf("pckbd_read_char(): scancode:0x%x\n", scancode);
|
||||
#endif
|
||||
|
||||
/* return the byte as is for the K_RAW mode */
|
||||
if (state->ks_mode == K_RAW)
|
||||
return scancode;
|
||||
|
||||
/* translate the scan code into a keycode */
|
||||
keycode = scancode & 0x7F;
|
||||
switch(scancode) {
|
||||
case 0xF3: /* GRPH (compose key) released */
|
||||
if (state->ks_flags & COMPOSE) {
|
||||
state->ks_flags &= ~COMPOSE;
|
||||
if (state->ks_composed_char > UCHAR_MAX)
|
||||
state->ks_composed_char = 0;
|
||||
}
|
||||
break;
|
||||
case 0x73: /* GRPH (compose key) pressed */
|
||||
if (!(state->ks_flags & COMPOSE)) {
|
||||
state->ks_flags |= COMPOSE;
|
||||
state->ks_composed_char = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* return the key code in the K_CODE mode */
|
||||
if (state->ks_mode == K_CODE)
|
||||
return (keycode | (scancode & 0x80));
|
||||
|
||||
/* compose a character code */
|
||||
if (state->ks_flags & COMPOSE) {
|
||||
switch (scancode) {
|
||||
/* key pressed, process it */
|
||||
case 0x42: case 0x43: case 0x44: /* keypad 7,8,9 */
|
||||
state->ks_composed_char *= 10;
|
||||
state->ks_composed_char += scancode - 0x3B;
|
||||
if (state->ks_composed_char > UCHAR_MAX)
|
||||
return ERRKEY;
|
||||
goto next_code;
|
||||
case 0x46: case 0x47: case 0x48: /* keypad 4,5,6 */
|
||||
state->ks_composed_char *= 10;
|
||||
state->ks_composed_char += scancode - 0x42;
|
||||
if (state->ks_composed_char > UCHAR_MAX)
|
||||
return ERRKEY;
|
||||
goto next_code;
|
||||
case 0x4A: case 0x4B: case 0x4C: /* keypad 1,2,3 */
|
||||
state->ks_composed_char *= 10;
|
||||
state->ks_composed_char += scancode - 0x49;
|
||||
if (state->ks_composed_char > UCHAR_MAX)
|
||||
return ERRKEY;
|
||||
goto next_code;
|
||||
case 0x4E: /* keypad 0 */
|
||||
state->ks_composed_char *= 10;
|
||||
if (state->ks_composed_char > UCHAR_MAX)
|
||||
return ERRKEY;
|
||||
goto next_code;
|
||||
|
||||
/* key released, no interest here */
|
||||
case 0xC2: case 0xC3: case 0xC4: /* keypad 7,8,9 */
|
||||
case 0xC6: case 0xC7: case 0xC8: /* keypad 4,5,6 */
|
||||
case 0xCA: case 0xCB: case 0xCC: /* keypad 1,2,3 */
|
||||
case 0xCE: /* keypad 0 */
|
||||
goto next_code;
|
||||
|
||||
case 0x73: /* GRPH key */
|
||||
break;
|
||||
|
||||
default:
|
||||
if (state->ks_composed_char > 0) {
|
||||
state->ks_flags &= ~COMPOSE;
|
||||
state->ks_composed_char = 0;
|
||||
return ERRKEY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* keycode to key action */
|
||||
action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
|
||||
&state->ks_state, &state->ks_accents);
|
||||
if (action == NOKEY)
|
||||
goto next_code;
|
||||
else
|
||||
return action;
|
||||
}
|
||||
|
||||
/* check if char is waiting */
|
||||
static int
|
||||
pckbd_check_char(keyboard_t *kbd)
|
||||
{
|
||||
pckbd_state_t *state;
|
||||
|
||||
if (!KBD_IS_ACTIVE(kbd))
|
||||
return FALSE;
|
||||
state = (pckbd_state_t *)kbd->kb_data;
|
||||
if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
|
||||
return TRUE;
|
||||
return kbdc_data_ready(state->kbdc);
|
||||
}
|
||||
|
||||
/* some useful control functions */
|
||||
static int
|
||||
pckbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
|
||||
{
|
||||
pckbd_state_t *state = kbd->kb_data;
|
||||
int s;
|
||||
int i;
|
||||
|
||||
s = spltty();
|
||||
switch (cmd) {
|
||||
|
||||
case KDGKBMODE: /* get keyboard mode */
|
||||
*(int *)arg = state->ks_mode;
|
||||
break;
|
||||
case KDSKBMODE: /* set keyboard mode */
|
||||
switch (*(int *)arg) {
|
||||
case K_XLATE:
|
||||
if (state->ks_mode != K_XLATE) {
|
||||
/* make lock key state and LED state match */
|
||||
state->ks_state &= ~LOCK_MASK;
|
||||
state->ks_state |= KBD_LED_VAL(kbd);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case K_RAW:
|
||||
case K_CODE:
|
||||
if (state->ks_mode != *(int *)arg) {
|
||||
pckbd_clear_state(kbd);
|
||||
state->ks_mode = *(int *)arg;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
splx(s);
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case KDGETLED: /* get keyboard LED */
|
||||
*(int *)arg = KBD_LED_VAL(kbd);
|
||||
break;
|
||||
case KDSETLED: /* set keyboard LED */
|
||||
/* NOTE: lock key state in ks_state won't be changed */
|
||||
if (*(int *)arg & ~LOCK_MASK) {
|
||||
splx(s);
|
||||
return EINVAL;
|
||||
}
|
||||
i = *(int *)arg;
|
||||
/* replace CAPS LED with ALTGR LED for ALTGR keyboards */
|
||||
if (kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
|
||||
if (i & ALKED)
|
||||
i |= CLKED;
|
||||
else
|
||||
i &= ~CLKED;
|
||||
}
|
||||
KBD_LED_VAL(kbd) = *(int *)arg;
|
||||
break;
|
||||
|
||||
case KDGKBSTATE: /* get lock key state */
|
||||
*(int *)arg = state->ks_state & LOCK_MASK;
|
||||
break;
|
||||
case KDSKBSTATE: /* set lock key state */
|
||||
if (*(int *)arg & ~LOCK_MASK) {
|
||||
splx(s);
|
||||
return EINVAL;
|
||||
}
|
||||
state->ks_state &= ~LOCK_MASK;
|
||||
state->ks_state |= *(int *)arg;
|
||||
splx(s);
|
||||
/* set LEDs and quit */
|
||||
return pckbd_ioctl(kbd, KDSETLED, arg);
|
||||
|
||||
case KDSETRAD: /* set keyboard repeat rate (old interface)*/
|
||||
break;
|
||||
case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
|
||||
break;
|
||||
|
||||
case PIO_KEYMAP: /* set keyboard translation table */
|
||||
case PIO_KEYMAPENT: /* set keyboard translation table entry */
|
||||
case PIO_DEADKEYMAP: /* set accent key translation table */
|
||||
state->ks_accents = 0;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
splx(s);
|
||||
return genkbd_commonioctl(kbd, cmd, arg);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* lock the access to the keyboard */
|
||||
static int
|
||||
pckbd_lock(keyboard_t *kbd, int lock)
|
||||
{
|
||||
return kbdc_lock(((pckbd_state_t *)kbd->kb_data)->kbdc, lock);
|
||||
}
|
||||
|
||||
/* clear the internal state of the keyboard */
|
||||
static void
|
||||
pckbd_clear_state(keyboard_t *kbd)
|
||||
{
|
||||
pckbd_state_t *state;
|
||||
|
||||
state = (pckbd_state_t *)kbd->kb_data;
|
||||
state->ks_flags = 0;
|
||||
state->ks_state &= LOCK_MASK; /* preserve locking key state */
|
||||
state->ks_accents = 0;
|
||||
state->ks_composed_char = 0;
|
||||
}
|
||||
|
||||
/* save the internal state */
|
||||
static int
|
||||
pckbd_get_state(keyboard_t *kbd, void *buf, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return sizeof(pckbd_state_t);
|
||||
if (len < sizeof(pckbd_state_t))
|
||||
return -1;
|
||||
bcopy(kbd->kb_data, buf, sizeof(pckbd_state_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the internal state */
|
||||
static int
|
||||
pckbd_set_state(keyboard_t *kbd, void *buf, size_t len)
|
||||
{
|
||||
if (len < sizeof(pckbd_state_t))
|
||||
return ENOMEM;
|
||||
if (((pckbd_state_t *)kbd->kb_data)->kbdc
|
||||
!= ((pckbd_state_t *)buf)->kbdc)
|
||||
return ENOMEM;
|
||||
bcopy(buf, kbd->kb_data, sizeof(pckbd_state_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set polling mode */
|
||||
static int
|
||||
pckbd_poll(keyboard_t *kbd, int on)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* local functions */
|
||||
|
||||
static int
|
||||
probe_keyboard(KBDC kbdc, int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_keyboard(KBDC kbdc, int *type, int flags)
|
||||
{
|
||||
*type = KB_OTHER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* keyboard I/O routines */
|
||||
|
||||
/* retry count */
|
||||
#ifndef KBD_MAXRETRY
|
||||
#define KBD_MAXRETRY 3
|
||||
#endif
|
||||
|
||||
/* timing parameters */
|
||||
#ifndef KBD_RESETDELAY
|
||||
#define KBD_RESETDELAY 200 /* wait 200msec after kbd/mouse reset */
|
||||
#endif
|
||||
#ifndef KBD_MAXWAIT
|
||||
#define KBD_MAXWAIT 5 /* wait 5 times at most after reset */
|
||||
#endif
|
||||
|
||||
/* I/O recovery time */
|
||||
#define KBDC_DELAYTIME 37
|
||||
#define KBDD_DELAYTIME 37
|
||||
|
||||
/* I/O ports */
|
||||
#define KBD_STATUS_PORT 2 /* status port, read */
|
||||
#define KBD_DATA_PORT 0 /* data port, read */
|
||||
|
||||
/* status bits (KBD_STATUS_PORT) */
|
||||
#define KBDS_BUFFER_FULL 0x0002
|
||||
|
||||
/* macros */
|
||||
|
||||
#define kbdcp(p) ((struct kbdc_softc *)(p))
|
||||
|
||||
/* local variables */
|
||||
|
||||
static struct kbdc_softc kbdc_softc[1] = { { 0 }, };
|
||||
|
||||
/* associate a port number with a KBDC */
|
||||
|
||||
static KBDC
|
||||
kbdc_open(int port)
|
||||
{
|
||||
if (port <= 0)
|
||||
port = IO_KBD;
|
||||
|
||||
/* PC-98 has only one keyboard I/F */
|
||||
kbdc_softc[0].port = port;
|
||||
kbdc_softc[0].lock = FALSE;
|
||||
return (KBDC)&kbdc_softc[0];
|
||||
}
|
||||
|
||||
/* set/reset polling lock */
|
||||
static int
|
||||
kbdc_lock(KBDC p, int lock)
|
||||
{
|
||||
int prevlock;
|
||||
|
||||
prevlock = kbdcp(p)->lock;
|
||||
kbdcp(p)->lock = lock;
|
||||
|
||||
return (prevlock != lock);
|
||||
}
|
||||
|
||||
/* check if any data is waiting to be processed */
|
||||
static int
|
||||
kbdc_data_ready(KBDC p)
|
||||
{
|
||||
return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL);
|
||||
}
|
||||
|
||||
/* wait for data from the keyboard */
|
||||
static int
|
||||
wait_for_kbd_data(struct kbdc_softc *kbdc)
|
||||
{
|
||||
/* CPU will stay inside the loop for 200msec at most */
|
||||
int retry = 10000;
|
||||
int port = kbdc->port;
|
||||
|
||||
while (!(inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)) {
|
||||
DELAY(KBDD_DELAYTIME);
|
||||
DELAY(KBDC_DELAYTIME);
|
||||
if (--retry < 0)
|
||||
return 0;
|
||||
}
|
||||
DELAY(KBDD_DELAYTIME);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* read one byte from the keyboard */
|
||||
static int
|
||||
read_kbd_data(KBDC p)
|
||||
{
|
||||
if (!wait_for_kbd_data(kbdcp(p)))
|
||||
return -1; /* timeout */
|
||||
DELAY(KBDC_DELAYTIME);
|
||||
return inb(kbdcp(p)->port + KBD_DATA_PORT);
|
||||
}
|
||||
|
||||
/* read one byte from the keyboard, but return immediately if
|
||||
* no data is waiting
|
||||
*/
|
||||
static int
|
||||
read_kbd_data_no_wait(KBDC p)
|
||||
{
|
||||
if (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) {
|
||||
DELAY(KBDD_DELAYTIME);
|
||||
return inb(kbdcp(p)->port + KBD_DATA_PORT);
|
||||
}
|
||||
return -1; /* no data */
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
/*-
|
||||
* PMC (Power Management Controller of NEC PC-98Note) Driver
|
||||
*
|
||||
* Copyright (c) 2001 Chiharu Shibata.
|
||||
* 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. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
|
||||
struct pmc_isa_softc {
|
||||
struct resource *port_res;
|
||||
eventhandler_tag evt;
|
||||
int flags;
|
||||
};
|
||||
|
||||
static int pmc_isa_alloc_resources(device_t);
|
||||
static void pmc_isa_release_resources(device_t);
|
||||
static int pmc_isa_probe(device_t);
|
||||
static int pmc_isa_attach(device_t);
|
||||
static int pmc_isa_detach(device_t);
|
||||
|
||||
#define PMC_ISA_PORT 0x8f0
|
||||
#define PMC_ISA_PORTSIZE 4
|
||||
|
||||
#define sc_inw(sc, port) \
|
||||
bus_space_read_2(rman_get_bustag((sc)->port_res), \
|
||||
rman_get_bushandle((sc)->port_res), (port))
|
||||
|
||||
#define sc_outw(sc, port, value) \
|
||||
bus_space_write_2(rman_get_bustag((sc)->port_res), \
|
||||
rman_get_bushandle((sc)->port_res), (port), (value))
|
||||
|
||||
static void
|
||||
pmc_poweroff(void *arg, int howto)
|
||||
{
|
||||
struct pmc_isa_softc *sc = (struct pmc_isa_softc *)arg;
|
||||
|
||||
if (!sc->flags) {
|
||||
outb(0x5e8e, inb(0x5e8e) & ~0x11); /* FDD LED off */
|
||||
}
|
||||
|
||||
if (!(howto & RB_POWEROFF)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sc_outw(sc, 0, 0x0044);
|
||||
sc_outw(sc, 2, 1 << 10);
|
||||
#if 1
|
||||
/* for 9801NS/T */
|
||||
sc_outw(sc, 0, 0xf00a);
|
||||
sc_outw(sc, 2, 1 << 9);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
pmc_isa_alloc_resources(device_t dev)
|
||||
{
|
||||
struct pmc_isa_softc *sc = device_get_softc(dev);
|
||||
int rid;
|
||||
|
||||
bzero(sc, sizeof(*sc));
|
||||
|
||||
rid = 0;
|
||||
sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
|
||||
0ul, ~0ul, PMC_ISA_PORTSIZE,
|
||||
RF_ACTIVE);
|
||||
if (sc->port_res == NULL) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pmc_isa_release_resources(device_t dev)
|
||||
{
|
||||
struct pmc_isa_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (sc->port_res != NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port_res);
|
||||
}
|
||||
sc->port_res = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
pmc_isa_probe(device_t dev)
|
||||
{
|
||||
struct pmc_isa_softc *sc = device_get_softc(dev);
|
||||
u_int port;
|
||||
u_int16_t save, tmp;
|
||||
|
||||
#if 0
|
||||
if (isa_get_vendorid(dev)) {
|
||||
return ENXIO;
|
||||
}
|
||||
if (device_get_unit(dev) > 0) {
|
||||
printf("pmc: Only one PMC driver supported.\n");
|
||||
return ENXIO;
|
||||
}
|
||||
#endif
|
||||
port = isa_get_port(dev);
|
||||
if (port == -1) {
|
||||
port = PMC_ISA_PORT;
|
||||
}
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "port = 0x%x\n", port);
|
||||
}
|
||||
|
||||
if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port, PMC_ISA_PORTSIZE)) {
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "bus_set_resource failed\n");
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
if (pmc_isa_alloc_resources(dev)) {
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "pmc_isa_alloc_resources failed\n");
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
/* Check the existence of PMC */
|
||||
sc_outw(sc, 0, 0x0052);
|
||||
save = sc_inw(sc, 2);
|
||||
tmp = save & ~0x3f;
|
||||
sc_outw(sc, 2, tmp);
|
||||
if (sc_inw(sc, 2) != tmp) {
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "failed to clear index(0x0052)\n");
|
||||
}
|
||||
|
||||
pmc_isa_release_resources(dev);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
tmp |= 0x3e;
|
||||
sc_outw(sc, 2, tmp);
|
||||
if (sc_inw(sc, 2) != tmp) {
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "failed to set index(0x0052)\n");
|
||||
}
|
||||
|
||||
pmc_isa_release_resources(dev);
|
||||
return ENXIO;
|
||||
}
|
||||
sc_outw(sc, 2, save);
|
||||
|
||||
pmc_isa_release_resources(dev);
|
||||
|
||||
device_set_desc(dev, "Power Management Controller");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pmc_isa_attach(device_t dev)
|
||||
{
|
||||
struct pmc_isa_softc *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
error = pmc_isa_alloc_resources(dev);
|
||||
if (error) {
|
||||
device_printf(dev, "resource allocation failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Power the system off using PMC */
|
||||
sc->evt = EVENTHANDLER_REGISTER(shutdown_final, pmc_poweroff, sc,
|
||||
SHUTDOWN_PRI_LAST);
|
||||
sc->flags = device_get_flags(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pmc_isa_detach(device_t dev)
|
||||
{
|
||||
struct pmc_isa_softc *sc = device_get_softc(dev);
|
||||
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "pmc_isa_detach called\n");
|
||||
}
|
||||
|
||||
if (sc->evt != NULL) {
|
||||
EVENTHANDLER_DEREGISTER(shutdown_final, sc->evt);
|
||||
}
|
||||
sc->evt = NULL;
|
||||
|
||||
pmc_isa_release_resources(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static device_method_t pmc_isa_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, pmc_isa_probe),
|
||||
DEVMETHOD(device_attach, pmc_isa_attach),
|
||||
DEVMETHOD(device_detach, pmc_isa_detach),
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static driver_t pmc_isa_driver = {
|
||||
"pmc",
|
||||
pmc_isa_methods, sizeof(struct pmc_isa_softc),
|
||||
};
|
||||
|
||||
devclass_t pmc_devclass;
|
||||
|
||||
DRIVER_MODULE(pmc, isa, pmc_isa_driver, pmc_devclass, 0, 0);
|
2212
sys/pc98/pc98/ppc.c
2212
sys/pc98/pc98/ppc.c
File diff suppressed because it is too large
Load Diff
@ -1,280 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Alcove - Nicolas Souchu
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
*/
|
||||
#ifndef __PPCREG_H
|
||||
#define __PPCREG_H
|
||||
|
||||
/*
|
||||
* Parallel Port Chipset type.
|
||||
*/
|
||||
#define SMC_LIKE 0
|
||||
#define SMC_37C665GT 1
|
||||
#define SMC_37C666GT 2
|
||||
#define NS_PC87332 3
|
||||
#define NS_PC87306 4
|
||||
#define INTEL_820191AA 5 /* XXX not implemented */
|
||||
#define GENERIC 6
|
||||
#define WINB_W83877F 7
|
||||
#define WINB_W83877AF 8
|
||||
#define WINB_UNKNOWN 9
|
||||
#define NS_PC87334 10
|
||||
#define SMC_37C935 11
|
||||
#define NS_PC87303 12
|
||||
|
||||
/*
|
||||
* Parallel Port Chipset Type. SMC versus GENERIC (others)
|
||||
*/
|
||||
#define PPC_TYPE_SMCLIKE 0
|
||||
#define PPC_TYPE_GENERIC 1
|
||||
|
||||
/*
|
||||
* Generic structure to hold parallel port chipset info.
|
||||
*/
|
||||
struct ppc_data {
|
||||
|
||||
int ppc_unit;
|
||||
int ppc_model; /* chipset model if detected */
|
||||
int ppc_type; /* generic or smclike chipset type */
|
||||
|
||||
int ppc_mode; /* chipset current mode */
|
||||
int ppc_avm; /* chipset available modes */
|
||||
int ppc_dtm; /* chipset detected modes */
|
||||
|
||||
#define PPC_IRQ_NONE 0x0
|
||||
#define PPC_IRQ_nACK 0x1
|
||||
#define PPC_IRQ_DMA 0x2
|
||||
#define PPC_IRQ_FIFO 0x4
|
||||
#define PPC_IRQ_nFAULT 0x8
|
||||
int ppc_irqstat; /* remind irq settings */
|
||||
|
||||
#define PPC_DMA_INIT 0x01
|
||||
#define PPC_DMA_STARTED 0x02
|
||||
#define PPC_DMA_COMPLETE 0x03
|
||||
#define PPC_DMA_INTERRUPTED 0x04
|
||||
#define PPC_DMA_ERROR 0x05
|
||||
int ppc_dmastat; /* dma state */
|
||||
int ppc_dmachan; /* dma channel */
|
||||
int ppc_dmaflags; /* dma transfer flags */
|
||||
caddr_t ppc_dmaddr; /* buffer address */
|
||||
u_int ppc_dmacnt; /* count of bytes sent with dma */
|
||||
|
||||
#define PPC_PWORD_MASK 0x30
|
||||
#define PPC_PWORD_16 0x00
|
||||
#define PPC_PWORD_8 0x10
|
||||
#define PPC_PWORD_32 0x20
|
||||
char ppc_pword; /* PWord size */
|
||||
short ppc_fifo; /* FIFO threshold */
|
||||
|
||||
short ppc_wthr; /* writeIntrThresold */
|
||||
short ppc_rthr; /* readIntrThresold */
|
||||
|
||||
char *ppc_ptr; /* microseq current pointer */
|
||||
int ppc_accum; /* microseq accumulator */
|
||||
int ppc_base; /* parallel port base address */
|
||||
int ppc_epp; /* EPP mode (1.7 or 1.9) */
|
||||
int ppc_irq;
|
||||
|
||||
unsigned char ppc_flags;
|
||||
|
||||
device_t ppbus; /* parallel port chipset corresponding ppbus */
|
||||
|
||||
int rid_irq, rid_drq, rid_ioport;
|
||||
struct resource *res_irq, *res_drq, *res_ioport;
|
||||
|
||||
bus_space_handle_t bsh;
|
||||
bus_space_tag_t bst;
|
||||
|
||||
void *intr_cookie;
|
||||
|
||||
int ppc_registered; /* 1 if ppcintr() is the registered interrupt */
|
||||
};
|
||||
|
||||
/*
|
||||
* Parallel Port Chipset registers.
|
||||
*/
|
||||
#define PPC_SPP_DTR 0 /* SPP data register */
|
||||
#define PPC_ECP_A_FIFO 0 /* ECP Address fifo register */
|
||||
#define PPC_SPP_STR 1 /* SPP status register */
|
||||
#define PPC_SPP_CTR 2 /* SPP control register */
|
||||
#define PPC_EPP_ADDR 3 /* EPP address register (8 bit) */
|
||||
#define PPC_EPP_DATA 4 /* EPP data register (8, 16 or 32 bit) */
|
||||
#ifdef PC98
|
||||
#define PPC_1284_ENABLE 0x09 /* IEEE STD 1284 Enable register */
|
||||
#define PPC_ECP_D_FIFO 0x0c /* ECP Data fifo register */
|
||||
#define PPC_ECP_CNFGA 0x0c /* Configuration register A */
|
||||
#define PPC_ECP_CNFGB 0x0d /* Configuration register B */
|
||||
#define PPC_ECP_ECR 0x0e /* ECP extended control register */
|
||||
#else
|
||||
#define PPC_ECP_D_FIFO 0x400 /* ECP Data fifo register */
|
||||
#define PPC_ECP_CNFGA 0x400 /* Configuration register A */
|
||||
#define PPC_ECP_CNFGB 0x401 /* Configuration register B */
|
||||
#define PPC_ECP_ECR 0x402 /* ECP extended control register */
|
||||
#endif
|
||||
|
||||
#define PPC_FIFO_EMPTY 0x1 /* ecr register - bit 0 */
|
||||
#define PPC_FIFO_FULL 0x2 /* ecr register - bit 1 */
|
||||
#define PPC_SERVICE_INTR 0x4 /* ecr register - bit 2 */
|
||||
#define PPC_ENABLE_DMA 0x8 /* ecr register - bit 3 */
|
||||
#define PPC_nFAULT_INTR 0x10 /* ecr register - bit 4 */
|
||||
#define PPC_ECR_STD 0x0
|
||||
#define PPC_ECR_PS2 0x20
|
||||
#define PPC_ECR_FIFO 0x40
|
||||
#define PPC_ECR_ECP 0x60
|
||||
#define PPC_ECR_EPP 0x80
|
||||
|
||||
#define PPC_DISABLE_INTR (PPC_SERVICE_INTR | PPC_nFAULT_INTR)
|
||||
#define PPC_ECR_RESET (PPC_ECR_PS2 | PPC_DISABLE_INTR)
|
||||
|
||||
#define r_dtr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR))
|
||||
#define r_str(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR))
|
||||
#define r_ctr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR))
|
||||
|
||||
#define r_epp_A(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR))
|
||||
#define r_epp_D(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA))
|
||||
#define r_cnfgA(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGA))
|
||||
#define r_cnfgB(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_CNFGB))
|
||||
#define r_ecr(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR))
|
||||
#define r_fifo(ppc) (bus_space_read_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO))
|
||||
|
||||
#define w_dtr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_DTR, byte))
|
||||
#define w_str(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_STR, byte))
|
||||
#define w_ctr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_SPP_CTR, byte))
|
||||
|
||||
#define w_epp_A(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_ADDR, byte))
|
||||
#define w_epp_D(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_EPP_DATA, byte))
|
||||
#define w_ecr(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_ECR, byte))
|
||||
#define w_fifo(ppc, byte) (bus_space_write_1((ppc)->bst, (ppc)->bsh, PPC_ECP_D_FIFO, byte))
|
||||
|
||||
/*
|
||||
* Register defines for the PC873xx parts
|
||||
*/
|
||||
|
||||
#define PC873_FER 0x00
|
||||
#define PC873_PPENABLE (1<<0)
|
||||
#define PC873_FAR 0x01
|
||||
#define PC873_PTR 0x02
|
||||
#define PC873_CFGLOCK (1<<6)
|
||||
#define PC873_EPPRDIR (1<<7)
|
||||
#define PC873_EXTENDED (1<<7)
|
||||
#define PC873_LPTBIRQ7 (1<<3)
|
||||
#define PC873_FCR 0x03
|
||||
#define PC873_ZWS (1<<5)
|
||||
#define PC873_ZWSPWDN (1<<6)
|
||||
#define PC873_PCR 0x04
|
||||
#define PC873_EPPEN (1<<0)
|
||||
#define PC873_EPP19 (1<<1)
|
||||
#define PC873_ECPEN (1<<2)
|
||||
#define PC873_ECPCLK (1<<3)
|
||||
#define PC873_PMC 0x06
|
||||
#define PC873_TUP 0x07
|
||||
#define PC873_SID 0x08
|
||||
#define PC873_PNP0 0x1b
|
||||
#define PC873_PNP1 0x1c
|
||||
#define PC873_LPTBA 0x19
|
||||
|
||||
/*
|
||||
* Register defines for the SMC FDC37C66xGT parts
|
||||
*/
|
||||
|
||||
/* Init codes */
|
||||
#define SMC665_iCODE 0x55
|
||||
#define SMC666_iCODE 0x44
|
||||
|
||||
/* Base configuration ports */
|
||||
#define SMC66x_CSR 0x3F0
|
||||
#define SMC666_CSR 0x370 /* hard-configured value for 666 */
|
||||
|
||||
/* Bits */
|
||||
#define SMC_CR1_ADDR 0x3 /* bit 0 and 1 */
|
||||
#define SMC_CR1_MODE (1<<3) /* bit 3 */
|
||||
#define SMC_CR4_EMODE 0x3 /* bits 0 and 1 */
|
||||
#define SMC_CR4_EPPTYPE (1<<6) /* bit 6 */
|
||||
|
||||
/* Extended modes */
|
||||
#define SMC_SPP 0x0 /* SPP */
|
||||
#define SMC_EPPSPP 0x1 /* EPP and SPP */
|
||||
#define SMC_ECP 0x2 /* ECP */
|
||||
#define SMC_ECPEPP 0x3 /* ECP and EPP */
|
||||
|
||||
/*
|
||||
* Register defines for the SMC FDC37C935 parts
|
||||
*/
|
||||
|
||||
/* Configuration ports */
|
||||
#define SMC935_CFG 0x370
|
||||
#define SMC935_IND 0x370
|
||||
#define SMC935_DAT 0x371
|
||||
|
||||
/* Registers */
|
||||
#define SMC935_LOGDEV 0x7
|
||||
#define SMC935_ID 0x20
|
||||
#define SMC935_PORTHI 0x60
|
||||
#define SMC935_PORTLO 0x61
|
||||
#define SMC935_PPMODE 0xf0
|
||||
|
||||
/* Parallel port modes */
|
||||
#define SMC935_SPP 0x38 + 0
|
||||
#define SMC935_EPP19SPP 0x38 + 1
|
||||
#define SMC935_ECP 0x38 + 2
|
||||
#define SMC935_ECPEPP19 0x38 + 3
|
||||
#define SMC935_CENT 0x38 + 4
|
||||
#define SMC935_EPP17SPP 0x38 + 5
|
||||
#define SMC935_UNUSED 0x38 + 6
|
||||
#define SMC935_ECPEPP17 0x38 + 7
|
||||
|
||||
/*
|
||||
* Register defines for the Winbond W83877F parts
|
||||
*/
|
||||
|
||||
#define WINB_W83877F_ID 0xa
|
||||
#define WINB_W83877AF_ID 0xb
|
||||
|
||||
/* Configuration bits */
|
||||
#define WINB_HEFERE (1<<5) /* CROC bit 5 */
|
||||
#define WINB_HEFRAS (1<<0) /* CR16 bit 0 */
|
||||
|
||||
#define WINB_PNPCVS (1<<2) /* CR16 bit 2 */
|
||||
#define WINB_CHIPID 0xf /* CR9 bits 0-3 */
|
||||
|
||||
#define WINB_PRTMODS0 (1<<2) /* CR0 bit 2 */
|
||||
#define WINB_PRTMODS1 (1<<3) /* CR0 bit 3 */
|
||||
#define WINB_PRTMODS2 (1<<7) /* CR9 bit 7 */
|
||||
|
||||
/* W83877F modes: CR9/bit7 | CR0/bit3 | CR0/bit2 */
|
||||
#define WINB_W83757 0x0
|
||||
#define WINB_EXTFDC 0x4
|
||||
#define WINB_EXTADP 0x8
|
||||
#define WINB_EXT2FDD 0xc
|
||||
#define WINB_JOYSTICK 0x80
|
||||
|
||||
#define WINB_PARALLEL 0x80
|
||||
#define WINB_EPP_SPP 0x4
|
||||
#define WINB_ECP 0x8
|
||||
#define WINB_ECP_EPP 0xc
|
||||
|
||||
#endif
|
@ -1,56 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 FreeBSD(98) Porting Team.
|
||||
* 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _PC98_PC98_SC_MACHDEP_H_
|
||||
#define _PC98_PC98_SC_MACHDEP_H_
|
||||
|
||||
#undef SC_DFLT_FONT
|
||||
#undef SC_MOUSE_CHAR
|
||||
#undef SC_PIXEL_MODE
|
||||
#undef SC_NO_FONT_LOADING
|
||||
#define SC_NO_FONT_LOADING 1
|
||||
#undef SC_NO_PALETTE_LOADING
|
||||
#define SC_NO_PALETTE_LOADING 1
|
||||
|
||||
#ifndef SC_KERNEL_CONS_ATTR
|
||||
#define SC_KERNEL_CONS_ATTR (FG_LIGHTGREY | BG_BLACK)
|
||||
#endif
|
||||
|
||||
#define KANJI 1
|
||||
|
||||
#define BELL_DURATION 5
|
||||
#define BELL_PITCH_8M 1339
|
||||
#define BELL_PITCH_5M 1678
|
||||
|
||||
#define UJIS 0
|
||||
#define SJIS 1
|
||||
|
||||
#define PRINTABLE(c) ((c) > 0x1b || ((c) > 0x0f && (c) < 0x1b) \
|
||||
|| (c) < 0x07)
|
||||
|
||||
#endif /* !_PC98_PC98_SC_MACHDEP_H_ */
|
@ -1,208 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 FreeBSD(98) Porting Team.
|
||||
* 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_syscons.h"
|
||||
#include "opt_gdc.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/fbio.h>
|
||||
#include <sys/consio.h>
|
||||
|
||||
#include <dev/fb/fbreg.h>
|
||||
#include <dev/syscons/syscons.h>
|
||||
|
||||
#ifndef SC_RENDER_DEBUG
|
||||
#define SC_RENDER_DEBUG 0
|
||||
#endif
|
||||
|
||||
static vr_clear_t gdc_txtclear;
|
||||
static vr_draw_border_t gdc_txtborder;
|
||||
static vr_draw_t gdc_txtdraw;
|
||||
static vr_set_cursor_t gdc_txtcursor_shape;
|
||||
static vr_draw_cursor_t gdc_txtcursor;
|
||||
#ifndef SC_NO_CUTPASTE
|
||||
static vr_draw_mouse_t gdc_txtmouse;
|
||||
#else
|
||||
#define gdc_txtmouse (vr_draw_mouse_t *)gdc_nop
|
||||
#endif
|
||||
|
||||
#ifndef SC_NO_MODE_CHANGE
|
||||
static vr_draw_border_t gdc_grborder;
|
||||
#endif
|
||||
|
||||
static void gdc_nop(scr_stat *scp, ...);
|
||||
|
||||
static sc_rndr_sw_t txtrndrsw = {
|
||||
gdc_txtclear,
|
||||
gdc_txtborder,
|
||||
gdc_txtdraw,
|
||||
gdc_txtcursor_shape,
|
||||
gdc_txtcursor,
|
||||
(vr_blink_cursor_t *)gdc_nop,
|
||||
(vr_set_mouse_t *)gdc_nop,
|
||||
gdc_txtmouse,
|
||||
};
|
||||
RENDERER(gdc, 0, txtrndrsw, gdc_set);
|
||||
|
||||
#ifndef SC_NO_MODE_CHANGE
|
||||
static sc_rndr_sw_t grrndrsw = {
|
||||
(vr_clear_t *)gdc_nop,
|
||||
gdc_grborder,
|
||||
(vr_draw_t *)gdc_nop,
|
||||
(vr_set_cursor_t *)gdc_nop,
|
||||
(vr_draw_cursor_t *)gdc_nop,
|
||||
(vr_blink_cursor_t *)gdc_nop,
|
||||
(vr_set_mouse_t *)gdc_nop,
|
||||
(vr_draw_mouse_t *)gdc_nop,
|
||||
};
|
||||
RENDERER(gdc, GRAPHICS_MODE, grrndrsw, gdc_set);
|
||||
#endif /* SC_NO_MODE_CHANGE */
|
||||
|
||||
RENDERER_MODULE(gdc, gdc_set);
|
||||
|
||||
static void
|
||||
gdc_nop(scr_stat *scp, ...)
|
||||
{
|
||||
}
|
||||
|
||||
/* text mode renderer */
|
||||
|
||||
static void
|
||||
gdc_txtclear(scr_stat *scp, int c, int attr)
|
||||
{
|
||||
sc_vtb_clear(&scp->scr, c, attr);
|
||||
}
|
||||
|
||||
static void
|
||||
gdc_txtborder(scr_stat *scp, int color)
|
||||
{
|
||||
(*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
|
||||
}
|
||||
|
||||
static void
|
||||
gdc_txtdraw(scr_stat *scp, int from, int count, int flip)
|
||||
{
|
||||
vm_offset_t p;
|
||||
int c;
|
||||
int a;
|
||||
|
||||
if (from + count > scp->xsize*scp->ysize)
|
||||
count = scp->xsize*scp->ysize - from;
|
||||
|
||||
if (flip) {
|
||||
for (p = sc_vtb_pointer(&scp->scr, from); count-- > 0; ++from) {
|
||||
c = sc_vtb_getc(&scp->vtb, from);
|
||||
a = sc_vtb_geta(&scp->vtb, from);
|
||||
#if 0
|
||||
a ^= 0x0800;
|
||||
#else
|
||||
a = (a & 0x8800) | ((a & 0x7000) >> 4)
|
||||
| ((a & 0x0700) << 4);
|
||||
#endif
|
||||
p = sc_vtb_putchar(&scp->scr, p, c, a);
|
||||
}
|
||||
} else {
|
||||
sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdc_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
|
||||
{
|
||||
if (base < 0 || base >= scp->font_size)
|
||||
return;
|
||||
/* the caller may set height <= 0 in order to disable the cursor */
|
||||
(*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
|
||||
base, height,
|
||||
scp->font_size, blink);
|
||||
}
|
||||
|
||||
static void
|
||||
gdc_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
|
||||
{
|
||||
if (on) {
|
||||
scp->status |= VR_CURSOR_ON;
|
||||
(*vidsw[scp->sc->adapter]->set_hw_cursor)(scp->sc->adp,
|
||||
at%scp->xsize, at/scp->xsize);
|
||||
} else {
|
||||
if (scp->status & VR_CURSOR_ON)
|
||||
(*vidsw[scp->sc->adapter]->set_hw_cursor)(scp->sc->adp,
|
||||
-1, -1);
|
||||
scp->status &= ~VR_CURSOR_ON;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SC_NO_CUTPASTE
|
||||
|
||||
static void
|
||||
draw_txtmouse(scr_stat *scp, int x, int y)
|
||||
{
|
||||
int at;
|
||||
int a;
|
||||
|
||||
at = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
|
||||
a = sc_vtb_geta(&scp->vtb, at);
|
||||
#if 0
|
||||
a ^= 0x0800;
|
||||
#else
|
||||
a = (a & 0x8800) | ((a & 0x7000) >> 4)
|
||||
| ((a & 0x0700) << 4);
|
||||
#endif
|
||||
sc_vtb_putc(&scp->scr, at, sc_vtb_getc(&scp->scr, at), a);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_txtmouse(scr_stat *scp, int x, int y)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdc_txtmouse(scr_stat *scp, int x, int y, int on)
|
||||
{
|
||||
if (on)
|
||||
draw_txtmouse(scp, x, y);
|
||||
else
|
||||
remove_txtmouse(scp, x, y);
|
||||
}
|
||||
|
||||
#endif /* SC_NO_CUTPASTE */
|
||||
|
||||
#ifndef SC_NO_MODE_CHANGE
|
||||
|
||||
/* graphics mode renderer */
|
||||
|
||||
static void
|
||||
gdc_grborder(scr_stat *scp, int color)
|
||||
{
|
||||
(*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
|
||||
}
|
||||
|
||||
#endif /* SC_NO_MODE_CHANGE */
|
File diff suppressed because it is too large
Load Diff
@ -1,399 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 FreeBSD(98) Porting Team.
|
||||
* 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_syscons.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/consio.h>
|
||||
#include <sys/fbio.h>
|
||||
|
||||
#include <machine/md_var.h>
|
||||
|
||||
#include <dev/fb/fbreg.h>
|
||||
#include <dev/syscons/syscons.h>
|
||||
|
||||
#define ATTR_OFFSET_FB 0x2000
|
||||
#define attr_offset(vtb) ((vtb)->vtb_size*sizeof(u_int16_t))
|
||||
|
||||
#define vtb_pointer(vtb, at) \
|
||||
((vtb)->vtb_buffer + sizeof(u_int16_t)*(at))
|
||||
|
||||
#define vtb_wrap(vtb, at, offset) \
|
||||
(((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size)
|
||||
|
||||
static u_int8_t ibmpc_to_pc98[256] = {
|
||||
0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1,
|
||||
0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9,
|
||||
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
|
||||
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
|
||||
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
|
||||
0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
|
||||
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
|
||||
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
|
||||
|
||||
0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3,
|
||||
0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb,
|
||||
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
|
||||
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
|
||||
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
|
||||
0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
|
||||
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
|
||||
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
|
||||
};
|
||||
#define at2pc98(attr) ((attr) | ibmpc_to_pc98[(unsigned)(attr) >> 8])
|
||||
|
||||
void
|
||||
sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait)
|
||||
{
|
||||
vtb->vtb_flags = 0;
|
||||
vtb->vtb_type = type;
|
||||
vtb->vtb_cols = cols;
|
||||
vtb->vtb_rows = rows;
|
||||
vtb->vtb_size = cols*rows;
|
||||
vtb->vtb_buffer = 0;
|
||||
vtb->vtb_tail = 0;
|
||||
|
||||
switch (type) {
|
||||
case VTB_MEMORY:
|
||||
case VTB_RINGBUFFER:
|
||||
if ((buf == NULL) && (cols*rows != 0)) {
|
||||
vtb->vtb_buffer =
|
||||
(vm_offset_t)malloc(cols*rows*sizeof(u_int16_t)*2,
|
||||
M_DEVBUF,
|
||||
((wait) ? M_WAITOK : M_NOWAIT) | M_ZERO);
|
||||
if (vtb->vtb_buffer != 0) {
|
||||
vtb->vtb_flags |= VTB_ALLOCED;
|
||||
}
|
||||
} else {
|
||||
vtb->vtb_buffer = (vm_offset_t)buf;
|
||||
}
|
||||
vtb->vtb_flags |= VTB_VALID;
|
||||
break;
|
||||
case VTB_FRAMEBUFFER:
|
||||
vtb->vtb_buffer = (vm_offset_t)buf;
|
||||
vtb->vtb_flags |= VTB_VALID;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_destroy(sc_vtb_t *vtb)
|
||||
{
|
||||
vm_offset_t p;
|
||||
|
||||
vtb->vtb_cols = 0;
|
||||
vtb->vtb_rows = 0;
|
||||
vtb->vtb_size = 0;
|
||||
vtb->vtb_tail = 0;
|
||||
|
||||
p = vtb->vtb_buffer;
|
||||
vtb->vtb_buffer = 0;
|
||||
switch (vtb->vtb_type) {
|
||||
case VTB_MEMORY:
|
||||
case VTB_RINGBUFFER:
|
||||
if ((vtb->vtb_flags & VTB_ALLOCED) && (p != 0))
|
||||
free((void *)p, M_DEVBUF);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
vtb->vtb_flags = 0;
|
||||
vtb->vtb_type = VTB_INVALID;
|
||||
}
|
||||
|
||||
size_t
|
||||
sc_vtb_size(int cols, int rows)
|
||||
{
|
||||
return (size_t)(cols*rows*sizeof(u_int16_t)*2);
|
||||
}
|
||||
|
||||
int
|
||||
sc_vtb_getc(sc_vtb_t *vtb, int at)
|
||||
{
|
||||
vm_offset_t p = vtb_pointer(vtb, at);
|
||||
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER)
|
||||
return (readw(p) & 0x00ff);
|
||||
else
|
||||
return (*(u_int16_t *)p & 0x00ff);
|
||||
}
|
||||
|
||||
int
|
||||
sc_vtb_geta(sc_vtb_t *vtb, int at)
|
||||
{
|
||||
vm_offset_t p = vtb_pointer(vtb, at);
|
||||
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER)
|
||||
return (readw(p + ATTR_OFFSET_FB) & 0xff00);
|
||||
else
|
||||
return (*(u_int16_t *)(p + attr_offset(vtb)) & 0xff00);
|
||||
}
|
||||
|
||||
__inline static void
|
||||
vtb_putc(sc_vtb_t *vtb, vm_offset_t p, int c, int a)
|
||||
{
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
writew(p, c);
|
||||
writew(p + ATTR_OFFSET_FB, at2pc98(a));
|
||||
} else {
|
||||
*(u_int16_t *)p = c;
|
||||
*(u_int16_t *)(p + attr_offset(vtb)) = at2pc98(a);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
|
||||
{
|
||||
vtb_putc(vtb, vtb_pointer(vtb, at), c, a);
|
||||
}
|
||||
|
||||
vm_offset_t
|
||||
sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a)
|
||||
{
|
||||
vtb_putc(vtb, p, c, a);
|
||||
return (p + sizeof(u_int16_t));
|
||||
}
|
||||
|
||||
vm_offset_t
|
||||
sc_vtb_pointer(sc_vtb_t *vtb, int at)
|
||||
{
|
||||
return (vtb_pointer(vtb, at));
|
||||
}
|
||||
|
||||
int
|
||||
sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset)
|
||||
{
|
||||
return ((pos + offset + vtb->vtb_size)%vtb->vtb_size);
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_clear(sc_vtb_t *vtb, int c, int attr)
|
||||
{
|
||||
vm_offset_t p = vtb_pointer(vtb, 0);
|
||||
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
fillw_io(c, p, vtb->vtb_size);
|
||||
fillw_io(at2pc98(attr), p + ATTR_OFFSET_FB, vtb->vtb_size);
|
||||
} else {
|
||||
fillw(c, (void *)p, vtb->vtb_size);
|
||||
fillw(at2pc98(attr), (void *)(p + attr_offset(vtb)),
|
||||
vtb->vtb_size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count)
|
||||
{
|
||||
vm_offset_t p1, p2;
|
||||
|
||||
p1 = vtb_pointer(vtb1, from);
|
||||
p2 = vtb_pointer(vtb2, to);
|
||||
if (vtb2->vtb_type == VTB_FRAMEBUFFER) {
|
||||
bcopy_toio(p1, p2, count*sizeof(u_int16_t));
|
||||
bcopy_toio(p1 + attr_offset(vtb1),
|
||||
p2 + ATTR_OFFSET_FB,
|
||||
count*sizeof(u_int16_t));
|
||||
} else if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
|
||||
bcopy_fromio(p1, p2, count*sizeof(u_int16_t));
|
||||
bcopy_fromio(p1 + ATTR_OFFSET_FB,
|
||||
p2 + attr_offset(vtb2),
|
||||
count*sizeof(u_int16_t));
|
||||
} else {
|
||||
bcopy((void *)p1, (void *)p2, count*sizeof(u_int16_t));
|
||||
bcopy((void *)(p1 + attr_offset(vtb1)),
|
||||
(void *)(p2 + attr_offset(vtb2)),
|
||||
count*sizeof(u_int16_t));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count)
|
||||
{
|
||||
int len;
|
||||
vm_offset_t p1, p2;
|
||||
|
||||
if (vtb2->vtb_type != VTB_RINGBUFFER)
|
||||
return;
|
||||
|
||||
while (count > 0) {
|
||||
p1 = vtb_pointer(vtb1, from);
|
||||
p2 = vtb_pointer(vtb2, vtb2->vtb_tail);
|
||||
len = imin(count, vtb2->vtb_size - vtb2->vtb_tail);
|
||||
if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
|
||||
bcopy_fromio(p1, p2, len*sizeof(u_int16_t));
|
||||
bcopy_fromio(p1 + ATTR_OFFSET_FB,
|
||||
p2 + attr_offset(vtb2),
|
||||
len*sizeof(u_int16_t));
|
||||
} else {
|
||||
bcopy((void *)p1, (void *)p2, len*sizeof(u_int16_t));
|
||||
bcopy((void *)(p1 + attr_offset(vtb1)),
|
||||
(void *)(p2 + attr_offset(vtb2)),
|
||||
len*sizeof(u_int16_t));
|
||||
}
|
||||
from += len;
|
||||
count -= len;
|
||||
vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_seek(sc_vtb_t *vtb, int pos)
|
||||
{
|
||||
vtb->vtb_tail = pos%vtb->vtb_size;
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr)
|
||||
{
|
||||
vm_offset_t p;
|
||||
|
||||
if (at + count > vtb->vtb_size)
|
||||
count = vtb->vtb_size - at;
|
||||
p = vtb_pointer(vtb, at);
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
fillw_io(c, p, count);
|
||||
fillw_io(at2pc98(attr), p + ATTR_OFFSET_FB, count);
|
||||
} else {
|
||||
fillw(c, (void *)p, count);
|
||||
fillw(at2pc98(attr), (void *)(p + attr_offset(vtb)), count);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_move(sc_vtb_t *vtb, int from, int to, int count)
|
||||
{
|
||||
vm_offset_t p1, p2;
|
||||
|
||||
if (from + count > vtb->vtb_size)
|
||||
count = vtb->vtb_size - from;
|
||||
if (to + count > vtb->vtb_size)
|
||||
count = vtb->vtb_size - to;
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
p1 = vtb_pointer(vtb, from);
|
||||
p2 = vtb_pointer(vtb, to);
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
bcopy_io(p1, p2, count*sizeof(u_int16_t));
|
||||
bcopy_io(p1 + ATTR_OFFSET_FB,
|
||||
p2 + ATTR_OFFSET_FB, count*sizeof(u_int16_t));
|
||||
} else {
|
||||
bcopy((void *)p1, (void *)p2, count*sizeof(u_int16_t));
|
||||
bcopy((void *)(p1 + attr_offset(vtb)),
|
||||
(void *)(p2 + attr_offset(vtb)), count*sizeof(u_int16_t));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr)
|
||||
{
|
||||
int len;
|
||||
vm_offset_t p1, p2;
|
||||
|
||||
if (at + count > vtb->vtb_size)
|
||||
count = vtb->vtb_size - at;
|
||||
len = vtb->vtb_size - at - count;
|
||||
if (len > 0) {
|
||||
p1 = vtb_pointer(vtb, at + count);
|
||||
p2 = vtb_pointer(vtb, at);
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
bcopy_io(p1, p2, len*sizeof(u_int16_t));
|
||||
bcopy_io(p1 + ATTR_OFFSET_FB,
|
||||
p2 + ATTR_OFFSET_FB,
|
||||
len*sizeof(u_int16_t));
|
||||
} else {
|
||||
bcopy((void *)p1, (void *)p2, len*sizeof(u_int16_t));
|
||||
bcopy((void *)(p1 + attr_offset(vtb)),
|
||||
(void *)(p2 + attr_offset(vtb)),
|
||||
len*sizeof(u_int16_t));
|
||||
}
|
||||
}
|
||||
p1 = vtb_pointer(vtb, at + len);
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
fillw_io(c, p1, vtb->vtb_size - at - len);
|
||||
fillw_io(at2pc98(attr), p1 + ATTR_OFFSET_FB,
|
||||
vtb->vtb_size - at - len);
|
||||
} else {
|
||||
fillw(c, (void *)p1, vtb->vtb_size - at - len);
|
||||
fillw(at2pc98(attr), (void *)(p1 + attr_offset(vtb)),
|
||||
vtb->vtb_size - at - len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr)
|
||||
{
|
||||
vm_offset_t p1, p2;
|
||||
|
||||
p1 = vtb_pointer(vtb, at);
|
||||
if (at + count > vtb->vtb_size) {
|
||||
count = vtb->vtb_size - at;
|
||||
} else {
|
||||
p2 = vtb_pointer(vtb, at + count);
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
bcopy_io(p1, p2,
|
||||
(vtb->vtb_size - at - count)*sizeof(u_int16_t));
|
||||
bcopy_io(p1 + ATTR_OFFSET_FB,
|
||||
p2 + ATTR_OFFSET_FB,
|
||||
(vtb->vtb_size - at - count)*sizeof(u_int16_t));
|
||||
} else {
|
||||
bcopy((void *)p1, (void *)p2,
|
||||
(vtb->vtb_size - at - count)*sizeof(u_int16_t));
|
||||
bcopy((void *)(p1 + attr_offset(vtb)),
|
||||
(void *)(p2 + attr_offset(vtb)),
|
||||
(vtb->vtb_size - at - count)*sizeof(u_int16_t));
|
||||
}
|
||||
}
|
||||
if (vtb->vtb_type == VTB_FRAMEBUFFER) {
|
||||
fillw_io(c, p1, count);
|
||||
fillw_io(at2pc98(attr), p1 + ATTR_OFFSET_FB, count);
|
||||
} else {
|
||||
fillw(c, (void *)p1, count);
|
||||
fillw(at2pc98(attr), (void *)(p1 + attr_offset(vtb)), count);
|
||||
}
|
||||
}
|
4413
sys/pc98/pc98/sio.c
4413
sys/pc98/pc98/sio.c
File diff suppressed because it is too large
Load Diff
@ -1,118 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Yoshihiro TAKAHASHI. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/tty.h>
|
||||
#include <machine/bus.h>
|
||||
#include <sys/timepps.h>
|
||||
|
||||
#include <dev/sio/siovar.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
|
||||
static int sio_isa_attach(device_t dev);
|
||||
static int sio_isa_probe(device_t dev);
|
||||
|
||||
static device_method_t sio_isa_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, sio_isa_probe),
|
||||
DEVMETHOD(device_attach, sio_isa_attach),
|
||||
DEVMETHOD(device_detach, siodetach),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t sio_isa_driver = {
|
||||
sio_driver_name,
|
||||
sio_isa_methods,
|
||||
0,
|
||||
};
|
||||
|
||||
static struct isa_pnp_id sio_ids[] = {
|
||||
{0x0100e4a5, "RSA-98III"},
|
||||
{0x4180a3b8, NULL}, /* NEC8041 - PC-9821CB-B04 */
|
||||
{0x0181a3b8, NULL}, /* NEC8101 - PC-9821CB2-B04 */
|
||||
{0x5181a3b8, NULL}, /* NEC8151 - Internal FAX/Modem for Cx3, Cb3 */
|
||||
{0x9181a3b8, NULL}, /* NEC8191 - NEC PC-9801-120 */
|
||||
{0xe181a3b8, NULL}, /* NEC81E1 - Internal FAX/Modem */
|
||||
{0x1182a3b8, NULL}, /* NEC8211 - PC-9801-123 */
|
||||
{0x3182a3b8, NULL}, /* NEC8231 - Internal FAX/Modem(Voice) */
|
||||
{0x4182a3b8, NULL}, /* NEC8241 - NEC PC-9821NR-B05 */
|
||||
{0x5182a3b8, NULL}, /* NEC8251 - Internel FAX/Modem */
|
||||
{0x7182a3b8, NULL}, /* NEC8271 - NEC PC-9801-125 */
|
||||
{0x11802fbf, NULL}, /* OYO8011 - Internal FAX/Modem for ValueStar(Ring) */
|
||||
{0}
|
||||
};
|
||||
|
||||
static int
|
||||
sio_isa_probe(dev)
|
||||
device_t dev;
|
||||
{
|
||||
int logical_id;
|
||||
|
||||
/* Check isapnp ids */
|
||||
if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO)
|
||||
return (ENXIO);
|
||||
|
||||
logical_id = isa_get_logicalid(dev);
|
||||
switch (logical_id) {
|
||||
case 0x0100e4a5: /* RSA-98III */
|
||||
SET_FLAG(dev, SET_IFTYPE(COM_IF_RSA98III));
|
||||
break;
|
||||
case 0x4180a3b8: /* PC-9821CB-B04 */
|
||||
case 0x0181a3b8: /* PC-9821CB2-B04 */
|
||||
case 0x5181a3b8: /* for Cx3, Cb3 internal */
|
||||
case 0x9181a3b8: /* PC-9801-120 */
|
||||
case 0xe181a3b8: /* Internal FAX/Modem */
|
||||
case 0x1182a3b8: /* PC-9801-123 */
|
||||
case 0x3182a3b8: /* FAX/Voice/Modem internal */
|
||||
case 0x4182a3b8: /* PC-9821NR-B05 */
|
||||
case 0x5182a3b8: /* FAX/Modem internal */
|
||||
case 0x7182a3b8: /* PC-9801-125 */
|
||||
case 0x11802fbf: /* for ValueStar internal */
|
||||
SET_FLAG(dev, SET_IFTYPE(COM_IF_NS16550));
|
||||
break;
|
||||
}
|
||||
|
||||
return (sioprobe(dev, 0, 0UL, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
sio_isa_attach(dev)
|
||||
device_t dev;
|
||||
{
|
||||
return (sioattach(dev, 0, 0UL));
|
||||
}
|
||||
|
||||
DRIVER_MODULE(sio, isa, sio_isa_driver, sio_devclass, 0, 0);
|
@ -1,265 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 FreeBSD(98) Porting Team.
|
||||
* 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_syscons.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/consio.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/pc98/pc98_machdep.h>
|
||||
|
||||
#include <dev/syscons/syscons.h>
|
||||
|
||||
#include <i386/isa/timerreg.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
|
||||
static devclass_t sc_devclass;
|
||||
|
||||
static sc_softc_t main_softc;
|
||||
#ifdef SC_NO_SUSPEND_VTYSWITCH
|
||||
static int sc_no_suspend_vtswitch = 1;
|
||||
#else
|
||||
static int sc_no_suspend_vtswitch = 0;
|
||||
#endif
|
||||
static int sc_cur_scr;
|
||||
|
||||
TUNABLE_INT("hw.syscons.sc_no_suspend_vtswitch", (int *)&sc_no_suspend_vtswitch);
|
||||
SYSCTL_DECL(_hw_syscons);
|
||||
SYSCTL_INT(_hw_syscons, OID_AUTO, sc_no_suspend_vtswitch, CTLFLAG_RW,
|
||||
&sc_no_suspend_vtswitch, 0, "Disable VT switch before suspend.");
|
||||
|
||||
static void
|
||||
scidentify (driver_t *driver, device_t parent)
|
||||
{
|
||||
BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "sc", 0);
|
||||
}
|
||||
|
||||
static int
|
||||
scprobe(device_t dev)
|
||||
{
|
||||
/* No pnp support */
|
||||
if (isa_get_vendorid(dev))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "System console");
|
||||
return sc_probe_unit(device_get_unit(dev), device_get_flags(dev));
|
||||
}
|
||||
|
||||
static int
|
||||
scattach(device_t dev)
|
||||
{
|
||||
return sc_attach_unit(device_get_unit(dev), device_get_flags(dev));
|
||||
}
|
||||
|
||||
static int
|
||||
scsuspend(device_t dev)
|
||||
{
|
||||
int retry = 10;
|
||||
static int dummy;
|
||||
sc_softc_t *sc;
|
||||
|
||||
sc = &main_softc;
|
||||
|
||||
if (sc->cur_scp == NULL)
|
||||
return (0);
|
||||
|
||||
sc_cur_scr = sc->cur_scp->index;
|
||||
|
||||
if (sc_no_suspend_vtswitch)
|
||||
return (0);
|
||||
|
||||
do {
|
||||
sc_switch_scr(sc, 0);
|
||||
if (!sc->switch_in_progress) {
|
||||
break;
|
||||
}
|
||||
tsleep(&dummy, 0, "scsuspend", 100);
|
||||
} while (retry--);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
scresume(device_t dev)
|
||||
{
|
||||
sc_softc_t *sc;
|
||||
|
||||
if (sc_no_suspend_vtswitch)
|
||||
return (0);
|
||||
|
||||
sc = &main_softc;
|
||||
sc_switch_scr(sc, sc_cur_scr);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sc_max_unit(void)
|
||||
{
|
||||
return devclass_get_maxunit(sc_devclass);
|
||||
}
|
||||
|
||||
sc_softc_t
|
||||
*sc_get_softc(int unit, int flags)
|
||||
{
|
||||
sc_softc_t *sc;
|
||||
|
||||
if (unit < 0)
|
||||
return NULL;
|
||||
if (flags & SC_KERNEL_CONSOLE) {
|
||||
/* FIXME: clear if it is wired to another unit! */
|
||||
sc = &main_softc;
|
||||
} else {
|
||||
sc = (sc_softc_t *)device_get_softc(devclass_get_device(sc_devclass, unit));
|
||||
if (sc == NULL)
|
||||
return NULL;
|
||||
}
|
||||
sc->unit = unit;
|
||||
if (!(sc->flags & SC_INIT_DONE)) {
|
||||
sc->keyboard = -1;
|
||||
sc->adapter = -1;
|
||||
sc->mouse_char = SC_MOUSE_CHAR;
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
|
||||
sc_softc_t
|
||||
*sc_find_softc(struct video_adapter *adp, struct keyboard *kbd)
|
||||
{
|
||||
sc_softc_t *sc;
|
||||
int units;
|
||||
int i;
|
||||
|
||||
sc = &main_softc;
|
||||
if (((adp == NULL) || (adp == sc->adp))
|
||||
&& ((kbd == NULL) || (kbd == sc->kbd)))
|
||||
return sc;
|
||||
units = devclass_get_maxunit(sc_devclass);
|
||||
for (i = 0; i < units; ++i) {
|
||||
sc = (sc_softc_t *)device_get_softc(devclass_get_device(sc_devclass, i));
|
||||
if (sc == NULL)
|
||||
continue;
|
||||
if (((adp == NULL) || (adp == sc->adp))
|
||||
&& ((kbd == NULL) || (kbd == sc->kbd)))
|
||||
return sc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
sc_get_cons_priority(int *unit, int *flags)
|
||||
{
|
||||
const char *at;
|
||||
int u, f;
|
||||
|
||||
*unit = -1;
|
||||
for (u = 0; u < 16; u++) {
|
||||
if (resource_disabled(SC_DRIVER_NAME, u))
|
||||
continue;
|
||||
if (resource_string_value(SC_DRIVER_NAME, u, "at", &at) != 0)
|
||||
continue;
|
||||
if (resource_int_value(SC_DRIVER_NAME, u, "flags", &f) != 0)
|
||||
f = 0;
|
||||
if (f & SC_KERNEL_CONSOLE) {
|
||||
/* the user designates this unit to be the console */
|
||||
*unit = u;
|
||||
*flags = f;
|
||||
break;
|
||||
}
|
||||
if (*unit < 0) {
|
||||
/* ...otherwise remember the first found unit */
|
||||
*unit = u;
|
||||
*flags = f;
|
||||
}
|
||||
}
|
||||
if (*unit < 0)
|
||||
return CN_DEAD;
|
||||
return CN_INTERNAL;
|
||||
}
|
||||
|
||||
void
|
||||
sc_get_bios_values(bios_values_t *values)
|
||||
{
|
||||
values->cursor_start = 15;
|
||||
values->cursor_end = 16;
|
||||
values->shift_state = 0;
|
||||
if (pc98_machine_type & M_8M)
|
||||
values->bell_pitch = BELL_PITCH_8M;
|
||||
else
|
||||
values->bell_pitch = BELL_PITCH_5M;
|
||||
}
|
||||
|
||||
int
|
||||
sc_tone(int herz)
|
||||
{
|
||||
int pitch;
|
||||
|
||||
if (herz) {
|
||||
/* enable counter 1 */
|
||||
outb(0x35, inb(0x35) & 0xf7);
|
||||
/* set command for counter 1, 2 byte write */
|
||||
if (acquire_timer1(TIMER_16BIT | TIMER_SQWAVE))
|
||||
return EBUSY;
|
||||
/* set pitch */
|
||||
pitch = timer_freq/herz;
|
||||
outb(TIMER_CNTR1, pitch);
|
||||
outb(TIMER_CNTR1, pitch >> 8);
|
||||
} else {
|
||||
/* disable counter 1 */
|
||||
outb(0x35, inb(0x35) | 0x08);
|
||||
release_timer1();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static device_method_t sc_methods[] = {
|
||||
DEVMETHOD(device_identify, scidentify),
|
||||
DEVMETHOD(device_probe, scprobe),
|
||||
DEVMETHOD(device_attach, scattach),
|
||||
DEVMETHOD(device_suspend, scsuspend),
|
||||
DEVMETHOD(device_resume, scresume),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t sc_driver = {
|
||||
SC_DRIVER_NAME,
|
||||
sc_methods,
|
||||
sizeof(sc_softc_t),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(sc, isa, sc_driver, sc_devclass, 0, 0);
|
@ -64,7 +64,7 @@
|
||||
|
||||
/* XXX Shouldn't reach into the MD code here */
|
||||
#ifdef PC98
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <pc98/cbus/cbus.h>
|
||||
#else
|
||||
#include <i386/isa/isa.h>
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user