The SMC is represented on the acpi tables, so we can completely remove

dependency on isa. We are now an acpi child.

Also:
	* Add compile time debugging activation
	* Increase the delay for the SMS init flag.
This commit is contained in:
Rui Paulo 2008-04-07 11:22:12 +00:00
parent e0c098c888
commit 4470f0f388
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=177972
2 changed files with 84 additions and 56 deletions

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2007 Rui Paulo <rpaulo@FreeBSD.org>
* Copyright (c) 2007, 2008 Rui Paulo <rpaulo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -48,17 +48,15 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
#include <isa/isavar.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <contrib/dev/acpica/acpi.h>
#include <dev/acpica/acpivar.h>
#include <dev/asmc/asmcvar.h>
/*
* Device interface.
*/
static void asmc_identify(driver_t *driver, device_t parent);
static int asmc_probe(device_t dev);
static int asmc_attach(device_t dev);
static int asmc_detach(device_t dev);
@ -201,7 +199,6 @@ struct asmc_model asmc_models[] = {
* Driver methods.
*/
static device_method_t asmc_methods[] = {
DEVMETHOD(device_identify, asmc_identify),
DEVMETHOD(device_probe, asmc_probe),
DEVMETHOD(device_attach, asmc_attach),
DEVMETHOD(device_detach, asmc_detach),
@ -215,17 +212,21 @@ static driver_t asmc_driver = {
sizeof(struct asmc_softc)
};
/*
* Debugging
*/
#define _COMPONENT ACPI_OEM
ACPI_MODULE_NAME("ASMC")
#ifdef DEBUG
#define ASMC_DPRINTF(str) device_printf(dev, str)
#endif
static char *asmc_ids[] = { "APP0001", NULL };
static devclass_t asmc_devclass;
DRIVER_MODULE(asmc, isa, asmc_driver, asmc_devclass, NULL, NULL);
static void
asmc_identify(driver_t *driver, device_t parent)
{
if (device_find_child(parent, "asmc", -1) == NULL &&
asmc_match(parent))
BUS_ADD_CHILD(parent, 0, "asmc", -1);
}
DRIVER_MODULE(asmc, acpi, asmc_driver, asmc_devclass, NULL, NULL);
MODULE_DEPEND(asmc, acpi, 1, 1, 1);
static struct asmc_model *
asmc_match(device_t dev)
@ -250,13 +251,16 @@ asmc_probe(device_t dev)
{
struct asmc_model *model;
if (resource_disabled("asmc", 0))
if (acpi_disabled("asmc"))
return (ENXIO);
if (ACPI_ID_PROBE(device_get_parent(dev), dev, asmc_ids) == NULL)
return (ENXIO);
model = asmc_match(dev);
if (!model)
if (!model) {
device_printf(dev, "model not recognized\n");
return (ENXIO);
if (isa_get_irq(dev) == -1)
bus_set_resource(dev, SYS_RES_IRQ, 0, ASMC_IRQ, 1);
}
device_set_desc(dev, model->smc_desc);
return (BUS_PROBE_DEFAULT);
@ -273,6 +277,13 @@ asmc_attach(device_t dev)
struct sysctl_oid *sysctlnode;
struct asmc_model *model;
sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
&sc->sc_rid_port, RF_ACTIVE);
if (sc->sc_ioport == NULL) {
device_printf(dev, "unable to allocate IO port\n");
return (ENOMEM);
}
sysctlctx = device_get_sysctl_ctx(dev);
sysctlnode = device_get_sysctl_tree(dev);
@ -420,16 +431,16 @@ asmc_attach(device_t dev)
/*
* Allocate an IRQ for the SMS.
*/
sc->sc_rid = 0;
sc->sc_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid,
ASMC_IRQ, ASMC_IRQ, 1, RF_ACTIVE);
if (sc->sc_res == NULL) {
sc->sc_rid_irq = 0;
sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->sc_rid_irq, RF_ACTIVE);
if (sc->sc_irq == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
ret = ENXIO;
goto err2;
}
ret = bus_setup_intr(dev, sc->sc_res,
ret = bus_setup_intr(dev, sc->sc_irq,
INTR_TYPE_MISC | INTR_MPSAFE,
#ifdef INTR_FILTER
asmc_sms_intrfast, asmc_sms_handler,
@ -445,8 +456,10 @@ asmc_attach(device_t dev)
nosms:
return (0);
err1:
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_res);
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, sc->sc_irq);
err2:
bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port,
sc->sc_ioport);
mtx_destroy(&sc->sc_mtx);
if (sc->sc_sms_tq)
taskqueue_free(sc->sc_sms_tq);
@ -464,9 +477,13 @@ asmc_detach(device_t dev)
taskqueue_free(sc->sc_sms_tq);
}
if (sc->sc_cookie)
bus_teardown_intr(dev, sc->sc_res, sc->sc_cookie);
if (sc->sc_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_res);
bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie);
if (sc->sc_irq)
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq,
sc->sc_irq);
if (sc->sc_ioport)
bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port,
sc->sc_ioport);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -486,6 +503,7 @@ asmc_init(device_t dev)
* We are ready to recieve interrupts from the SMS.
*/
buf[0] = 0x01;
ASMC_DPRINTF(("intok key\n"));
asmc_key_write(dev, ASMC_KEY_INTOK, buf, 1);
DELAY(50);
@ -493,20 +511,24 @@ asmc_init(device_t dev)
* Initiate the polling intervals.
*/
buf[0] = 20; /* msecs */
ASMC_DPRINTF(("low int key\n"));
asmc_key_write(dev, ASMC_KEY_SMS_LOW_INT, buf, 1);
DELAY(200);
buf[0] = 20; /* msecs */
ASMC_DPRINTF(("high int key\n"));
asmc_key_write(dev, ASMC_KEY_SMS_HIGH_INT, buf, 1);
DELAY(200);
buf[0] = 0x00;
buf[1] = 0x60;
ASMC_DPRINTF(("sms low key\n"));
asmc_key_write(dev, ASMC_KEY_SMS_LOW, buf, 2);
DELAY(200);
buf[0] = 0x01;
buf[1] = 0xc0;
ASMC_DPRINTF(("sms high key\n"));
asmc_key_write(dev, ASMC_KEY_SMS_HIGH, buf, 2);
DELAY(200);
@ -515,8 +537,9 @@ asmc_init(device_t dev)
* required.
*/
buf[0] = 0x01;
ASMC_DPRINTF(("sms flag key\n"));
asmc_key_write(dev, ASMC_KEY_SMS_FLAG, buf, 1);
DELAY(50);
DELAY(200);
/*
* Wait up to 5 seconds for SMS initialization.
@ -525,11 +548,14 @@ asmc_init(device_t dev)
if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 &&
(buf[0] != 0x00 || buf[1] != 0x00)) {
error = 0;
device_printf(dev, "WARNING: Sudden Motion Sensor "
"not initialized!\n");
goto nosms;
}
buf[0] = ASMC_SMS_INIT1;
buf[1] = ASMC_SMS_INIT2;
ASMC_DPRINTF(("sms key\n"));
asmc_key_write(dev, ASMC_KEY_SMS, buf, 2);
DELAY(50);
}
@ -562,18 +588,19 @@ asmc_init(device_t dev)
static int
asmc_wait(device_t dev, uint8_t val)
{
struct asmc_softc *sc = device_get_softc(dev);
u_int i;
val = val & ASMC_STATUS_MASK;
for (i = 0; i < 1000; i++) {
if ((inb(ASMC_CMDPORT) & ASMC_STATUS_MASK) == val)
if ((ASMC_CMDPORT_READ(sc) & ASMC_STATUS_MASK) == val)
return (0);
DELAY(10);
}
device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, val,
inb(ASMC_CMDPORT));
ASMC_CMDPORT_READ(sc));
return (1);
}
@ -586,22 +613,22 @@ asmc_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len)
mtx_lock_spin(&sc->sc_mtx);
outb(ASMC_CMDPORT, ASMC_CMDREAD);
ASMC_CMDPORT_WRITE(sc, ASMC_CMDREAD);
if (asmc_wait(dev, 0x0c))
goto out;
for (i = 0; i < 4; i++) {
outb(ASMC_DATAPORT, key[i]);
ASMC_DATAPORT_WRITE(sc, key[i]);
if (asmc_wait(dev, 0x04))
goto out;
}
outb(ASMC_DATAPORT, len);
ASMC_DATAPORT_WRITE(sc, len);
for (i = 0; i < len; i++) {
if (asmc_wait(dev, 0x05))
goto out;
buf[i] = inb(ASMC_DATAPORT);
buf[i] = ASMC_DATAPORT_READ(sc);
}
error = 0;
@ -619,22 +646,25 @@ asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len)
mtx_lock_spin(&sc->sc_mtx);
outb(ASMC_CMDPORT, ASMC_CMDWRITE);
ASMC_DPRINTF(("cmd port: cmd write\n"));
ASMC_CMDPORT_WRITE(sc, ASMC_CMDWRITE);
if (asmc_wait(dev, 0x0c))
goto out;
ASMC_DPRINTF(("data port: key\n"));
for (i = 0; i < 4; i++) {
outb(ASMC_DATAPORT, key[i]);
ASMC_DATAPORT_WRITE(sc, key[i]);
if (asmc_wait(dev, 0x04))
goto out;
}
ASMC_DPRINTF(("data port: length\n"));
ASMC_DATAPORT_WRITE(sc, len);
outb(ASMC_DATAPORT, len);
ASMC_DPRINTF(("data port: buffer\n"));
for (i = 0; i < len; i++) {
if (asmc_wait(dev, 0x04))
goto out;
outb(ASMC_DATAPORT, buf[i]);
ASMC_DATAPORT_WRITE(sc, buf[i]);
}
error = 0;
@ -820,7 +850,7 @@ asmc_sms_intrfast(void *arg)
struct asmc_softc *sc = device_get_softc(dev);
mtx_lock_spin(&sc->sc_mtx);
type = inb(ASMC_INTPORT);
type = ASMC_INTPORT_READ(sc);
mtx_unlock_spin(&sc->sc_mtx);
sc->sc_sms_intrtype = type;
@ -886,7 +916,7 @@ asmc_sms_task(void *arg, int pending)
}
snprintf(notify, sizeof(notify), " notify=0x%x", type);
devctl_notify("ISA", "asmc", "SMS", notify);
devctl_notify("ACPI", "asmc", "SMS", notify);
}
static int

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2007 Rui Paulo <rpaulo@FreeBSD.org>
* Copyright (c) 2007, 2008 Rui Paulo <rpaulo@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -41,39 +41,37 @@ struct asmc_softc {
struct sysctl_oid *sc_sms_tree;
struct sysctl_oid *sc_light_tree;
struct asmc_model *sc_model;
int sc_rid;
struct resource *sc_res;
int sc_rid_port;
int sc_rid_irq;
struct resource *sc_ioport;
struct resource *sc_irq;
void *sc_cookie;
int sc_sms_intrtype;
struct taskqueue *sc_sms_tq;
struct task sc_sms_task;
};
/*
* The Sudden Motion Sensor is able to generate an interrupt when
* there are certain critical conditions (free fall, high acceleration and
* shocks).
* The following IRQ is used.
*/
#define ASMC_IRQ 6
/*
* Data port.
*/
#define ASMC_DATAPORT 0x300
#define ASMC_DATAPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x00)
#define ASMC_DATAPORT_WRITE(sc, val) \
bus_write_1(sc->sc_ioport, 0, val)
#define ASMC_STATUS_MASK 0x0f
/*
* Command port.
*/
#define ASMC_CMDPORT 0x304
#define ASMC_CMDPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x04)
#define ASMC_CMDPORT_WRITE(sc, val) \
bus_write_1(sc->sc_ioport, 4, val)
#define ASMC_CMDREAD 0x10
#define ASMC_CMDWRITE 0x11
/*
* Interrupt port.
*/
#define ASMC_INTPORT 0x31f
#define ASMC_INTPORT_READ(sc) bus_read_1(sc->sc_ioport, 0x1f)
/* Number of keys */