mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 09:10:28 +00:00
- Hook up the new locations of the atkbdc(4), atkbd(4) and psm(4) source
files after they were repo-copied to sys/dev/atkbdc. The sources of atkbdc(4) and its children were moved to the new location in preparation for adding an EBus front-end to atkbdc(4) for use on sparc64; i.e. in order to not further scatter them over the whole tree which would have been the result of adding atkbdc_ebus.c in e.g. sys/sparc64/ebus. Another reason for the repo-copies was that some of the sources were misfiled, e.g. sys/isa/atkbd_isa.c wasn't ISA-specific at all but for hanging atkbd(4) off of atkbdc(4) and was renamed to atkbd_atkbdc.c accordingly. Most of sys/isa/psm.c, i.e. expect for its PSMC PNP part, also isn't ISA-specific. - Separate the parts of atkbdc_isa.c which aren't actually ISA-specific but are shareable between different atkbdc(4) bus front-ends into atkbdc_subr.c (repo-copied from atkbdc_isa.c). While here use bus_generic_rl_alloc_resource() and bus_generic_rl_release_resource() respectively in atkbdc_isa.c instead of rolling own versions. - Add sparc64 MD bits to atkbdc(4) and atkbd(4) and an EBus front-end for atkbdc(4). PS/2 controllers and input devices are used on a couple of Sun OEM boards and occur on either the EBus or the ISA bus. Depending on the board it's either the only on-board mean to connect a keyboard and mouse or an alternative to either RS232 or USB devices. - Wrap the PSMC PNP part of psm.c in #ifdef DEV_ISA so it can be compiled without isa(4) (e.g. for EBus-only machines). This ISA-specific part isn't separated into its own source file, yet, as it requires more work than was feasible for 6.0 in order to do it in a clean way. Actually philip@ is working on a rewrite of psm(4) so a more comprehensive clean-up and separation of hardware dependent and independent parts is expected to happen after 6.0. Tested on: i386, sparc64 (AX1105, AXe and AXi boards) Reviewed by: philip
This commit is contained in:
parent
a8e0b2e8ab
commit
520b635320
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147271
|
@ -166,6 +166,12 @@ crypto/blowfish/bf_enc.c optional crypto
|
|||
crypto/des/des_enc.c optional crypto
|
||||
dev/advansys/adv_isa.c optional adv isa
|
||||
dev/aic/aic_isa.c optional aic isa
|
||||
dev/atkbdc/atkbd.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbd_atkbdc.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbdc.c optional atkbdc
|
||||
dev/atkbdc/atkbdc_isa.c optional atkbdc isa
|
||||
dev/atkbdc/atkbdc_subr.c optional atkbdc
|
||||
dev/atkbdc/psm.c optional psm atkbdc
|
||||
dev/dec/mcclock.c optional mcclock
|
||||
dev/dec/mcclock_if.m optional mcclock
|
||||
dev/ed/if_ed_3c503.c optional ed isa ed_3c503
|
||||
|
@ -180,8 +186,6 @@ dev/fb/vga.c optional vga
|
|||
dev/fdc/fdc.c optional fdc
|
||||
dev/fdc/fdc_isa.c optional fdc isa
|
||||
dev/hwpmc/hwpmc_alpha.c optional hwpmc
|
||||
dev/kbd/atkbd.c optional atkbd
|
||||
dev/kbd/atkbdc.c optional atkbdc
|
||||
dev/kbd/kbd.c optional atkbd
|
||||
dev/kbd/kbd.c optional sc
|
||||
dev/kbd/kbd.c optional ukbd
|
||||
|
@ -202,9 +206,6 @@ dev/syscons/sysmouse.c optional sc
|
|||
dev/uart/uart_cpu_alpha.c optional uart
|
||||
geom/geom_bsd.c standard
|
||||
geom/geom_bsd_enc.c standard
|
||||
isa/atkbd_isa.c optional atkbd
|
||||
isa/atkbdc_isa.c optional atkbdc
|
||||
isa/psm.c optional psm
|
||||
isa/syscons_isa.c optional sc
|
||||
isa/vga_isa.c optional vga
|
||||
libkern/alpha/bswap16.S standard
|
||||
|
|
|
@ -132,6 +132,12 @@ crypto/des/des_enc.c optional netsmbcrypto
|
|||
crypto/des/des_setkey.c optional netsmbcrypto
|
||||
dev/acpica/acpi_if.m standard
|
||||
dev/arcmsr/arcmsr.c optional arcmsr pci
|
||||
dev/atkbdc/atkbd.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbd_atkbdc.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbdc.c optional atkbdc
|
||||
dev/atkbdc/atkbdc_isa.c optional atkbdc isa
|
||||
dev/atkbdc/atkbdc_subr.c optional atkbdc
|
||||
dev/atkbdc/psm.c optional psm atkbdc
|
||||
dev/fb/fb.c optional fb
|
||||
dev/fb/fb.c optional vga
|
||||
dev/fb/splash.c optional splash
|
||||
|
@ -149,8 +155,6 @@ dev/fdc/fdc_pccard.c optional fdc pccard
|
|||
dev/hwpmc/hwpmc_amd.c optional hwpmc
|
||||
dev/hwpmc/hwpmc_piv.c optional hwpmc
|
||||
dev/hwpmc/hwpmc_x86.c optional hwpmc
|
||||
dev/kbd/atkbd.c optional atkbd
|
||||
dev/kbd/atkbdc.c optional atkbdc
|
||||
dev/kbd/kbd.c optional atkbd
|
||||
dev/kbd/kbd.c optional sc
|
||||
dev/kbd/kbd.c optional ukbd
|
||||
|
@ -175,9 +179,6 @@ geom/geom_bsd.c standard
|
|||
geom/geom_bsd_enc.c standard
|
||||
geom/geom_mbr.c standard
|
||||
geom/geom_mbr_enc.c standard
|
||||
isa/atkbd_isa.c optional atkbd
|
||||
isa/atkbdc_isa.c optional atkbdc
|
||||
isa/psm.c optional psm
|
||||
isa/syscons_isa.c optional sc
|
||||
isa/vga_isa.c optional vga
|
||||
kern/link_elf_obj.c standard
|
||||
|
|
|
@ -145,6 +145,12 @@ dev/ar/if_ar_isa.c optional ar isa
|
|||
dev/ar/if_ar_pci.c optional ar pci
|
||||
dev/arl/if_arl.c optional arl
|
||||
dev/arl/if_arl_isa.c optional arl isa
|
||||
dev/atkbdc/atkbd.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbd_atkbdc.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbdc.c optional atkbdc
|
||||
dev/atkbdc/atkbdc_isa.c optional atkbdc isa
|
||||
dev/atkbdc/atkbdc_subr.c optional atkbdc
|
||||
dev/atkbdc/psm.c optional psm atkbdc
|
||||
dev/cm/if_cm_isa.c optional cm isa
|
||||
dev/cp/cpddk.c optional cp
|
||||
dev/cp/if_cp.c optional cp
|
||||
|
@ -185,8 +191,6 @@ dev/if_ndis/if_ndis_pci.c optional ndis cardbus
|
|||
dev/if_ndis/if_ndis_pci.c optional ndis pci
|
||||
dev/if_ndis/if_ndis_usb.c optional ndis usb
|
||||
dev/io/iodev.c optional io
|
||||
dev/kbd/atkbd.c optional atkbd
|
||||
dev/kbd/atkbdc.c optional atkbdc
|
||||
dev/kbd/kbd.c optional atkbd
|
||||
dev/kbd/kbd.c optional sc
|
||||
dev/kbd/kbd.c optional ukbd
|
||||
|
@ -448,9 +452,6 @@ i4b/layer1/itjc/i4b_itjc_isac.c optional itjc
|
|||
i4b/layer1/itjc/i4b_itjc_l1.c optional itjc
|
||||
i4b/layer1/itjc/i4b_itjc_l1fsm.c optional itjc
|
||||
#
|
||||
isa/atkbd_isa.c optional atkbd
|
||||
isa/atkbdc_isa.c optional atkbdc
|
||||
isa/psm.c optional psm
|
||||
isa/syscons_isa.c optional sc
|
||||
isa/vga_isa.c optional vga
|
||||
kern/imgact_aout.c optional compat_aout
|
||||
|
|
|
@ -48,13 +48,17 @@ crypto/des/des_enc.c optional crypto
|
|||
crypto/des/des_enc.c optional ipsec ipsec_esp
|
||||
dev/advansys/adv_isa.c optional adv isa
|
||||
dev/aic/aic_isa.c optional aic isa
|
||||
dev/atkbdc/atkbd.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbd_atkbdc.c optional atkbd atkbdc
|
||||
dev/atkbdc/atkbdc.c optional atkbdc
|
||||
dev/atkbdc/atkbdc_isa.c optional atkbdc isa
|
||||
dev/atkbdc/atkbdc_subr.c optional atkbdc
|
||||
dev/atkbdc/psm.c optional psm atkbdc
|
||||
dev/fb/fb.c optional fb
|
||||
dev/fb/fb.c optional vga
|
||||
dev/fb/splash.c optional splash
|
||||
dev/fb/vga.c optional vga
|
||||
dev/hwpmc/hwpmc_ia64.c optional hwpmc
|
||||
dev/kbd/atkbd.c optional atkbd
|
||||
dev/kbd/atkbdc.c optional atkbdc
|
||||
dev/kbd/kbd.c optional atkbd
|
||||
dev/kbd/kbd.c optional sc
|
||||
dev/kbd/kbd.c optional ukbd
|
||||
|
@ -125,9 +129,6 @@ ia64/ia64/vm_machdep.c standard
|
|||
ia64/isa/isa.c optional isa
|
||||
ia64/isa/isa_dma.c optional isa
|
||||
ia64/pci/pci_cfgreg.c optional pci
|
||||
isa/atkbd_isa.c optional atkbd
|
||||
isa/atkbdc_isa.c optional atkbdc
|
||||
isa/psm.c optional psm
|
||||
isa/syscons_isa.c optional sc
|
||||
isa/vga_isa.c optional vga
|
||||
kern/imgact_elf32.c optional compat_ia32
|
||||
|
|
|
@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
|
@ -51,16 +52,17 @@ __FBSDID("$FreeBSD$");
|
|||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#endif /* __i386__ */
|
||||
|
||||
#include <sys/kbio.h>
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
#include <dev/kbd/atkbdreg.h>
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <dev/atkbdc/atkbdreg.h>
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
|
||||
static timeout_t atkbd_timeout;
|
||||
static void atkbd_shutdown_final(void *v);
|
||||
|
||||
int
|
||||
atkbd_probe_unit(int unit, int ctlr, int irq, int flags)
|
||||
|
@ -119,6 +121,10 @@ atkbd_attach_unit(int unit, keyboard_t **kbd, int ctlr, int irq, int flags)
|
|||
|
||||
if (bootverbose)
|
||||
(*sw->diag)(*kbd, bootverbose);
|
||||
|
||||
EVENTHANDLER_REGISTER(shutdown_final, atkbd_shutdown_final, *kbd,
|
||||
SHUTDOWN_PRI_DEFAULT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -839,7 +845,7 @@ atkbd_check_char(keyboard_t *kbd)
|
|||
static int
|
||||
atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
|
||||
{
|
||||
/* trasnlate LED_XXX bits into the device specific bits */
|
||||
/* translate LED_XXX bits into the device specific bits */
|
||||
static u_char ledmap[8] = {
|
||||
0, 4, 2, 6, 1, 5, 3, 7,
|
||||
};
|
||||
|
@ -1021,6 +1027,30 @@ atkbd_poll(keyboard_t *kbd, int on)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
atkbd_shutdown_final(void *v)
|
||||
{
|
||||
#ifdef __sparc64__
|
||||
keyboard_t *kbd = v;
|
||||
KBDC kbdc = ((atkbd_state_t *)kbd->kb_data)->kbdc;
|
||||
|
||||
/*
|
||||
* Turn off the translation in preparation for handing the keyboard
|
||||
* over to the OFW as the OBP driver doesn't use translation and
|
||||
* also doesn't disable it itself resulting in a broken keymap at
|
||||
* the boot prompt. Also disable the aux port and the interrupts as
|
||||
* the OBP driver doesn't use them, i.e. polls the keyboard. Not
|
||||
* disabling the interrupts doesn't cause real problems but the
|
||||
* responsiveness is a bit better when they are turned off.
|
||||
*/
|
||||
send_kbd_command(kbdc, KBDC_DISABLE_KBD);
|
||||
set_controller_command_byte(kbdc,
|
||||
KBD_AUX_CONTROL_BITS | KBD_KBD_CONTROL_BITS | KBD_TRANSLATION,
|
||||
KBD_DISABLE_AUX_PORT | KBD_DISABLE_KBD_INT | KBD_ENABLE_KBD_PORT);
|
||||
send_kbd_command(kbdc, KBDC_ENABLE_KBD);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* local functions */
|
||||
|
||||
static int
|
||||
|
@ -1299,11 +1329,10 @@ init_keyboard(KBDC kbdc, int *type, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __alpha__
|
||||
#if defined(__alpha__) || defined(__sparc64__)
|
||||
if (send_kbd_command_and_data(
|
||||
kbdc, KBDC_SET_SCANCODE_SET, 2) != KBD_ACK) {
|
||||
printf("atkbd: can't set translation.\n");
|
||||
|
||||
}
|
||||
c |= KBD_TRANSLATION;
|
||||
#endif
|
||||
|
|
|
@ -41,11 +41,8 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#include <sys/kbio.h>
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
#include <dev/kbd/atkbdreg.h>
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <isa/isavar.h>
|
||||
#include <dev/atkbdc/atkbdreg.h>
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
|
||||
typedef struct {
|
||||
struct resource *intr;
|
||||
|
@ -58,7 +55,7 @@ static void atkbdidentify(driver_t *driver, device_t dev);
|
|||
static int atkbdprobe(device_t dev);
|
||||
static int atkbdattach(device_t dev);
|
||||
static int atkbdresume(device_t dev);
|
||||
static void atkbd_isa_intr(void *arg);
|
||||
static void atkbdintr(void *arg);
|
||||
|
||||
static device_method_t atkbd_methods[] = {
|
||||
DEVMETHOD(device_identify, atkbdidentify),
|
||||
|
@ -139,7 +136,7 @@ atkbdattach(device_t dev)
|
|||
RF_SHAREABLE | RF_ACTIVE);
|
||||
if (sc->intr == NULL)
|
||||
return ENXIO;
|
||||
error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, atkbd_isa_intr,
|
||||
error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, atkbdintr,
|
||||
kbd, &sc->ih);
|
||||
if (error)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
|
||||
|
@ -169,7 +166,7 @@ atkbdresume(device_t dev)
|
|||
}
|
||||
|
||||
static void
|
||||
atkbd_isa_intr(void *arg)
|
||||
atkbdintr(void *arg)
|
||||
{
|
||||
keyboard_t *kbd;
|
||||
|
||||
|
|
|
@ -44,10 +44,15 @@ __FBSDID("$FreeBSD$");
|
|||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
|
||||
#ifdef __sparc64__
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <machine/bus_private.h>
|
||||
#include <machine/ofw_machdep.h>
|
||||
#else
|
||||
#include <isa/isareg.h>
|
||||
#endif
|
||||
|
||||
/* constants */
|
||||
|
||||
|
@ -88,6 +93,10 @@ static atkbdc_softc_t *atkbdc_softc[MAXKBDC] = { &default_kbdc };
|
|||
|
||||
static int verbose = KBDIO_DEBUG;
|
||||
|
||||
#ifdef __sparc64__
|
||||
static struct bus_space_tag atkbdc_bst_store[MAXKBDC];
|
||||
#endif
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
static int atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag,
|
||||
|
@ -144,14 +153,16 @@ atkbdc_configure(void)
|
|||
bus_space_tag_t tag;
|
||||
bus_space_handle_t h0;
|
||||
bus_space_handle_t h1;
|
||||
#ifdef __sparc64__
|
||||
char name[32];
|
||||
phandle_t chosen, node;
|
||||
ihandle_t stdin;
|
||||
bus_addr_t port0;
|
||||
bus_addr_t port1;
|
||||
int space;
|
||||
#else
|
||||
int port0;
|
||||
int port1;
|
||||
|
||||
port0 = IO_KBD;
|
||||
resource_int_value("atkbdc", 0, "port", &port0);
|
||||
port1 = IO_KBD + KBD_STATUS_PORT;
|
||||
#if 0
|
||||
resource_int_value("atkbdc", 0, "port", &port0);
|
||||
#endif
|
||||
|
||||
/* XXX: tag should be passed from the caller */
|
||||
|
@ -163,16 +174,50 @@ atkbdc_configure(void)
|
|||
tag = busspace_isa_io;
|
||||
#elif defined(__ia64__)
|
||||
tag = IA64_BUS_SPACE_IO;
|
||||
#elif defined(__sparc64__)
|
||||
tag = &atkbdc_bst_store[0];
|
||||
#else
|
||||
#error "define tag!"
|
||||
#endif
|
||||
|
||||
#ifdef __sparc64__
|
||||
if ((chosen = OF_finddevice("/chosen")) == -1)
|
||||
return 0;
|
||||
if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1)
|
||||
return 0;
|
||||
if ((node = OF_instance_to_package(stdin)) == -1)
|
||||
return 0;
|
||||
if (OF_getprop(node, "name", name, sizeof(name)) == -1)
|
||||
return 0;
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
if (strcmp(name, "kb_ps2") != 0)
|
||||
return 0;
|
||||
/*
|
||||
* The stdin handle points to an instance of a PS/2 keyboard
|
||||
* package but we want the 8042 controller, which is the parent
|
||||
* of that keyboard node.
|
||||
*/
|
||||
if ((node = OF_parent(node)) == 0)
|
||||
return 0;
|
||||
if (OF_decode_addr(node, 0, &space, &port0) != 0)
|
||||
return 0;
|
||||
h0 = sparc64_fake_bustag(space, port0, tag);
|
||||
bus_space_subregion(tag, h0, KBD_DATA_PORT, 1, &h0);
|
||||
if (OF_decode_addr(node, 1, &space, &port1) != 0)
|
||||
return 0;
|
||||
h1 = sparc64_fake_bustag(space, port1, tag);
|
||||
bus_space_subregion(tag, h1, KBD_STATUS_PORT, 1, &h1);
|
||||
#else
|
||||
port0 = IO_KBD;
|
||||
resource_int_value("atkbdc", 0, "port", &port0);
|
||||
port1 = IO_KBD + KBD_STATUS_PORT;
|
||||
#if notyet
|
||||
bus_space_map(tag, port0, IO_KBDSIZE, 0, &h0);
|
||||
bus_space_map(tag, port1, IO_KBDSIZE, 0, &h1);
|
||||
#else
|
||||
h0 = (bus_space_handle_t)port0;
|
||||
h1 = (bus_space_handle_t)port1;
|
||||
#endif
|
||||
#endif
|
||||
return atkbdc_setup(atkbdc_softc[0], tag, h0, h1);
|
||||
}
|
||||
|
|
304
sys/dev/atkbdc/atkbdc_ebus.c
Normal file
304
sys/dev/atkbdc/atkbdc_ebus.c
Normal file
|
@ -0,0 +1,304 @@
|
|||
/*-
|
||||
* Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
|
||||
* Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
|
||||
* 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.
|
||||
*
|
||||
* from: FreeBSD: src/sys/isa/atkbdc_isa.c,v 1.31 2005/05/29 04:42:28 nyan
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$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 <sys/kbio.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
|
||||
#include <machine/resource.h>
|
||||
#include <machine/ver.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
#include <dev/atkbdc/atkbdreg.h>
|
||||
#include <dev/atkbdc/atkbdc_subr.h>
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
#include <dev/atkbdc/psm.h>
|
||||
|
||||
static device_probe_t atkbdc_ebus_probe;
|
||||
static device_attach_t atkbdc_ebus_attach;
|
||||
|
||||
static device_method_t atkbdc_ebus_methods[] = {
|
||||
DEVMETHOD(device_probe, atkbdc_ebus_probe),
|
||||
DEVMETHOD(device_attach, atkbdc_ebus_attach),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
DEVMETHOD(bus_print_child, atkbdc_print_child),
|
||||
DEVMETHOD(bus_read_ivar, atkbdc_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, atkbdc_write_ivar),
|
||||
DEVMETHOD(bus_get_resource_list,atkbdc_get_resource_list),
|
||||
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
|
||||
DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t atkbdc_ebus_driver = {
|
||||
ATKBDC_DRIVER_NAME,
|
||||
atkbdc_ebus_methods,
|
||||
sizeof(atkbdc_softc_t *),
|
||||
};
|
||||
|
||||
DRIVER_MODULE(atkbdc, ebus, atkbdc_ebus_driver, atkbdc_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
atkbdc_ebus_probe(device_t dev)
|
||||
{
|
||||
struct resource *port0, *port1;
|
||||
u_long count, start;
|
||||
int error, rid;
|
||||
|
||||
if (strcmp(ofw_bus_get_name(dev), "8042") != 0)
|
||||
return (ENXIO);
|
||||
|
||||
/*
|
||||
* On AXi and AXmp boards the NS16550 (used to connect keyboard/
|
||||
* mouse) share their IRQ lines with the i8042. Any IRQ activity
|
||||
* (typically during attach) of the NS16550 used to connect the
|
||||
* keyboard when actually the PS/2 keyboard is selected in OFW
|
||||
* causes interaction with the OBP i8042 driver resulting in a
|
||||
* hang and vice versa. As RS232 keyboards and mice obviously
|
||||
* aren't meant to be used in parallel with PS/2 ones on these
|
||||
* boards don't attach to the i8042 in case the PS/2 keyboard
|
||||
* isn't selected in order to prevent such hangs.
|
||||
* Note that it's not sufficient here to rely on the '8042' node
|
||||
* only showing up when a PS/2 keyboard is actually connected as
|
||||
* the user still might have adjusted the 'keyboard' alias to
|
||||
* point to the RS232 keyboard.
|
||||
*/
|
||||
if ((!strcmp(sparc64_model, "SUNW,UltraAX-MP") ||
|
||||
!strcmp(sparc64_model, "SUNW,UltraSPARC-IIi-Engine")) &&
|
||||
OF_finddevice("keyboard") != ofw_bus_get_node(dev)) {
|
||||
device_disable(dev);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
device_set_desc(dev, "Keyboard controller (i8042)");
|
||||
|
||||
/*
|
||||
* The '8042' node has two identical 8 addresses wide resources
|
||||
* which are apparently meant to be used one for the keyboard
|
||||
* half and the other one for the mouse half. To simplify matters
|
||||
* we use one for the command/data port resource and the other
|
||||
* one for the status port resource as the atkbdc(4) back-end
|
||||
* expects two struct resource rather than two bus space handles.
|
||||
*/
|
||||
rid = 0;
|
||||
if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
|
||||
device_printf(dev,
|
||||
"cannot determine command/data port resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
port0 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start, 1,
|
||||
RF_ACTIVE);
|
||||
if (port0 == NULL) {
|
||||
device_printf(dev,
|
||||
"cannot allocate command/data port resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
rid = 1;
|
||||
if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
|
||||
device_printf(dev, "cannot determine status port resource\n");
|
||||
error = ENXIO;
|
||||
goto fail_port0;
|
||||
}
|
||||
start += KBD_STATUS_PORT;
|
||||
port1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start, 1,
|
||||
RF_ACTIVE);
|
||||
if (port1 == NULL) {
|
||||
device_printf(dev, "cannot allocate status port resource\n");
|
||||
error = ENXIO;
|
||||
goto fail_port0;
|
||||
}
|
||||
|
||||
error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
|
||||
if (error != 0)
|
||||
device_printf(dev, "atkbdc_porbe_unit failed\n");
|
||||
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 1, port1);
|
||||
fail_port0:
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0, port0);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_ebus_attach(device_t dev)
|
||||
{
|
||||
atkbdc_softc_t *sc;
|
||||
atkbdc_device_t *adi;
|
||||
device_t cdev;
|
||||
phandle_t child;
|
||||
u_long count, intr, start;
|
||||
int children, error, rid, unit;
|
||||
char *cname, *dname;
|
||||
|
||||
unit = device_get_unit(dev);
|
||||
sc = *(atkbdc_softc_t **)device_get_softc(dev);
|
||||
if (sc == NULL) {
|
||||
/*
|
||||
* We have to maintain two copies of the kbdc_softc struct,
|
||||
* as the low-level console needs to have access to the
|
||||
* keyboard controller before kbdc is probed and attached.
|
||||
* kbdc_soft[] contains the default entry for that purpose.
|
||||
* See atkbdc.c. XXX
|
||||
*/
|
||||
sc = atkbdc_get_softc(unit);
|
||||
if (sc == NULL)
|
||||
return (ENOMEM);
|
||||
device_set_softc(dev, sc);
|
||||
}
|
||||
|
||||
rid = 0;
|
||||
if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
|
||||
device_printf(dev,
|
||||
"cannot determine command/data port resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->port0 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start,
|
||||
1, RF_ACTIVE);
|
||||
if (sc->port0 == NULL) {
|
||||
device_printf(dev,
|
||||
"cannot allocate command/data port resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
rid = 1;
|
||||
if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
|
||||
device_printf(dev, "cannot determine status port resource\n");
|
||||
error = ENXIO;
|
||||
goto fail_port0;
|
||||
}
|
||||
start += KBD_STATUS_PORT;
|
||||
sc->port1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start,
|
||||
1, RF_ACTIVE);
|
||||
if (sc->port1 == NULL) {
|
||||
device_printf(dev, "cannot allocate status port resource\n");
|
||||
error = ENXIO;
|
||||
goto fail_port0;
|
||||
}
|
||||
|
||||
error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "atkbdc_attach_unit failed\n");
|
||||
goto fail_port1;
|
||||
}
|
||||
|
||||
/* Attach children. */
|
||||
children = 0;
|
||||
for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
|
||||
child = OF_peer(child)) {
|
||||
if ((OF_getprop_alloc(child, "name", 1, (void **)&cname)) == -1)
|
||||
continue;
|
||||
if (children >= 2) {
|
||||
device_printf(dev,
|
||||
"<%s>: only two children per 8042 supported\n",
|
||||
cname);
|
||||
free(cname, M_OFWPROP);
|
||||
continue;
|
||||
}
|
||||
adi = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (adi == NULL) {
|
||||
device_printf(dev, "<%s>: malloc failed\n", cname);
|
||||
free(cname, M_OFWPROP);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(cname, "kb_ps2") == 0) {
|
||||
adi->rid = KBDC_RID_KBD;
|
||||
dname = ATKBD_DRIVER_NAME;
|
||||
} else if (strcmp(cname, "kdmouse") == 0) {
|
||||
adi->rid = KBDC_RID_AUX;
|
||||
dname = PSM_DRIVER_NAME;
|
||||
} else {
|
||||
device_printf(dev, "<%s>: unknown device\n", cname);
|
||||
free(adi, M_ATKBDDEV);
|
||||
free(cname, M_OFWPROP);
|
||||
continue;
|
||||
}
|
||||
intr = bus_get_resource_start(dev, SYS_RES_IRQ, adi->rid);
|
||||
if (intr == 0) {
|
||||
device_printf(dev,
|
||||
"<%s>: cannot determine interrupt resource\n",
|
||||
cname);
|
||||
free(adi, M_ATKBDDEV);
|
||||
free(cname, M_OFWPROP);
|
||||
continue;
|
||||
}
|
||||
resource_list_init(&adi->resources);
|
||||
resource_list_add(&adi->resources, SYS_RES_IRQ, adi->rid,
|
||||
intr, intr, 1);
|
||||
if ((cdev = device_add_child(dev, dname, -1)) == NULL) {
|
||||
device_printf(dev, "<%s>: device_add_child failed\n",
|
||||
cname);
|
||||
resource_list_free(&adi->resources);
|
||||
free(adi, M_ATKBDDEV);
|
||||
free(cname, M_OFWPROP);
|
||||
continue;
|
||||
}
|
||||
device_set_ivars(cdev, adi);
|
||||
children++;
|
||||
}
|
||||
|
||||
error = bus_generic_attach(dev);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "bus_generic_attach failed\n");
|
||||
goto fail_port1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail_port1:
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->port1);
|
||||
fail_port0:
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->port0);
|
||||
|
||||
return (error);
|
||||
}
|
|
@ -38,57 +38,30 @@ __FBSDID("$FreeBSD$");
|
|||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
#include <dev/atkbdc/atkbdc_subr.h>
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
static MALLOC_DEFINE(M_ATKBDDEV, "atkbddev", "AT Keyboard device");
|
||||
|
||||
/* children */
|
||||
typedef struct atkbdc_device {
|
||||
struct resource_list resources;
|
||||
int rid;
|
||||
u_int32_t vendorid;
|
||||
u_int32_t serial;
|
||||
u_int32_t logicalid;
|
||||
u_int32_t compatid;
|
||||
} atkbdc_device_t;
|
||||
|
||||
/* kbdc */
|
||||
static devclass_t atkbdc_devclass;
|
||||
|
||||
static int atkbdc_probe(device_t dev);
|
||||
static int atkbdc_attach(device_t dev);
|
||||
static device_t atkbdc_add_child(device_t bus, int order, char *name,
|
||||
static int atkbdc_isa_probe(device_t dev);
|
||||
static int atkbdc_isa_attach(device_t dev);
|
||||
static device_t atkbdc_isa_add_child(device_t bus, int order, char *name,
|
||||
int unit);
|
||||
static int atkbdc_print_child(device_t bus, device_t dev);
|
||||
static int atkbdc_read_ivar(device_t bus, device_t dev, int index,
|
||||
uintptr_t *val);
|
||||
static int atkbdc_write_ivar(device_t bus, device_t dev, int index,
|
||||
uintptr_t val);
|
||||
static struct resource_list
|
||||
*atkbdc_get_resource_list (device_t bus, device_t dev);
|
||||
static struct resource
|
||||
*atkbdc_alloc_resource(device_t bus, device_t dev, int type,
|
||||
int *rid, u_long start, u_long end,
|
||||
u_long count, u_int flags);
|
||||
static int atkbdc_release_resource(device_t bus, device_t dev, int type,
|
||||
int rid, struct resource *res);
|
||||
|
||||
static device_method_t atkbdc_methods[] = {
|
||||
DEVMETHOD(device_probe, atkbdc_probe),
|
||||
DEVMETHOD(device_attach, atkbdc_attach),
|
||||
static device_method_t atkbdc_isa_methods[] = {
|
||||
DEVMETHOD(device_probe, atkbdc_isa_probe),
|
||||
DEVMETHOD(device_attach, atkbdc_isa_attach),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
DEVMETHOD(bus_add_child, atkbdc_add_child),
|
||||
DEVMETHOD(bus_add_child, atkbdc_isa_add_child),
|
||||
DEVMETHOD(bus_print_child, atkbdc_print_child),
|
||||
DEVMETHOD(bus_read_ivar, atkbdc_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, atkbdc_write_ivar),
|
||||
DEVMETHOD(bus_get_resource_list,atkbdc_get_resource_list),
|
||||
DEVMETHOD(bus_alloc_resource, atkbdc_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, atkbdc_release_resource),
|
||||
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
|
@ -100,9 +73,9 @@ static device_method_t atkbdc_methods[] = {
|
|||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t atkbdc_driver = {
|
||||
static driver_t atkbdc_isa_driver = {
|
||||
ATKBDC_DRIVER_NAME,
|
||||
atkbdc_methods,
|
||||
atkbdc_isa_methods,
|
||||
sizeof(atkbdc_softc_t *),
|
||||
};
|
||||
|
||||
|
@ -112,7 +85,7 @@ static struct isa_pnp_id atkbdc_ids[] = {
|
|||
};
|
||||
|
||||
static int
|
||||
atkbdc_probe(device_t dev)
|
||||
atkbdc_isa_probe(device_t dev)
|
||||
{
|
||||
struct resource *port0;
|
||||
struct resource *port1;
|
||||
|
@ -167,7 +140,7 @@ atkbdc_probe(device_t dev)
|
|||
}
|
||||
|
||||
static int
|
||||
atkbdc_attach(device_t dev)
|
||||
atkbdc_isa_attach(device_t dev)
|
||||
{
|
||||
atkbdc_softc_t *sc;
|
||||
int unit;
|
||||
|
@ -180,7 +153,7 @@ atkbdc_attach(device_t dev)
|
|||
/*
|
||||
* We have to maintain two copies of the kbdc_softc struct,
|
||||
* as the low-level console needs to have access to the
|
||||
* keyboard controller before kbdc is probed and attached.
|
||||
* keyboard controller before kbdc is probed and attached.
|
||||
* kbdc_soft[] contains the default entry for that purpose.
|
||||
* See atkbdc.c. XXX
|
||||
*/
|
||||
|
@ -216,7 +189,7 @@ atkbdc_attach(device_t dev)
|
|||
}
|
||||
|
||||
static device_t
|
||||
atkbdc_add_child(device_t bus, int order, char *name, int unit)
|
||||
atkbdc_isa_add_child(device_t bus, int order, char *name, int unit)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
device_t child;
|
||||
|
@ -258,108 +231,5 @@ atkbdc_add_child(device_t bus, int order, char *name, int unit)
|
|||
return child;
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_print_child(device_t bus, device_t dev)
|
||||
{
|
||||
atkbdc_device_t *kbdcdev;
|
||||
u_long irq;
|
||||
int flags;
|
||||
int retval = 0;
|
||||
|
||||
kbdcdev = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
|
||||
retval += bus_print_child_header(bus, dev);
|
||||
flags = device_get_flags(dev);
|
||||
if (flags != 0)
|
||||
retval += printf(" flags 0x%x", flags);
|
||||
irq = bus_get_resource_start(dev, SYS_RES_IRQ, kbdcdev->rid);
|
||||
if (irq != 0)
|
||||
retval += printf(" irq %ld", irq);
|
||||
retval += bus_print_child_footer(bus, dev);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
switch (index) {
|
||||
case KBDC_IVAR_VENDORID:
|
||||
*val = (u_long)ivar->vendorid;
|
||||
break;
|
||||
case KBDC_IVAR_SERIAL:
|
||||
*val = (u_long)ivar->serial;
|
||||
break;
|
||||
case KBDC_IVAR_LOGICALID:
|
||||
*val = (u_long)ivar->logicalid;
|
||||
break;
|
||||
case KBDC_IVAR_COMPATID:
|
||||
*val = (u_long)ivar->compatid;
|
||||
break;
|
||||
default:
|
||||
return ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
switch (index) {
|
||||
case KBDC_IVAR_VENDORID:
|
||||
ivar->vendorid = (u_int32_t)val;
|
||||
break;
|
||||
case KBDC_IVAR_SERIAL:
|
||||
ivar->serial = (u_int32_t)val;
|
||||
break;
|
||||
case KBDC_IVAR_LOGICALID:
|
||||
ivar->logicalid = (u_int32_t)val;
|
||||
break;
|
||||
case KBDC_IVAR_COMPATID:
|
||||
ivar->compatid = (u_int32_t)val;
|
||||
break;
|
||||
default:
|
||||
return ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource_list
|
||||
*atkbdc_get_resource_list (device_t bus, device_t dev)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return &ivar->resources;
|
||||
}
|
||||
|
||||
static struct resource
|
||||
*atkbdc_alloc_resource(device_t bus, device_t dev, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return resource_list_alloc(&ivar->resources, bus, dev, type, rid,
|
||||
start, end, count, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_release_resource(device_t bus, device_t dev, int type, int rid,
|
||||
struct resource *res)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return resource_list_release(&ivar->resources, bus, dev, type, rid,
|
||||
res);
|
||||
}
|
||||
|
||||
DRIVER_MODULE(atkbdc, isa, atkbdc_driver, atkbdc_devclass, 0, 0);
|
||||
DRIVER_MODULE(atkbdc, acpi, atkbdc_driver, atkbdc_devclass, 0, 0);
|
||||
DRIVER_MODULE(atkbdc, isa, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
||||
DRIVER_MODULE(atkbdc, acpi, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
* 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: FreeBSD: src/sys/isa/atkbdc_isa.c,v 1.31 2005/05/29 04:42:28 nyan Exp
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
@ -38,227 +40,14 @@ __FBSDID("$FreeBSD$");
|
|||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
#include <dev/atkbdc/atkbdc_subr.h>
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <isa/isavar.h>
|
||||
MALLOC_DEFINE(M_ATKBDDEV, "atkbddev", "AT Keyboard device");
|
||||
|
||||
static MALLOC_DEFINE(M_ATKBDDEV, "atkbddev", "AT Keyboard device");
|
||||
devclass_t atkbdc_devclass;
|
||||
|
||||
/* children */
|
||||
typedef struct atkbdc_device {
|
||||
struct resource_list resources;
|
||||
int rid;
|
||||
u_int32_t vendorid;
|
||||
u_int32_t serial;
|
||||
u_int32_t logicalid;
|
||||
u_int32_t compatid;
|
||||
} atkbdc_device_t;
|
||||
|
||||
/* kbdc */
|
||||
static devclass_t atkbdc_devclass;
|
||||
|
||||
static int atkbdc_probe(device_t dev);
|
||||
static int atkbdc_attach(device_t dev);
|
||||
static device_t atkbdc_add_child(device_t bus, int order, char *name,
|
||||
int unit);
|
||||
static int atkbdc_print_child(device_t bus, device_t dev);
|
||||
static int atkbdc_read_ivar(device_t bus, device_t dev, int index,
|
||||
uintptr_t *val);
|
||||
static int atkbdc_write_ivar(device_t bus, device_t dev, int index,
|
||||
uintptr_t val);
|
||||
static struct resource_list
|
||||
*atkbdc_get_resource_list (device_t bus, device_t dev);
|
||||
static struct resource
|
||||
*atkbdc_alloc_resource(device_t bus, device_t dev, int type,
|
||||
int *rid, u_long start, u_long end,
|
||||
u_long count, u_int flags);
|
||||
static int atkbdc_release_resource(device_t bus, device_t dev, int type,
|
||||
int rid, struct resource *res);
|
||||
|
||||
static device_method_t atkbdc_methods[] = {
|
||||
DEVMETHOD(device_probe, atkbdc_probe),
|
||||
DEVMETHOD(device_attach, atkbdc_attach),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
DEVMETHOD(bus_add_child, atkbdc_add_child),
|
||||
DEVMETHOD(bus_print_child, atkbdc_print_child),
|
||||
DEVMETHOD(bus_read_ivar, atkbdc_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, atkbdc_write_ivar),
|
||||
DEVMETHOD(bus_get_resource_list,atkbdc_get_resource_list),
|
||||
DEVMETHOD(bus_alloc_resource, atkbdc_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, atkbdc_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
|
||||
DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t atkbdc_driver = {
|
||||
ATKBDC_DRIVER_NAME,
|
||||
atkbdc_methods,
|
||||
sizeof(atkbdc_softc_t *),
|
||||
};
|
||||
|
||||
static struct isa_pnp_id atkbdc_ids[] = {
|
||||
{ 0x0303d041, "Keyboard controller (i8042)" }, /* PNP0303 */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
atkbdc_probe(device_t dev)
|
||||
{
|
||||
struct resource *port0;
|
||||
struct resource *port1;
|
||||
u_long start;
|
||||
u_long count;
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
/* check PnP IDs */
|
||||
if (ISA_PNP_PROBE(device_get_parent(dev), dev, atkbdc_ids) == ENXIO)
|
||||
return ENXIO;
|
||||
|
||||
device_set_desc(dev, "Keyboard controller (i8042)");
|
||||
|
||||
/*
|
||||
* Adjust I/O port resources.
|
||||
* The AT keyboard controller uses two ports (a command/data port
|
||||
* 0x60 and a status port 0x64), which may be given to us in
|
||||
* one resource (0x60 through 0x64) or as two separate resources
|
||||
* (0x60 and 0x64). Furthermore, /boot/device.hints may contain
|
||||
* just one port, 0x60. We shall adjust resource settings
|
||||
* so that these two ports are available as two separate resources.
|
||||
*/
|
||||
device_quiet(dev);
|
||||
rid = 0;
|
||||
if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count) != 0)
|
||||
return ENXIO;
|
||||
if (count > 1) /* adjust the count */
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, rid, start, 1);
|
||||
port0 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
|
||||
if (port0 == NULL)
|
||||
return ENXIO;
|
||||
rid = 1;
|
||||
if (bus_get_resource(dev, SYS_RES_IOPORT, rid, NULL, NULL) != 0)
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, 1,
|
||||
start + KBD_STATUS_PORT, 1);
|
||||
port1 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
|
||||
if (port1 == NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
|
||||
return ENXIO;
|
||||
}
|
||||
device_verbose(dev);
|
||||
|
||||
error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
|
||||
if (error == 0)
|
||||
bus_generic_probe(dev);
|
||||
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_attach(device_t dev)
|
||||
{
|
||||
atkbdc_softc_t *sc;
|
||||
int unit;
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
unit = device_get_unit(dev);
|
||||
sc = *(atkbdc_softc_t **)device_get_softc(dev);
|
||||
if (sc == NULL) {
|
||||
/*
|
||||
* We have to maintain two copies of the kbdc_softc struct,
|
||||
* as the low-level console needs to have access to the
|
||||
* keyboard controller before kbdc is probed and attached.
|
||||
* kbdc_soft[] contains the default entry for that purpose.
|
||||
* See atkbdc.c. XXX
|
||||
*/
|
||||
sc = atkbdc_get_softc(unit);
|
||||
if (sc == NULL)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
rid = 0;
|
||||
sc->port0 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->port0 == NULL)
|
||||
return ENXIO;
|
||||
rid = 1;
|
||||
sc->port1 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->port1 == NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1);
|
||||
if (error) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->port1);
|
||||
return error;
|
||||
}
|
||||
*(atkbdc_softc_t **)device_get_softc(dev) = sc;
|
||||
|
||||
bus_generic_attach(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static device_t
|
||||
atkbdc_add_child(device_t bus, int order, char *name, int unit)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
device_t child;
|
||||
int t;
|
||||
|
||||
ivar = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (!ivar)
|
||||
return NULL;
|
||||
|
||||
child = device_add_child_ordered(bus, order, name, unit);
|
||||
if (child == NULL) {
|
||||
free(ivar, M_ATKBDDEV);
|
||||
return child;
|
||||
}
|
||||
|
||||
resource_list_init(&ivar->resources);
|
||||
ivar->rid = order;
|
||||
|
||||
/*
|
||||
* If the device is not created by the PnP BIOS or ACPI,
|
||||
* refer to device hints for IRQ.
|
||||
*/
|
||||
if (ISA_PNP_PROBE(device_get_parent(bus), bus, atkbdc_ids) != 0) {
|
||||
if (resource_int_value(name, unit, "irq", &t) != 0)
|
||||
t = -1;
|
||||
} else {
|
||||
t = bus_get_resource_start(bus, SYS_RES_IRQ, ivar->rid);
|
||||
}
|
||||
if (t > 0)
|
||||
resource_list_add(&ivar->resources, SYS_RES_IRQ, ivar->rid,
|
||||
t, t, 1);
|
||||
|
||||
if (resource_disabled(name, unit))
|
||||
device_disable(child);
|
||||
|
||||
device_set_ivars(child, ivar);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
atkbdc_print_child(device_t bus, device_t dev)
|
||||
{
|
||||
atkbdc_device_t *kbdcdev;
|
||||
|
@ -280,7 +69,7 @@ atkbdc_print_child(device_t bus, device_t dev)
|
|||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
atkbdc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
@ -305,7 +94,7 @@ atkbdc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
atkbdc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
@ -330,36 +119,11 @@ atkbdc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct resource_list
|
||||
*atkbdc_get_resource_list (device_t bus, device_t dev)
|
||||
struct resource_list
|
||||
*atkbdc_get_resource_list(device_t bus, device_t dev)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return &ivar->resources;
|
||||
}
|
||||
|
||||
static struct resource
|
||||
*atkbdc_alloc_resource(device_t bus, device_t dev, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return resource_list_alloc(&ivar->resources, bus, dev, type, rid,
|
||||
start, end, count, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_release_resource(device_t bus, device_t dev, int type, int rid,
|
||||
struct resource *res)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return resource_list_release(&ivar->resources, bus, dev, type, rid,
|
||||
res);
|
||||
}
|
||||
|
||||
DRIVER_MODULE(atkbdc, isa, atkbdc_driver, atkbdc_devclass, 0, 0);
|
||||
DRIVER_MODULE(atkbdc, acpi, atkbdc_driver, atkbdc_devclass, 0, 0);
|
||||
|
|
|
@ -23,26 +23,31 @@
|
|||
* (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: FreeBSD: src/sys/isa/atkbdc_isa.c,v 1.31 2005/05/29 04:42:28 nyan Exp
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _DEV_KBD_ATKBDREG_H_
|
||||
#define _DEV_KBD_ATKBDREG_H_
|
||||
#ifndef _DEV_ATKBDC_ATKBDC_SUBR_H_
|
||||
#define _DEV_ATKBDC_ATKBDC_SUBR_H_
|
||||
|
||||
#define ATKBD_DRIVER_NAME "atkbd"
|
||||
MALLOC_DECLARE(M_ATKBDDEV);
|
||||
|
||||
/* device configuration flags (atkbdprobe, atkbdattach) */
|
||||
#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */
|
||||
#define KB_CONF_NO_RESET (1 << 1) /* don't reset the keyboard */
|
||||
#define KB_CONF_ALT_SCANCODESET (1 << 2) /* assume the XT type keyboard */
|
||||
#define KB_CONF_NO_PROBE_TEST (1 << 3) /* don't test keyboard during probe */
|
||||
extern devclass_t atkbdc_devclass;
|
||||
|
||||
#ifdef _KERNEL
|
||||
/* children */
|
||||
typedef struct atkbdc_device {
|
||||
struct resource_list resources;
|
||||
int rid;
|
||||
u_int32_t vendorid;
|
||||
u_int32_t serial;
|
||||
u_int32_t logicalid;
|
||||
u_int32_t compatid;
|
||||
} atkbdc_device_t;
|
||||
|
||||
int atkbd_probe_unit(int unit, int ctlr, int irq, int flags);
|
||||
int atkbd_attach_unit(int unit, keyboard_t **kbd,
|
||||
int ctlr, int irq, int flags);
|
||||
/* kbdc */
|
||||
int atkbdc_print_child(device_t bus, device_t dev);
|
||||
int atkbdc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val);
|
||||
int atkbdc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val);
|
||||
struct resource_list *atkbdc_get_resource_list(device_t bus, device_t dev);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_DEV_KBD_ATKBDREG_H_ */
|
||||
#endif /* !_DEV_ATKBDC_ATKBDC_SUBR_H_ */
|
|
@ -31,8 +31,8 @@
|
|||
* from kbdio.h,v 1.8 1998/09/25 11:55:46 yokota Exp
|
||||
*/
|
||||
|
||||
#ifndef _DEV_KBD_ATKBDCREG_H_
|
||||
#define _DEV_KBD_ATKBDCREG_H_
|
||||
#ifndef _DEV_ATKBDC_ATKBDCREG_H_
|
||||
#define _DEV_ATKBDC_ATKBDCREG_H_
|
||||
|
||||
#include "opt_kbd.h" /* Structures depend on the value if KBDIO_DEBUG */
|
||||
|
||||
|
@ -261,4 +261,4 @@ int set_controller_command_byte(KBDC kbdc, int command, int flag);
|
|||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_DEV_KBD_ATKBDCREG_H_ */
|
||||
#endif /* !_DEV_ATKBDC_ATKBDCREG_H_ */
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _DEV_KBD_ATKBDREG_H_
|
||||
#define _DEV_KBD_ATKBDREG_H_
|
||||
#ifndef _DEV_ATKBDC_ATKBDREG_H_
|
||||
#define _DEV_ATKBDC_ATKBDREG_H_
|
||||
|
||||
#define ATKBD_DRIVER_NAME "atkbd"
|
||||
|
||||
|
@ -45,4 +45,4 @@ int atkbd_attach_unit(int unit, keyboard_t **kbd,
|
|||
|
||||
#endif
|
||||
|
||||
#endif /* !_DEV_KBD_ATKBDREG_H_ */
|
||||
#endif /* !_DEV_ATKBDC_ATKBDREG_H_ */
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_isa.h"
|
||||
#include "opt_psm.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -82,8 +83,12 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/mouse.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#ifdef DEV_ISA
|
||||
#include <isa/isavar.h>
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
#endif
|
||||
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
#include <dev/atkbdc/psm.h>
|
||||
|
||||
/*
|
||||
* Driver specific options: the following options may be set by
|
||||
|
@ -117,7 +122,6 @@ do { \
|
|||
|
||||
/* end of driver specific options */
|
||||
|
||||
#define PSM_DRIVER_NAME "psm"
|
||||
#define PSMCPNP_DRIVER_NAME "psmcpnp"
|
||||
|
||||
/* input queue */
|
||||
|
@ -3469,6 +3473,31 @@ enable_versapad(struct psm_softc *sc)
|
|||
return TRUE; /* PS/2 absolute mode */
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if 'now' is earlier than (start + (secs.usecs)).
|
||||
* Now may be NULL and the function will fetch the current time from
|
||||
* getmicrouptime(), or a cached 'now' can be passed in.
|
||||
* All values should be numbers derived from getmicrouptime().
|
||||
*/
|
||||
static int
|
||||
timeelapsed(start, secs, usecs, now)
|
||||
const struct timeval *start, *now;
|
||||
int secs, usecs;
|
||||
{
|
||||
struct timeval snow, tv;
|
||||
|
||||
/* if there is no 'now' passed in, the get it as a convience. */
|
||||
if (now == NULL) {
|
||||
getmicrouptime(&snow);
|
||||
now = &snow;
|
||||
}
|
||||
|
||||
tv.tv_sec = secs;
|
||||
tv.tv_usec = usecs;
|
||||
timevaladd(&tv, start);
|
||||
return (timevalcmp(&tv, now, <));
|
||||
}
|
||||
|
||||
static int
|
||||
psmresume(device_t dev)
|
||||
{
|
||||
|
@ -3499,6 +3528,8 @@ psmresume(device_t dev)
|
|||
|
||||
DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0);
|
||||
|
||||
#ifdef DEV_ISA
|
||||
|
||||
/*
|
||||
* This sucks up assignments from PNPBIOS and ACPI.
|
||||
*/
|
||||
|
@ -3629,30 +3660,7 @@ psmcpnp_attach(device_t dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if 'now' is earlier than (start + (secs.usecs)).
|
||||
* Now may be NULL and the function will fetch the current time from
|
||||
* getmicrouptime(), or a cached 'now' can be passed in.
|
||||
* All values should be numbers derived from getmicrouptime().
|
||||
*/
|
||||
static int
|
||||
timeelapsed(start, secs, usecs, now)
|
||||
const struct timeval *start, *now;
|
||||
int secs, usecs;
|
||||
{
|
||||
struct timeval snow, tv;
|
||||
|
||||
/* if there is no 'now' passed in, the get it as a convience. */
|
||||
if (now == NULL) {
|
||||
getmicrouptime(&snow);
|
||||
now = &snow;
|
||||
}
|
||||
|
||||
tv.tv_sec = secs;
|
||||
tv.tv_usec = usecs;
|
||||
timevaladd(&tv, start);
|
||||
return (timevalcmp(&tv, now, <));
|
||||
}
|
||||
|
||||
DRIVER_MODULE(psmcpnp, isa, psmcpnp_driver, psmcpnp_devclass, 0, 0);
|
||||
DRIVER_MODULE(psmcpnp, acpi, psmcpnp_driver, psmcpnp_devclass, 0, 0);
|
||||
|
||||
#endif /* DEV_ISA */
|
||||
|
|
32
sys/dev/atkbdc/psm.h
Normal file
32
sys/dev/atkbdc/psm.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-
|
||||
* Copyright (c) 1992, 1993 Erik Forsberg.
|
||||
* Copyright (c) 1996, 1997 Kazutaka YOKOTA.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ``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 I 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: FreeBSD: src/sys/isa/psm.c,v 1.84 2005/01/10 13:05:58 philip
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _DEV_ATKBDC_PSM_H_
|
||||
#define _DEV_ATKBDC_PSM_H_
|
||||
|
||||
#define PSM_DRIVER_NAME "psm"
|
||||
|
||||
#endif /* !_DEV_ATKBDC_PSM_H_ */
|
1441
sys/dev/kbd/atkbd.c
1441
sys/dev/kbd/atkbd.c
File diff suppressed because it is too large
Load diff
1042
sys/dev/kbd/atkbdc.c
1042
sys/dev/kbd/atkbdc.c
File diff suppressed because it is too large
Load diff
|
@ -1,264 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1996-1999
|
||||
* Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
|
||||
* 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$
|
||||
* from kbdio.h,v 1.8 1998/09/25 11:55:46 yokota Exp
|
||||
*/
|
||||
|
||||
#ifndef _DEV_KBD_ATKBDCREG_H_
|
||||
#define _DEV_KBD_ATKBDCREG_H_
|
||||
|
||||
#include "opt_kbd.h" /* Structures depend on the value if KBDIO_DEBUG */
|
||||
|
||||
/* constants */
|
||||
|
||||
/* I/O ports */
|
||||
#define KBD_STATUS_PORT 4 /* status port, read */
|
||||
#define KBD_COMMAND_PORT 4 /* controller command port, write */
|
||||
#define KBD_DATA_PORT 0 /* data port, read/write
|
||||
* also used as keyboard command
|
||||
* and mouse command port
|
||||
*/
|
||||
|
||||
/* controller commands (sent to KBD_COMMAND_PORT) */
|
||||
#define KBDC_SET_COMMAND_BYTE 0x0060
|
||||
#define KBDC_GET_COMMAND_BYTE 0x0020
|
||||
#define KBDC_WRITE_TO_AUX 0x00d4
|
||||
#define KBDC_DISABLE_AUX_PORT 0x00a7
|
||||
#define KBDC_ENABLE_AUX_PORT 0x00a8
|
||||
#define KBDC_TEST_AUX_PORT 0x00a9
|
||||
#define KBDC_DIAGNOSE 0x00aa
|
||||
#define KBDC_TEST_KBD_PORT 0x00ab
|
||||
#define KBDC_DISABLE_KBD_PORT 0x00ad
|
||||
#define KBDC_ENABLE_KBD_PORT 0x00ae
|
||||
|
||||
/* controller command byte (set by KBDC_SET_COMMAND_BYTE) */
|
||||
#define KBD_TRANSLATION 0x0040
|
||||
#define KBD_RESERVED_BITS 0x0004
|
||||
#define KBD_OVERRIDE_KBD_LOCK 0x0008
|
||||
#define KBD_ENABLE_KBD_PORT 0x0000
|
||||
#define KBD_DISABLE_KBD_PORT 0x0010
|
||||
#define KBD_ENABLE_AUX_PORT 0x0000
|
||||
#define KBD_DISABLE_AUX_PORT 0x0020
|
||||
#define KBD_ENABLE_AUX_INT 0x0002
|
||||
#define KBD_DISABLE_AUX_INT 0x0000
|
||||
#define KBD_ENABLE_KBD_INT 0x0001
|
||||
#define KBD_DISABLE_KBD_INT 0x0000
|
||||
#define KBD_KBD_CONTROL_BITS (KBD_DISABLE_KBD_PORT | KBD_ENABLE_KBD_INT)
|
||||
#define KBD_AUX_CONTROL_BITS (KBD_DISABLE_AUX_PORT | KBD_ENABLE_AUX_INT)
|
||||
|
||||
/* keyboard device commands (sent to KBD_DATA_PORT) */
|
||||
#define KBDC_RESET_KBD 0x00ff
|
||||
#define KBDC_ENABLE_KBD 0x00f4
|
||||
#define KBDC_DISABLE_KBD 0x00f5
|
||||
#define KBDC_SET_DEFAULTS 0x00f6
|
||||
#define KBDC_SEND_DEV_ID 0x00f2
|
||||
#define KBDC_SET_LEDS 0x00ed
|
||||
#define KBDC_ECHO 0x00ee
|
||||
#define KBDC_SET_SCANCODE_SET 0x00f0
|
||||
#define KBDC_SET_TYPEMATIC 0x00f3
|
||||
|
||||
/* aux device commands (sent to KBD_DATA_PORT) */
|
||||
#define PSMC_RESET_DEV 0x00ff
|
||||
#define PSMC_ENABLE_DEV 0x00f4
|
||||
#define PSMC_DISABLE_DEV 0x00f5
|
||||
#define PSMC_SET_DEFAULTS 0x00f6
|
||||
#define PSMC_SEND_DEV_ID 0x00f2
|
||||
#define PSMC_SEND_DEV_STATUS 0x00e9
|
||||
#define PSMC_SEND_DEV_DATA 0x00eb
|
||||
#define PSMC_SET_SCALING11 0x00e6
|
||||
#define PSMC_SET_SCALING21 0x00e7
|
||||
#define PSMC_SET_RESOLUTION 0x00e8
|
||||
#define PSMC_SET_STREAM_MODE 0x00ea
|
||||
#define PSMC_SET_REMOTE_MODE 0x00f0
|
||||
#define PSMC_SET_SAMPLING_RATE 0x00f3
|
||||
|
||||
/* PSMC_SET_RESOLUTION argument */
|
||||
#define PSMD_RES_LOW 0 /* typically 25ppi */
|
||||
#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */
|
||||
#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */
|
||||
#define PSMD_RES_HIGH 3 /* typically 200ppi */
|
||||
#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH
|
||||
|
||||
/* PSMC_SET_SAMPLING_RATE */
|
||||
#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */
|
||||
|
||||
/* status bits (KBD_STATUS_PORT) */
|
||||
#define KBDS_BUFFER_FULL 0x0021
|
||||
#define KBDS_ANY_BUFFER_FULL 0x0001
|
||||
#define KBDS_KBD_BUFFER_FULL 0x0001
|
||||
#define KBDS_AUX_BUFFER_FULL 0x0021
|
||||
#define KBDS_INPUT_BUFFER_FULL 0x0002
|
||||
|
||||
/* return code */
|
||||
#define KBD_ACK 0x00fa
|
||||
#define KBD_RESEND 0x00fe
|
||||
#define KBD_RESET_DONE 0x00aa
|
||||
#define KBD_RESET_FAIL 0x00fc
|
||||
#define KBD_DIAG_DONE 0x0055
|
||||
#define KBD_DIAG_FAIL 0x00fd
|
||||
#define KBD_ECHO 0x00ee
|
||||
|
||||
#define PSM_ACK 0x00fa
|
||||
#define PSM_RESEND 0x00fe
|
||||
#define PSM_RESET_DONE 0x00aa
|
||||
#define PSM_RESET_FAIL 0x00fc
|
||||
|
||||
/* aux device ID */
|
||||
#define PSM_MOUSE_ID 0
|
||||
#define PSM_BALLPOINT_ID 2
|
||||
#define PSM_INTELLI_ID 3
|
||||
#define PSM_EXPLORER_ID 4
|
||||
#define PSM_4DMOUSE_ID 6
|
||||
#define PSM_4DPLUS_ID 8
|
||||
#define PSM_4DPLUS_RFSW35_ID 24
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#define ATKBDC_DRIVER_NAME "atkbdc"
|
||||
|
||||
/*
|
||||
* driver specific options: the following options may be set by
|
||||
* `options' statements in the kernel configuration file.
|
||||
*/
|
||||
|
||||
/* 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 20
|
||||
#define KBDD_DELAYTIME 7
|
||||
|
||||
/* debug option */
|
||||
#ifndef KBDIO_DEBUG
|
||||
#define KBDIO_DEBUG 0
|
||||
#endif
|
||||
|
||||
/* end of driver specific options */
|
||||
|
||||
/* types/structures */
|
||||
|
||||
#define KBDQ_BUFSIZE 32
|
||||
|
||||
typedef struct _kqueue {
|
||||
int head;
|
||||
int tail;
|
||||
unsigned char q[KBDQ_BUFSIZE];
|
||||
#if KBDIO_DEBUG >= 2
|
||||
int call_count;
|
||||
int qcount;
|
||||
int max_qcount;
|
||||
#endif
|
||||
} kqueue;
|
||||
|
||||
struct resource;
|
||||
|
||||
typedef struct atkbdc_softc {
|
||||
struct resource *port0; /* data port */
|
||||
struct resource *port1; /* status port */
|
||||
bus_space_tag_t iot;
|
||||
bus_space_handle_t ioh0;
|
||||
bus_space_handle_t ioh1;
|
||||
int command_byte; /* current command byte value */
|
||||
int command_mask; /* command byte mask bits for kbd/aux devices */
|
||||
int lock; /* FIXME: XXX not quite a semaphore... */
|
||||
kqueue kbd; /* keyboard data queue */
|
||||
kqueue aux; /* auxiliary data queue */
|
||||
} atkbdc_softc_t;
|
||||
|
||||
enum kbdc_device_ivar {
|
||||
KBDC_IVAR_VENDORID,
|
||||
KBDC_IVAR_SERIAL,
|
||||
KBDC_IVAR_LOGICALID,
|
||||
KBDC_IVAR_COMPATID,
|
||||
};
|
||||
|
||||
typedef caddr_t KBDC;
|
||||
|
||||
#define KBDC_RID_KBD 0
|
||||
#define KBDC_RID_AUX 1
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
atkbdc_softc_t *atkbdc_get_softc(int unit);
|
||||
int atkbdc_probe_unit(int unit, struct resource *port0, struct resource *port1);
|
||||
int atkbdc_attach_unit(int unit, atkbdc_softc_t *sc, struct resource *port0,
|
||||
struct resource *port1);
|
||||
int atkbdc_configure(void);
|
||||
|
||||
KBDC atkbdc_open(int unit);
|
||||
int kbdc_lock(KBDC kbdc, int lock);
|
||||
int kbdc_data_ready(KBDC kbdc);
|
||||
|
||||
int write_controller_command(KBDC kbdc,int c);
|
||||
int write_controller_data(KBDC kbdc,int c);
|
||||
|
||||
int write_kbd_command(KBDC kbdc,int c);
|
||||
int write_aux_command(KBDC kbdc,int c);
|
||||
int send_kbd_command(KBDC kbdc,int c);
|
||||
int send_aux_command(KBDC kbdc,int c);
|
||||
int send_kbd_command_and_data(KBDC kbdc,int c,int d);
|
||||
int send_aux_command_and_data(KBDC kbdc,int c,int d);
|
||||
|
||||
int read_controller_data(KBDC kbdc);
|
||||
int read_kbd_data(KBDC kbdc);
|
||||
int read_kbd_data_no_wait(KBDC kbdc);
|
||||
int read_aux_data(KBDC kbdc);
|
||||
int read_aux_data_no_wait(KBDC kbdc);
|
||||
|
||||
void empty_kbd_buffer(KBDC kbdc, int t);
|
||||
void empty_aux_buffer(KBDC kbdc, int t);
|
||||
void empty_both_buffers(KBDC kbdc, int t);
|
||||
|
||||
int reset_kbd(KBDC kbdc);
|
||||
int reset_aux_dev(KBDC kbdc);
|
||||
|
||||
int test_controller(KBDC kbdc);
|
||||
int test_kbd_port(KBDC kbdc);
|
||||
int test_aux_port(KBDC kbdc);
|
||||
|
||||
int kbdc_get_device_mask(KBDC kbdc);
|
||||
void kbdc_set_device_mask(KBDC kbdc, int mask);
|
||||
|
||||
int get_controller_command_byte(KBDC kbdc);
|
||||
int set_controller_command_byte(KBDC kbdc, int command, int flag);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_DEV_KBD_ATKBDCREG_H_ */
|
|
@ -79,7 +79,7 @@
|
|||
#include <machine/stdarg.h>
|
||||
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
#include <dev/atkbdc/atkbdcreg.h>
|
||||
|
||||
#include <i386/isa/pcvt/pcvt_conf.h>
|
||||
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$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 <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <sys/kbio.h>
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
#include <dev/kbd/atkbdreg.h>
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
typedef struct {
|
||||
struct resource *intr;
|
||||
void *ih;
|
||||
} atkbd_softc_t;
|
||||
|
||||
static devclass_t atkbd_devclass;
|
||||
|
||||
static void atkbdidentify(driver_t *driver, device_t dev);
|
||||
static int atkbdprobe(device_t dev);
|
||||
static int atkbdattach(device_t dev);
|
||||
static int atkbdresume(device_t dev);
|
||||
static void atkbd_isa_intr(void *arg);
|
||||
|
||||
static device_method_t atkbd_methods[] = {
|
||||
DEVMETHOD(device_identify, atkbdidentify),
|
||||
DEVMETHOD(device_probe, atkbdprobe),
|
||||
DEVMETHOD(device_attach, atkbdattach),
|
||||
DEVMETHOD(device_resume, atkbdresume),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t atkbd_driver = {
|
||||
ATKBD_DRIVER_NAME,
|
||||
atkbd_methods,
|
||||
sizeof(atkbd_softc_t),
|
||||
};
|
||||
|
||||
static void
|
||||
atkbdidentify(driver_t *driver, device_t parent)
|
||||
{
|
||||
|
||||
/* always add at least one child */
|
||||
BUS_ADD_CHILD(parent, KBDC_RID_KBD, driver->name, device_get_unit(parent));
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdprobe(device_t dev)
|
||||
{
|
||||
struct resource *res;
|
||||
u_long irq;
|
||||
int flags;
|
||||
int rid;
|
||||
|
||||
device_set_desc(dev, "AT Keyboard");
|
||||
|
||||
/* obtain parameters */
|
||||
flags = device_get_flags(dev);
|
||||
|
||||
/* see if IRQ is available */
|
||||
rid = KBDC_RID_KBD;
|
||||
res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
if (bootverbose)
|
||||
device_printf(dev, "unable to allocate IRQ\n");
|
||||
return ENXIO;
|
||||
}
|
||||
irq = rman_get_start(res);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, rid, res);
|
||||
|
||||
/* probe the device */
|
||||
return atkbd_probe_unit(device_get_unit(dev),
|
||||
device_get_unit(device_get_parent(dev)),
|
||||
irq, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdattach(device_t dev)
|
||||
{
|
||||
atkbd_softc_t *sc;
|
||||
keyboard_t *kbd;
|
||||
u_long irq;
|
||||
int flags;
|
||||
int rid;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
rid = KBDC_RID_KBD;
|
||||
irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid);
|
||||
flags = device_get_flags(dev);
|
||||
error = atkbd_attach_unit(device_get_unit(dev), &kbd,
|
||||
device_get_unit(device_get_parent(dev)),
|
||||
irq, flags);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* declare our interrupt handler */
|
||||
sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
if (sc->intr == NULL)
|
||||
return ENXIO;
|
||||
error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, atkbd_isa_intr,
|
||||
kbd, &sc->ih);
|
||||
if (error)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdresume(device_t dev)
|
||||
{
|
||||
atkbd_softc_t *sc;
|
||||
keyboard_t *kbd;
|
||||
int args[2];
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
kbd = kbd_get_keyboard(kbd_find_keyboard(ATKBD_DRIVER_NAME,
|
||||
device_get_unit(dev)));
|
||||
if (kbd) {
|
||||
kbd->kb_flags &= ~KB_INITIALIZED;
|
||||
args[0] = device_get_unit(device_get_parent(dev));
|
||||
args[1] = rman_get_start(sc->intr);
|
||||
(*kbdsw[kbd->kb_index]->init)(device_get_unit(dev), &kbd,
|
||||
args, device_get_flags(dev));
|
||||
(*kbdsw[kbd->kb_index]->clear_state)(kbd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
atkbd_isa_intr(void *arg)
|
||||
{
|
||||
keyboard_t *kbd;
|
||||
|
||||
kbd = (keyboard_t *)arg;
|
||||
(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
|
||||
}
|
||||
|
||||
DRIVER_MODULE(atkbd, atkbdc, atkbd_driver, atkbd_devclass, 0, 0);
|
|
@ -1,365 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$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 <sys/malloc.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/kbd/atkbdcreg.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
static MALLOC_DEFINE(M_ATKBDDEV, "atkbddev", "AT Keyboard device");
|
||||
|
||||
/* children */
|
||||
typedef struct atkbdc_device {
|
||||
struct resource_list resources;
|
||||
int rid;
|
||||
u_int32_t vendorid;
|
||||
u_int32_t serial;
|
||||
u_int32_t logicalid;
|
||||
u_int32_t compatid;
|
||||
} atkbdc_device_t;
|
||||
|
||||
/* kbdc */
|
||||
static devclass_t atkbdc_devclass;
|
||||
|
||||
static int atkbdc_probe(device_t dev);
|
||||
static int atkbdc_attach(device_t dev);
|
||||
static device_t atkbdc_add_child(device_t bus, int order, char *name,
|
||||
int unit);
|
||||
static int atkbdc_print_child(device_t bus, device_t dev);
|
||||
static int atkbdc_read_ivar(device_t bus, device_t dev, int index,
|
||||
uintptr_t *val);
|
||||
static int atkbdc_write_ivar(device_t bus, device_t dev, int index,
|
||||
uintptr_t val);
|
||||
static struct resource_list
|
||||
*atkbdc_get_resource_list (device_t bus, device_t dev);
|
||||
static struct resource
|
||||
*atkbdc_alloc_resource(device_t bus, device_t dev, int type,
|
||||
int *rid, u_long start, u_long end,
|
||||
u_long count, u_int flags);
|
||||
static int atkbdc_release_resource(device_t bus, device_t dev, int type,
|
||||
int rid, struct resource *res);
|
||||
|
||||
static device_method_t atkbdc_methods[] = {
|
||||
DEVMETHOD(device_probe, atkbdc_probe),
|
||||
DEVMETHOD(device_attach, atkbdc_attach),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
DEVMETHOD(bus_add_child, atkbdc_add_child),
|
||||
DEVMETHOD(bus_print_child, atkbdc_print_child),
|
||||
DEVMETHOD(bus_read_ivar, atkbdc_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, atkbdc_write_ivar),
|
||||
DEVMETHOD(bus_get_resource_list,atkbdc_get_resource_list),
|
||||
DEVMETHOD(bus_alloc_resource, atkbdc_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, atkbdc_release_resource),
|
||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
|
||||
DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t atkbdc_driver = {
|
||||
ATKBDC_DRIVER_NAME,
|
||||
atkbdc_methods,
|
||||
sizeof(atkbdc_softc_t *),
|
||||
};
|
||||
|
||||
static struct isa_pnp_id atkbdc_ids[] = {
|
||||
{ 0x0303d041, "Keyboard controller (i8042)" }, /* PNP0303 */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
atkbdc_probe(device_t dev)
|
||||
{
|
||||
struct resource *port0;
|
||||
struct resource *port1;
|
||||
u_long start;
|
||||
u_long count;
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
/* check PnP IDs */
|
||||
if (ISA_PNP_PROBE(device_get_parent(dev), dev, atkbdc_ids) == ENXIO)
|
||||
return ENXIO;
|
||||
|
||||
device_set_desc(dev, "Keyboard controller (i8042)");
|
||||
|
||||
/*
|
||||
* Adjust I/O port resources.
|
||||
* The AT keyboard controller uses two ports (a command/data port
|
||||
* 0x60 and a status port 0x64), which may be given to us in
|
||||
* one resource (0x60 through 0x64) or as two separate resources
|
||||
* (0x60 and 0x64). Furthermore, /boot/device.hints may contain
|
||||
* just one port, 0x60. We shall adjust resource settings
|
||||
* so that these two ports are available as two separate resources.
|
||||
*/
|
||||
device_quiet(dev);
|
||||
rid = 0;
|
||||
if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count) != 0)
|
||||
return ENXIO;
|
||||
if (count > 1) /* adjust the count */
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, rid, start, 1);
|
||||
port0 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
|
||||
if (port0 == NULL)
|
||||
return ENXIO;
|
||||
rid = 1;
|
||||
if (bus_get_resource(dev, SYS_RES_IOPORT, rid, NULL, NULL) != 0)
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, 1,
|
||||
start + KBD_STATUS_PORT, 1);
|
||||
port1 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
|
||||
if (port1 == NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
|
||||
return ENXIO;
|
||||
}
|
||||
device_verbose(dev);
|
||||
|
||||
error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
|
||||
if (error == 0)
|
||||
bus_generic_probe(dev);
|
||||
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_attach(device_t dev)
|
||||
{
|
||||
atkbdc_softc_t *sc;
|
||||
int unit;
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
unit = device_get_unit(dev);
|
||||
sc = *(atkbdc_softc_t **)device_get_softc(dev);
|
||||
if (sc == NULL) {
|
||||
/*
|
||||
* We have to maintain two copies of the kbdc_softc struct,
|
||||
* as the low-level console needs to have access to the
|
||||
* keyboard controller before kbdc is probed and attached.
|
||||
* kbdc_soft[] contains the default entry for that purpose.
|
||||
* See atkbdc.c. XXX
|
||||
*/
|
||||
sc = atkbdc_get_softc(unit);
|
||||
if (sc == NULL)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
rid = 0;
|
||||
sc->port0 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->port0 == NULL)
|
||||
return ENXIO;
|
||||
rid = 1;
|
||||
sc->port1 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->port1 == NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1);
|
||||
if (error) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->port1);
|
||||
return error;
|
||||
}
|
||||
*(atkbdc_softc_t **)device_get_softc(dev) = sc;
|
||||
|
||||
bus_generic_attach(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static device_t
|
||||
atkbdc_add_child(device_t bus, int order, char *name, int unit)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
device_t child;
|
||||
int t;
|
||||
|
||||
ivar = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (!ivar)
|
||||
return NULL;
|
||||
|
||||
child = device_add_child_ordered(bus, order, name, unit);
|
||||
if (child == NULL) {
|
||||
free(ivar, M_ATKBDDEV);
|
||||
return child;
|
||||
}
|
||||
|
||||
resource_list_init(&ivar->resources);
|
||||
ivar->rid = order;
|
||||
|
||||
/*
|
||||
* If the device is not created by the PnP BIOS or ACPI,
|
||||
* refer to device hints for IRQ.
|
||||
*/
|
||||
if (ISA_PNP_PROBE(device_get_parent(bus), bus, atkbdc_ids) != 0) {
|
||||
if (resource_int_value(name, unit, "irq", &t) != 0)
|
||||
t = -1;
|
||||
} else {
|
||||
t = bus_get_resource_start(bus, SYS_RES_IRQ, ivar->rid);
|
||||
}
|
||||
if (t > 0)
|
||||
resource_list_add(&ivar->resources, SYS_RES_IRQ, ivar->rid,
|
||||
t, t, 1);
|
||||
|
||||
if (resource_disabled(name, unit))
|
||||
device_disable(child);
|
||||
|
||||
device_set_ivars(child, ivar);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_print_child(device_t bus, device_t dev)
|
||||
{
|
||||
atkbdc_device_t *kbdcdev;
|
||||
u_long irq;
|
||||
int flags;
|
||||
int retval = 0;
|
||||
|
||||
kbdcdev = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
|
||||
retval += bus_print_child_header(bus, dev);
|
||||
flags = device_get_flags(dev);
|
||||
if (flags != 0)
|
||||
retval += printf(" flags 0x%x", flags);
|
||||
irq = bus_get_resource_start(dev, SYS_RES_IRQ, kbdcdev->rid);
|
||||
if (irq != 0)
|
||||
retval += printf(" irq %ld", irq);
|
||||
retval += bus_print_child_footer(bus, dev);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
switch (index) {
|
||||
case KBDC_IVAR_VENDORID:
|
||||
*val = (u_long)ivar->vendorid;
|
||||
break;
|
||||
case KBDC_IVAR_SERIAL:
|
||||
*val = (u_long)ivar->serial;
|
||||
break;
|
||||
case KBDC_IVAR_LOGICALID:
|
||||
*val = (u_long)ivar->logicalid;
|
||||
break;
|
||||
case KBDC_IVAR_COMPATID:
|
||||
*val = (u_long)ivar->compatid;
|
||||
break;
|
||||
default:
|
||||
return ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
switch (index) {
|
||||
case KBDC_IVAR_VENDORID:
|
||||
ivar->vendorid = (u_int32_t)val;
|
||||
break;
|
||||
case KBDC_IVAR_SERIAL:
|
||||
ivar->serial = (u_int32_t)val;
|
||||
break;
|
||||
case KBDC_IVAR_LOGICALID:
|
||||
ivar->logicalid = (u_int32_t)val;
|
||||
break;
|
||||
case KBDC_IVAR_COMPATID:
|
||||
ivar->compatid = (u_int32_t)val;
|
||||
break;
|
||||
default:
|
||||
return ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource_list
|
||||
*atkbdc_get_resource_list (device_t bus, device_t dev)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return &ivar->resources;
|
||||
}
|
||||
|
||||
static struct resource
|
||||
*atkbdc_alloc_resource(device_t bus, device_t dev, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return resource_list_alloc(&ivar->resources, bus, dev, type, rid,
|
||||
start, end, count, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
atkbdc_release_resource(device_t bus, device_t dev, int type, int rid,
|
||||
struct resource *res)
|
||||
{
|
||||
atkbdc_device_t *ivar;
|
||||
|
||||
ivar = (atkbdc_device_t *)device_get_ivars(dev);
|
||||
return resource_list_release(&ivar->resources, bus, dev, type, rid,
|
||||
res);
|
||||
}
|
||||
|
||||
DRIVER_MODULE(atkbdc, isa, atkbdc_driver, atkbdc_devclass, 0, 0);
|
||||
DRIVER_MODULE(atkbdc, acpi, atkbdc_driver, atkbdc_devclass, 0, 0);
|
3658
sys/isa/psm.c
3658
sys/isa/psm.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue