Improvements in tpm(4):
- Remove interrupt support, do polling only, avoids unnecessary trouble. - Simplify a few things. - Fix the suspend function, the SaveState command is 0x98, not 0x9C. - Make the driver MP-safe. - Sync the man page with reality.
This commit is contained in:
parent
f3a317a980
commit
066833e6eb
|
@ -1,20 +1,33 @@
|
|||
.\" $NetBSD: tpm.4,v 1.4 2018/02/22 01:40:49 pgoyette Exp $
|
||||
.\" $NetBSD: tpm.4,v 1.5 2019/10/08 18:43:03 maxv Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2010 Hans-Jörg Höxer, <Hans-Joerg.Hoexer@genua.de>
|
||||
.\" Copyright (c) 2019 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
.\" by Maxime Villard.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\" 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.
|
||||
.\"
|
||||
.Dd February 22, 2018
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
.\"
|
||||
.Dd October 6, 2019
|
||||
.Dt TPM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -22,40 +35,22 @@
|
|||
.Nd Trusted Platform Module
|
||||
.Sh SYNOPSIS
|
||||
.Cd "tpm* at isa? iomem 0xfed40000"
|
||||
.Cd "tpm* at isa? iomem 0xfed40000 irq 7"
|
||||
.Cd "tpm* at acpi?"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for various trusted platform modules (TPM) that can
|
||||
store cryptographic keys.
|
||||
driver provides support for various Trusted Platform Module (TPM) chips.
|
||||
.Pp
|
||||
Supported modules:
|
||||
.Pp
|
||||
.Bl -bullet -compact -offset indent
|
||||
.It
|
||||
Atmel 97SC3203
|
||||
TPM 2.0 chips over ACPI
|
||||
.It
|
||||
Broadcom BCM0102
|
||||
.It
|
||||
Infineon IFX SLD 9630 TT 1.1 and IFX SLB 9635 TT 1.2
|
||||
.It
|
||||
Intel INTC0102
|
||||
.It
|
||||
Sinosun SNS SSX35
|
||||
.It
|
||||
STM ST19WP18
|
||||
.It
|
||||
Winbond WEC WPCT200
|
||||
TPM 1.2 chips over ISA
|
||||
.El
|
||||
.Pp
|
||||
The driver can be configured to use an IRQ by providing a free ISA
|
||||
interrupt vector using the keyword
|
||||
.Em irq
|
||||
in the kernel configuration file or using
|
||||
.Xr config 1 .
|
||||
If not IRQ is specified, the driver uses polling.
|
||||
This is the default configuration.
|
||||
Note that the supported interface version is TIS1.2 in each case.
|
||||
.Sh SEE ALSO
|
||||
.Xr config 1 ,
|
||||
.Xr intro 4
|
||||
|
@ -64,6 +59,7 @@ This is the default configuration.
|
|||
The
|
||||
.Nm
|
||||
driver was written by
|
||||
.An Maxime Villard ,
|
||||
.An Michael Shalayeff
|
||||
and
|
||||
.An Hans-Joerg Hoexer .
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $ */
|
||||
/* $NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, 2019 The NetBSD Foundation, Inc.
|
||||
|
@ -30,10 +30,9 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.9 2019/10/08 18:43:02 maxv Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/bus.h>
|
||||
|
@ -45,8 +44,6 @@ __KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.8 2019/06/22 12:57:40 maxv Exp $");
|
|||
#include <dev/acpi/acpireg.h>
|
||||
#include <dev/acpi/acpivar.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
#include "ioconf.h"
|
||||
|
||||
#define _COMPONENT ACPI_RESOURCE_COMPONENT
|
||||
|
@ -100,41 +97,41 @@ tpm_acpi_attach(device_t parent, device_t self, void *aux)
|
|||
struct acpi_attach_args *aa = aux;
|
||||
struct acpi_resources res;
|
||||
struct acpi_mem *mem;
|
||||
struct acpi_irq *irq;
|
||||
bus_addr_t base;
|
||||
bus_addr_t size;
|
||||
int rv, inum;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_ver = TPM_2_0;
|
||||
int rv;
|
||||
|
||||
rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", &res,
|
||||
&acpi_resource_parse_ops_default);
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
aprint_error_dev(sc->sc_dev, "cannot parse resources %d\n", rv);
|
||||
aprint_error_dev(self, "cannot parse resources %d\n", rv);
|
||||
return;
|
||||
}
|
||||
|
||||
mem = acpi_res_mem(&res, 0);
|
||||
if (mem == NULL) {
|
||||
aprint_error_dev(sc->sc_dev, "cannot find mem\n");
|
||||
aprint_error_dev(self, "cannot find mem\n");
|
||||
goto out;
|
||||
}
|
||||
if (mem->ar_length != TPM_SPACE_SIZE) {
|
||||
aprint_error_dev(sc->sc_dev,
|
||||
"wrong size mem %"PRIu64" != %u\n",
|
||||
aprint_error_dev(self, "wrong size mem %"PRIu64" != %u\n",
|
||||
(uint64_t)mem->ar_length, TPM_SPACE_SIZE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
base = mem->ar_base;
|
||||
size = mem->ar_length;
|
||||
sc->sc_bt = aa->aa_memt;
|
||||
sc->sc_dev = self;
|
||||
sc->sc_ver = TPM_2_0;
|
||||
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
sc->sc_busy = false;
|
||||
sc->sc_init = tpm_tis12_init;
|
||||
sc->sc_start = tpm_tis12_start;
|
||||
sc->sc_read = tpm_tis12_read;
|
||||
sc->sc_write = tpm_tis12_write;
|
||||
sc->sc_end = tpm_tis12_end;
|
||||
sc->sc_bt = aa->aa_memt;
|
||||
|
||||
base = mem->ar_base;
|
||||
size = mem->ar_length;
|
||||
|
||||
if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) {
|
||||
aprint_error_dev(sc->sc_dev, "cannot map registers\n");
|
||||
|
@ -146,24 +143,11 @@ tpm_acpi_attach(device_t parent, device_t self, void *aux)
|
|||
goto out1;
|
||||
}
|
||||
|
||||
irq = acpi_res_irq(&res, 0);
|
||||
if (irq == NULL)
|
||||
inum = -1;
|
||||
else
|
||||
inum = irq->ar_irq;
|
||||
|
||||
if ((rv = (*sc->sc_init)(sc, inum)) != 0) {
|
||||
if ((*sc->sc_init)(sc) != 0) {
|
||||
aprint_error_dev(sc->sc_dev, "cannot init device %d\n", rv);
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (inum != -1 &&
|
||||
(sc->sc_ih = isa_intr_establish(aa->aa_ic, irq->ar_irq,
|
||||
IST_EDGE, IPL_TTY, tpm_intr, sc)) == NULL) {
|
||||
aprint_error_dev(sc->sc_dev, "cannot establish interrupt\n");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
acpi_resource_cleanup(&res);
|
||||
return;
|
||||
|
||||
|
|
350
sys/dev/ic/tpm.c
350
sys/dev/ic/tpm.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $ */
|
||||
/* $NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 The NetBSD Foundation, Inc.
|
||||
|
@ -48,7 +48,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.14 2019/10/08 18:43:02 maxv Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -67,6 +67,7 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $");
|
|||
|
||||
#define TPM_BUFSIZ 1024
|
||||
#define TPM_HDRSIZE 10
|
||||
|
||||
#define TPM_PARAM_SIZE 0x0001 /* that's a flag */
|
||||
|
||||
/* Timeouts. */
|
||||
|
@ -79,23 +80,6 @@ __KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13 2019/06/22 12:57:41 maxv Exp $");
|
|||
(TPM_INTF_DATA_AVAIL_INT|TPM_INTF_LOCALITY_CHANGE_INT| \
|
||||
TPM_INTF_INT_LEVEL_LOW)
|
||||
|
||||
static const struct {
|
||||
uint32_t devid;
|
||||
const char *name;
|
||||
int flags;
|
||||
#define TPM_DEV_NOINTS 0x0001
|
||||
} tpm_devs[] = {
|
||||
{ 0x000615d1, "IFX SLD 9630 TT 1.1", 0 },
|
||||
{ 0x000b15d1, "IFX SLB 9635 TT 1.2", 0 },
|
||||
{ 0x100214e4, "Broadcom BCM0102", TPM_DEV_NOINTS },
|
||||
{ 0x00fe1050, "WEC WPCT200", 0 },
|
||||
{ 0x687119fa, "SNS SSX35", 0 },
|
||||
{ 0x2e4d5453, "STM ST19WP18", 0 },
|
||||
{ 0x32021114, "ATML 97SC3203", TPM_DEV_NOINTS },
|
||||
{ 0x10408086, "INTEL INTC0102", 0 },
|
||||
{ 0, "", TPM_DEV_NOINTS },
|
||||
};
|
||||
|
||||
static inline int
|
||||
tpm_tmotohz(int tmo)
|
||||
{
|
||||
|
@ -129,7 +113,7 @@ tpm_request_locality(struct tpm_softc *sc, int l)
|
|||
while ((r = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_ACCESS) &
|
||||
(TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) !=
|
||||
(TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY) && to--) {
|
||||
rv = tsleep(sc->sc_init, PRIBIO | PCATCH, "tpm_locality", 1);
|
||||
rv = tsleep(sc->sc_init, PCATCH, "tpm_locality", 1);
|
||||
if (rv && rv != EWOULDBLOCK) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -161,7 +145,7 @@ tpm_getburst(struct tpm_softc *sc)
|
|||
if (burst)
|
||||
return burst;
|
||||
|
||||
rv = tsleep(sc, PRIBIO | PCATCH, "tpm_getburst", 1);
|
||||
rv = tsleep(sc, PCATCH, "tpm_getburst", 1);
|
||||
if (rv && rv != EWOULDBLOCK) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -189,9 +173,9 @@ tpm12_suspend(device_t dev, const pmf_qual_t *qual)
|
|||
{
|
||||
struct tpm_softc *sc = device_private(dev);
|
||||
static const uint8_t command[] = {
|
||||
0, 193, /* TPM_TAG_RQU_COMMAND */
|
||||
0, 0xC1, /* TPM_TAG_RQU_COMMAND */
|
||||
0, 0, 0, 10, /* Length in bytes */
|
||||
0, 0, 0, 156 /* TPM_ORD_SaveStates */
|
||||
0, 0, 0, 0x98 /* TPM_ORD_SaveState */
|
||||
};
|
||||
uint8_t scratch[sizeof(command)];
|
||||
|
||||
|
@ -209,16 +193,13 @@ tpm12_resume(device_t dev, const pmf_qual_t *qual)
|
|||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Wait for given status bits using polling.
|
||||
*/
|
||||
static int
|
||||
tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan)
|
||||
tpm_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan)
|
||||
{
|
||||
int rv;
|
||||
|
||||
while (((sc->sc_status = tpm_status(sc)) & mask) != mask && to--) {
|
||||
rv = tsleep(chan, PRIBIO | PCATCH, "tpm_poll", 1);
|
||||
rv = tsleep(chan, PCATCH, "tpm_poll", 1);
|
||||
if (rv && rv != EWOULDBLOCK) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -227,138 +208,32 @@ tpm_waitfor_poll(struct tpm_softc *sc, uint8_t mask, int to, wchan_t chan)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for given status bits using interrupts.
|
||||
*/
|
||||
static int
|
||||
tpm_waitfor_int(struct tpm_softc *sc, uint8_t mask, int tmo, wchan_t chan,
|
||||
int inttype)
|
||||
{
|
||||
int rv, to;
|
||||
|
||||
sc->sc_status = tpm_status(sc);
|
||||
if ((sc->sc_status & mask) == mask)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Enable interrupt on tpm chip. Note that interrupts on our
|
||||
* level (SPL_TTY) are disabled (see tpm{read,write} et al) and
|
||||
* will not be delivered to the cpu until we call tsleep(9) below.
|
||||
*/
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
|
||||
bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) |
|
||||
inttype);
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
|
||||
bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) |
|
||||
TPM_GLOBAL_INT_ENABLE);
|
||||
|
||||
sc->sc_status = tpm_status(sc);
|
||||
if ((sc->sc_status & mask) == mask) {
|
||||
rv = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
to = tpm_tmotohz(tmo);
|
||||
|
||||
/*
|
||||
* tsleep(9) enables interrupts on the cpu and returns after
|
||||
* wake up with interrupts disabled again. Note that interrupts
|
||||
* generated by the tpm chip while being at SPL_TTY are not lost
|
||||
* but held and delivered as soon as the cpu goes below SPL_TTY.
|
||||
*/
|
||||
rv = tsleep(chan, PRIBIO | PCATCH, "tpm_wait", to);
|
||||
|
||||
sc->sc_status = tpm_status(sc);
|
||||
if ((sc->sc_status & mask) == mask)
|
||||
rv = 0;
|
||||
|
||||
out:
|
||||
/* Disable interrupts on tpm chip again. */
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
|
||||
bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) &
|
||||
~TPM_GLOBAL_INT_ENABLE);
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
|
||||
bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE) &
|
||||
~inttype);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait on given status bits, use interrupts where possible, otherwise poll.
|
||||
*/
|
||||
static int
|
||||
tpm_waitfor(struct tpm_softc *sc, uint8_t bits, int tmo, wchan_t chan)
|
||||
{
|
||||
int retry, to, rv;
|
||||
uint8_t todo;
|
||||
|
||||
/*
|
||||
* We use interrupts for TPM_STS_DATA_AVAIL and TPM_STS_VALID (if the
|
||||
* TPM chip supports them) as waiting for those can take really long.
|
||||
* The other TPM_STS* are not needed very often so we do not support
|
||||
* them.
|
||||
*/
|
||||
if (sc->sc_vector != -1) {
|
||||
todo = bits;
|
||||
|
||||
/*
|
||||
* Wait for data ready. This interrupt only occurs when both
|
||||
* TPM_STS_VALID and TPM_STS_DATA_AVAIL are asserted. Thus we
|
||||
* don't have to bother with TPM_STS_VALID separately and can
|
||||
* just return.
|
||||
*
|
||||
* This only holds for interrupts! When using polling both
|
||||
* flags have to be waited for, see below.
|
||||
*/
|
||||
if ((bits & TPM_STS_DATA_AVAIL) &&
|
||||
(sc->sc_capabilities & TPM_INTF_DATA_AVAIL_INT))
|
||||
return tpm_waitfor_int(sc, bits, tmo, chan,
|
||||
TPM_DATA_AVAIL_INT);
|
||||
|
||||
/* Wait for status valid bit. */
|
||||
if ((bits & TPM_STS_VALID) &&
|
||||
(sc->sc_capabilities & TPM_INTF_STS_VALID_INT)) {
|
||||
rv = tpm_waitfor_int(sc, bits, tmo, chan,
|
||||
TPM_STS_VALID_INT);
|
||||
if (rv)
|
||||
return rv;
|
||||
todo = bits & ~TPM_STS_VALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* When all flags have been taken care of, return. Otherwise
|
||||
* use polling for eg TPM_STS_CMD_READY.
|
||||
*/
|
||||
if (todo == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
to = tpm_tmotohz(tmo);
|
||||
retry = 3;
|
||||
|
||||
restart:
|
||||
/*
|
||||
* If requested, wait for TPM_STS_VALID before dealing with any other
|
||||
* flag. Eg when both TPM_STS_DATA_AVAIL and TPM_STS_VALID are
|
||||
* requested, wait for the latter first.
|
||||
*/
|
||||
todo = bits;
|
||||
if (bits & TPM_STS_VALID)
|
||||
todo = TPM_STS_VALID;
|
||||
to = tpm_tmotohz(tmo);
|
||||
again:
|
||||
if ((rv = tpm_waitfor_poll(sc, todo, to, chan)) != 0)
|
||||
return rv;
|
||||
|
||||
if ((todo & sc->sc_status) == TPM_STS_VALID) {
|
||||
/* Now wait for other flags. */
|
||||
todo = bits & ~TPM_STS_VALID;
|
||||
to++;
|
||||
goto again;
|
||||
/*
|
||||
* TPM_STS_VALID has priority over the others.
|
||||
*/
|
||||
if (todo & TPM_STS_VALID) {
|
||||
if ((rv = tpm_poll(sc, TPM_STS_VALID, to+1, chan)) != 0)
|
||||
return rv;
|
||||
todo &= ~TPM_STS_VALID;
|
||||
}
|
||||
|
||||
if ((rv = tpm_poll(sc, todo, to, chan)) != 0)
|
||||
return rv;
|
||||
|
||||
if ((todo & sc->sc_status) != todo) {
|
||||
if (retry-- && (bits & TPM_STS_VALID)) {
|
||||
if ((retry-- > 0) && (bits & TPM_STS_VALID)) {
|
||||
bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_STS,
|
||||
TPM_STS_RESP_RETRY);
|
||||
goto restart;
|
||||
|
@ -369,31 +244,6 @@ again:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tpm_intr(void *v)
|
||||
{
|
||||
struct tpm_softc *sc = v;
|
||||
uint32_t reg;
|
||||
|
||||
reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS);
|
||||
if (!(reg & (TPM_CMD_READY_INT | TPM_LOCALITY_CHANGE_INT |
|
||||
TPM_STS_VALID_INT | TPM_DATA_AVAIL_INT)))
|
||||
return 0;
|
||||
|
||||
if (reg & TPM_STS_VALID_INT)
|
||||
wakeup(sc);
|
||||
if (reg & TPM_CMD_READY_INT)
|
||||
wakeup(sc->sc_write);
|
||||
if (reg & TPM_DATA_AVAIL_INT)
|
||||
wakeup(sc->sc_read);
|
||||
if (reg & TPM_LOCALITY_CHANGE_INT)
|
||||
wakeup(sc->sc_init);
|
||||
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS, reg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
|
@ -412,8 +262,6 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
|
|||
return 0;
|
||||
if ((cap & TPM_CAPS_REQUIRED) != TPM_CAPS_REQUIRED)
|
||||
return 0;
|
||||
if (!(cap & (TPM_INTF_INT_EDGE_RISING | TPM_INTF_INT_LEVEL_LOW)))
|
||||
return 0;
|
||||
|
||||
/* Request locality 0. */
|
||||
bus_space_write_1(bt, bh, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
|
||||
|
@ -436,70 +284,16 @@ tpm_tis12_probe(bus_space_tag_t bt, bus_space_handle_t bh)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
tpm_tis12_irqinit(struct tpm_softc *sc, int irq, int idx)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
if ((irq == -1) || (tpm_devs[idx].flags & TPM_DEV_NOINTS)) {
|
||||
sc->sc_vector = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ack and disable all interrupts. */
|
||||
reg = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE);
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE,
|
||||
reg & ~TPM_GLOBAL_INT_ENABLE);
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS,
|
||||
bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_INT_STATUS));
|
||||
|
||||
/* Program interrupt vector. */
|
||||
bus_space_write_1(sc->sc_bt, sc->sc_bh, TPM_INT_VECTOR, irq);
|
||||
sc->sc_vector = irq;
|
||||
|
||||
/* Program interrupt type. */
|
||||
reg &= ~(TPM_INT_EDGE_RISING|TPM_INT_EDGE_FALLING|TPM_INT_LEVEL_HIGH|
|
||||
TPM_INT_LEVEL_LOW);
|
||||
reg |= TPM_GLOBAL_INT_ENABLE|TPM_CMD_READY_INT|TPM_LOCALITY_CHANGE_INT|
|
||||
TPM_STS_VALID_INT|TPM_DATA_AVAIL_INT;
|
||||
if (sc->sc_capabilities & TPM_INTF_INT_EDGE_RISING)
|
||||
reg |= TPM_INT_EDGE_RISING;
|
||||
else if (sc->sc_capabilities & TPM_INTF_INT_EDGE_FALLING)
|
||||
reg |= TPM_INT_EDGE_FALLING;
|
||||
else if (sc->sc_capabilities & TPM_INTF_INT_LEVEL_HIGH)
|
||||
reg |= TPM_INT_LEVEL_HIGH;
|
||||
else
|
||||
reg |= TPM_INT_LEVEL_LOW;
|
||||
|
||||
bus_space_write_4(sc->sc_bt, sc->sc_bh, TPM_INT_ENABLE, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tpm_tis12_init(struct tpm_softc *sc, int irq)
|
||||
tpm_tis12_init(struct tpm_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
sc->sc_capabilities = bus_space_read_4(sc->sc_bt, sc->sc_bh,
|
||||
sc->sc_caps = bus_space_read_4(sc->sc_bt, sc->sc_bh,
|
||||
TPM_INTF_CAPABILITY);
|
||||
sc->sc_devid = bus_space_read_4(sc->sc_bt, sc->sc_bh, TPM_ID);
|
||||
sc->sc_rev = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_REV);
|
||||
|
||||
for (i = 0; tpm_devs[i].devid; i++) {
|
||||
if (tpm_devs[i].devid == sc->sc_devid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tpm_devs[i].devid)
|
||||
aprint_normal_dev(sc->sc_dev, "%s rev 0x%x\n",
|
||||
tpm_devs[i].name, sc->sc_rev);
|
||||
else
|
||||
aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n",
|
||||
sc->sc_devid, sc->sc_rev);
|
||||
|
||||
if (tpm_tis12_irqinit(sc, irq, i))
|
||||
return 1;
|
||||
aprint_normal_dev(sc->sc_dev, "device 0x%08x rev 0x%x\n",
|
||||
sc->sc_devid, sc->sc_rev);
|
||||
|
||||
if (tpm_request_locality(sc, 0))
|
||||
return 1;
|
||||
|
@ -511,11 +305,11 @@ tpm_tis12_init(struct tpm_softc *sc, int irq)
|
|||
}
|
||||
|
||||
int
|
||||
tpm_tis12_start(struct tpm_softc *sc, int flag)
|
||||
tpm_tis12_start(struct tpm_softc *sc, int rw)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (flag == UIO_READ) {
|
||||
if (rw == UIO_READ) {
|
||||
rv = tpm_waitfor(sc, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
TPM_READ_TMO, sc->sc_read);
|
||||
return rv;
|
||||
|
@ -544,7 +338,7 @@ tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
|
|||
{
|
||||
uint8_t *p = buf;
|
||||
size_t cnt;
|
||||
int rv, n, bcnt;
|
||||
int rv, n;
|
||||
|
||||
cnt = 0;
|
||||
while (len > 0) {
|
||||
|
@ -553,12 +347,12 @@ tpm_tis12_read(struct tpm_softc *sc, void *buf, size_t len, size_t *count,
|
|||
if (rv)
|
||||
return rv;
|
||||
|
||||
bcnt = tpm_getburst(sc);
|
||||
n = MIN(len, bcnt);
|
||||
|
||||
for (; n--; len--) {
|
||||
n = MIN(len, tpm_getburst(sc));
|
||||
while (n > 0) {
|
||||
*p++ = bus_space_read_1(sc->sc_bt, sc->sc_bh, TPM_DATA);
|
||||
cnt++;
|
||||
len--;
|
||||
n--;
|
||||
}
|
||||
|
||||
if ((flags & TPM_PARAM_SIZE) == 0 && cnt >= 6)
|
||||
|
@ -612,19 +406,18 @@ tpm_tis12_write(struct tpm_softc *sc, const void *buf, size_t len)
|
|||
}
|
||||
|
||||
int
|
||||
tpm_tis12_end(struct tpm_softc *sc, int flag, int err)
|
||||
tpm_tis12_end(struct tpm_softc *sc, int rw, int err)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (flag == UIO_READ) {
|
||||
if (rw == UIO_READ) {
|
||||
rv = tpm_waitfor(sc, TPM_STS_VALID, TPM_READ_TMO, sc->sc_read);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
/* Still more data? */
|
||||
sc->sc_status = tpm_status(sc);
|
||||
if (!err && ((sc->sc_status & TPM_STS_DATA_AVAIL) ==
|
||||
TPM_STS_DATA_AVAIL)) {
|
||||
if (!err && (sc->sc_status & TPM_STS_DATA_AVAIL)) {
|
||||
rv = EIO;
|
||||
}
|
||||
|
||||
|
@ -668,107 +461,111 @@ const struct cdevsw tpm_cdevsw = {
|
|||
.d_mmap = nommap,
|
||||
.d_kqfilter = nokqfilter,
|
||||
.d_discard = nodiscard,
|
||||
.d_flag = D_OTHER,
|
||||
.d_flag = D_OTHER | D_MPSAFE,
|
||||
};
|
||||
|
||||
#define TPMUNIT(a) minor(a)
|
||||
|
||||
static int
|
||||
tpmopen(dev_t dev, int flag, int mode, struct lwp *l)
|
||||
{
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
|
||||
int ret = 0;
|
||||
|
||||
if (sc == NULL)
|
||||
return ENXIO;
|
||||
if (sc->sc_flags & TPM_OPEN)
|
||||
return EBUSY;
|
||||
|
||||
sc->sc_flags |= TPM_OPEN;
|
||||
mutex_enter(&sc->sc_lock);
|
||||
if (sc->sc_busy) {
|
||||
ret = EBUSY;
|
||||
} else {
|
||||
sc->sc_busy = true;
|
||||
}
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
tpmclose(dev_t dev, int flag, int mode, struct lwp *l)
|
||||
{
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
|
||||
int ret = 0;
|
||||
|
||||
if (sc == NULL)
|
||||
return ENXIO;
|
||||
if (!(sc->sc_flags & TPM_OPEN))
|
||||
return EINVAL;
|
||||
|
||||
sc->sc_flags &= ~TPM_OPEN;
|
||||
mutex_enter(&sc->sc_lock);
|
||||
if (!sc->sc_busy) {
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
sc->sc_busy = false;
|
||||
}
|
||||
mutex_exit(&sc->sc_lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
tpmread(dev_t dev, struct uio *uio, int flags)
|
||||
{
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
|
||||
uint8_t buf[TPM_BUFSIZ], *p;
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
|
||||
uint8_t buf[TPM_BUFSIZ];
|
||||
size_t cnt, len, n;
|
||||
int rv, s;
|
||||
int rv;
|
||||
|
||||
if (sc == NULL)
|
||||
return ENXIO;
|
||||
|
||||
s = spltty();
|
||||
if ((rv = (*sc->sc_start)(sc, UIO_READ)))
|
||||
goto out;
|
||||
|
||||
/* Get the header. */
|
||||
if ((rv = (*sc->sc_read)(sc, buf, TPM_HDRSIZE, &cnt, 0))) {
|
||||
(*sc->sc_end)(sc, UIO_READ, rv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8) | buf[5];
|
||||
if (len > uio->uio_resid) {
|
||||
if (len > uio->uio_resid || len < cnt) {
|
||||
rv = EIO;
|
||||
(*sc->sc_end)(sc, UIO_READ, rv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy out header. */
|
||||
/* Copy out the header. */
|
||||
if ((rv = uiomove(buf, cnt, uio))) {
|
||||
(*sc->sc_end)(sc, UIO_READ, rv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get remaining part of the answer (if anything is left). */
|
||||
for (len -= cnt, p = buf, n = sizeof(buf); len > 0; p = buf, len -= n,
|
||||
n = sizeof(buf)) {
|
||||
n = MIN(n, len);
|
||||
if ((rv = (*sc->sc_read)(sc, p, n, NULL, TPM_PARAM_SIZE))) {
|
||||
/* Process the rest. */
|
||||
len -= cnt;
|
||||
while (len > 0) {
|
||||
n = MIN(sizeof(buf), len);
|
||||
if ((rv = (*sc->sc_read)(sc, buf, n, NULL, TPM_PARAM_SIZE))) {
|
||||
(*sc->sc_end)(sc, UIO_READ, rv);
|
||||
goto out;
|
||||
}
|
||||
p += n;
|
||||
if ((rv = uiomove(buf, p - buf, uio))) {
|
||||
if ((rv = uiomove(buf, n, uio))) {
|
||||
(*sc->sc_end)(sc, UIO_READ, rv);
|
||||
goto out;
|
||||
}
|
||||
len -= n;
|
||||
}
|
||||
|
||||
rv = (*sc->sc_end)(sc, UIO_READ, rv);
|
||||
out:
|
||||
splx(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
tpmwrite(dev_t dev, struct uio *uio, int flags)
|
||||
{
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
|
||||
uint8_t buf[TPM_BUFSIZ];
|
||||
int n, rv, s;
|
||||
int n, rv;
|
||||
|
||||
if (sc == NULL)
|
||||
return ENXIO;
|
||||
|
||||
s = spltty();
|
||||
|
||||
n = MIN(sizeof(buf), uio->uio_resid);
|
||||
if ((rv = uiomove(buf, n, uio))) {
|
||||
goto out;
|
||||
|
@ -782,14 +579,13 @@ tpmwrite(dev_t dev, struct uio *uio, int flags)
|
|||
|
||||
rv = (*sc->sc_end)(sc, UIO_WRITE, rv);
|
||||
out:
|
||||
splx(s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
|
||||
{
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, TPMUNIT(dev));
|
||||
struct tpm_softc *sc = device_lookup_private(&tpm_cd, minor(dev));
|
||||
struct tpm_ioc_getinfo *info;
|
||||
|
||||
if (sc == NULL)
|
||||
|
@ -802,7 +598,7 @@ tpmioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
|
|||
info->tpm_version = sc->sc_ver;
|
||||
info->device_id = sc->sc_devid;
|
||||
info->device_rev = sc->sc_rev;
|
||||
info->device_caps = sc->sc_capabilities;
|
||||
info->device_caps = sc->sc_caps;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tpmreg.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */
|
||||
/* $NetBSD: tpmreg.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 The NetBSD Foundation, Inc.
|
||||
|
@ -78,6 +78,7 @@
|
|||
#define TPM_STS_GO __BIT(5)
|
||||
#define TPM_STS_DATA_AVAIL __BIT(4)
|
||||
#define TPM_STS_DATA_EXPECT __BIT(3)
|
||||
#define TPM_STS_SELFTEST_DONE __BIT(2)
|
||||
#define TPM_STS_RESP_RETRY __BIT(1)
|
||||
|
||||
#define TPM_DATA 0x0024 /* 32bit register */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tpmvar.h,v 1.4 2019/06/22 12:57:41 maxv Exp $ */
|
||||
/* $NetBSD: tpmvar.h,v 1.5 2019/10/08 18:43:02 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 The NetBSD Foundation, Inc.
|
||||
|
@ -29,24 +29,6 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008, 2009 Michael Shalayeff
|
||||
* Copyright (c) 2009, 2010 Hans-Joerg Hoexer
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define TPM_API_VERSION 1
|
||||
|
||||
enum tpm_version {
|
||||
|
@ -56,7 +38,6 @@ enum tpm_version {
|
|||
|
||||
struct tpm_ioc_getinfo {
|
||||
uint32_t api_version;
|
||||
|
||||
uint32_t tpm_version;
|
||||
uint32_t device_id;
|
||||
uint32_t device_rev;
|
||||
|
@ -70,35 +51,29 @@ struct tpm_ioc_getinfo {
|
|||
struct tpm_softc {
|
||||
device_t sc_dev;
|
||||
enum tpm_version sc_ver;
|
||||
void *sc_ih;
|
||||
kmutex_t sc_lock;
|
||||
bool sc_busy;
|
||||
|
||||
int (*sc_init)(struct tpm_softc *, int);
|
||||
int (*sc_init)(struct tpm_softc *);
|
||||
int (*sc_start)(struct tpm_softc *, int);
|
||||
int (*sc_read)(struct tpm_softc *, void *, size_t, size_t *, int);
|
||||
int (*sc_write)(struct tpm_softc *, const void *, size_t);
|
||||
int (*sc_end)(struct tpm_softc *, int, int);
|
||||
|
||||
bus_space_tag_t sc_bt, sc_batm;
|
||||
bus_space_handle_t sc_bh, sc_bahm;
|
||||
bus_space_tag_t sc_bt;
|
||||
bus_space_handle_t sc_bh;
|
||||
|
||||
uint32_t sc_devid;
|
||||
uint32_t sc_rev;
|
||||
uint32_t sc_status;
|
||||
uint32_t sc_capabilities;
|
||||
|
||||
int sc_flags;
|
||||
#define TPM_OPEN 0x0001
|
||||
|
||||
int sc_vector;
|
||||
uint32_t sc_caps;
|
||||
};
|
||||
|
||||
int tpm_intr(void *);
|
||||
|
||||
bool tpm12_suspend(device_t, const pmf_qual_t *);
|
||||
bool tpm12_resume(device_t, const pmf_qual_t *);
|
||||
|
||||
int tpm_tis12_probe(bus_space_tag_t, bus_space_handle_t);
|
||||
int tpm_tis12_init(struct tpm_softc *, int);
|
||||
int tpm_tis12_init(struct tpm_softc *);
|
||||
int tpm_tis12_start(struct tpm_softc *, int);
|
||||
int tpm_tis12_read(struct tpm_softc *, void *, size_t, size_t *, int);
|
||||
int tpm_tis12_write(struct tpm_softc *, const void *, size_t);
|
||||
|
|
|
@ -1,8 +1,37 @@
|
|||
/* $NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $ */
|
||||
/* $NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Maxime Villard.
|
||||
*
|
||||
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008, 2009 Michael Shalayeff
|
||||
* Copyright (c) 2009, 2010 Hans-Jörg Höxer
|
||||
* Copyright (c) 2009, 2010 Hans-Joerg Hoexer
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
|
@ -19,13 +48,10 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.5 2019/10/08 18:43:03 maxv Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/pmf.h>
|
||||
|
@ -36,13 +62,13 @@ __KERNEL_RCSID(0, "$NetBSD: tpm_isa.c,v 1.4 2019/06/22 12:57:41 maxv Exp $");
|
|||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
#include "ioconf.h"
|
||||
|
||||
static int tpm_isa_match(device_t, cfdata_t, void *);
|
||||
static void tpm_isa_attach(device_t, device_t, void *);
|
||||
|
||||
CFATTACH_DECL_NEW(tpm_isa, sizeof(struct tpm_softc),
|
||||
tpm_isa_match, tpm_isa_attach, NULL, NULL);
|
||||
|
||||
extern struct cfdriver tpm_cd;
|
||||
CFATTACH_DECL_NEW(tpm_isa, sizeof(struct tpm_softc), tpm_isa_match,
|
||||
tpm_isa_attach, NULL, NULL);
|
||||
|
||||
static int
|
||||
tpm_isa_match(device_t parent, cfdata_t match, void *aux)
|
||||
|
@ -60,8 +86,8 @@ tpm_isa_match(device_t parent, cfdata_t match, void *aux)
|
|||
return 0;
|
||||
|
||||
/* XXX: integer locator sign extension */
|
||||
if (bus_space_map(bt, (unsigned int)ia->ia_iomem[0].ir_addr, TPM_SPACE_SIZE,
|
||||
0, &bh))
|
||||
if (bus_space_map(bt, (unsigned int)ia->ia_iomem[0].ir_addr,
|
||||
TPM_SPACE_SIZE, 0, &bh))
|
||||
return 0;
|
||||
|
||||
if ((rv = tpm_tis12_probe(bt, bh))) {
|
||||
|
@ -80,46 +106,33 @@ tpm_isa_attach(device_t parent, device_t self, void *aux)
|
|||
{
|
||||
struct tpm_softc *sc = device_private(self);
|
||||
struct isa_attach_args *ia = aux;
|
||||
bus_addr_t iobase;
|
||||
bus_addr_t base;
|
||||
bus_size_t size;
|
||||
int rv;
|
||||
|
||||
sc->sc_dev = self;
|
||||
sc->sc_ver = TPM_1_2;
|
||||
|
||||
sc->sc_bt = ia->ia_memt;
|
||||
iobase = (unsigned int)ia->ia_iomem[0].ir_addr;
|
||||
size = TPM_SPACE_SIZE;
|
||||
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
sc->sc_busy = false;
|
||||
sc->sc_init = tpm_tis12_init;
|
||||
sc->sc_start = tpm_tis12_start;
|
||||
sc->sc_read = tpm_tis12_read;
|
||||
sc->sc_write = tpm_tis12_write;
|
||||
sc->sc_end = tpm_tis12_end;
|
||||
sc->sc_bt = ia->ia_memt;
|
||||
|
||||
if (bus_space_map(sc->sc_bt, iobase, size, 0, &sc->sc_bh)) {
|
||||
base = (unsigned int)ia->ia_iomem[0].ir_addr;
|
||||
size = TPM_SPACE_SIZE;
|
||||
|
||||
if (bus_space_map(sc->sc_bt, base, size, 0, &sc->sc_bh)) {
|
||||
aprint_error_dev(sc->sc_dev, "cannot map registers\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rv = (*sc->sc_init)(sc, ia->ia_irq[0].ir_irq)) != 0) {
|
||||
if ((*sc->sc_init)(sc) != 0) {
|
||||
bus_space_unmap(sc->sc_bt, sc->sc_bh, size);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only setup interrupt handler when we have a vector and the
|
||||
* chip is TIS 1.2 compliant.
|
||||
*/
|
||||
if (sc->sc_init == tpm_tis12_init &&
|
||||
ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ &&
|
||||
(sc->sc_ih = isa_intr_establish_xname(ia->ia_ic,
|
||||
ia->ia_irq[0].ir_irq, IST_EDGE, IPL_TTY, tpm_intr, sc,
|
||||
device_xname(sc->sc_dev))) == NULL) {
|
||||
bus_space_unmap(sc->sc_bt, sc->sc_bh, TPM_SPACE_SIZE);
|
||||
aprint_error_dev(sc->sc_dev, "cannot establish interrupt\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pmf_device_register(sc->sc_dev, tpm12_suspend, tpm12_resume))
|
||||
aprint_error_dev(sc->sc_dev, "cannot set power mgmt handler\n");
|
||||
aprint_error_dev(sc->sc_dev, "couldn't establish power handler\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue