# $Id: openbsd-tcpa.diff,v 1.6 2007/02/24 22:54:27 jcs Exp $ # # openbsd port of rick wash's netbsd tcpa driver # # by joshua stein # # see http://www.citi.umich.edu/u/rwash/projects/trusted/netbsd.html for # more information on the original driver # # openbsd notes: # - converted from callout api to timeout # - disabled debugging by default # - renamed tcpa_{open,close,write,read,ioctl} functions to their # tcpa{open,close,write,read,ioctl} counterparts # # to apply patch: # # cd /usr/src # patch -p0 < /path/to/this/diff # # then recompile and install the GENERIC kernel. to create /dev/tpm: # # cd /usr/src/etc # make clean; make allarchs # cp etc.i386/MAKEDEV /dev # cd /dev # sh MAKEDEV tpm # # for userland access to /dev/tpm, use the libtpm port at # http://jcs.org/ports/ # Index: etc/etc.i386/MAKEDEV.md =================================================================== RCS file: /cvs/src/etc/etc.i386/MAKEDEV.md,v retrieving revision 1.28 diff -u -r1.28 MAKEDEV.md --- etc/etc.i386/MAKEDEV.md 3 Oct 2004 21:28:34 -0000 1.28 +++ etc/etc.i386/MAKEDEV.md 16 Jan 2005 02:03:41 -0000 @@ -19,6 +19,8 @@ dnl __devitem(nvram, nvram, NVRAM access)dnl _mkdev(nvram, nvram, {-M nvram c major_nvram_c 0 440 kmem-})dnl +__devitem(tpm, tpm, TPM access)dnl +_mkdev(tpm, tpm, {-M tpm c major_tpm_c 0 600-})dnl _TITLE(make) _DEV(all) _DEV(ramdisk) @@ -89,6 +91,7 @@ _DEV(speak, 27) _DEV(ss, 19) _DEV(systrace, 78) +_DEV(tpm, 85) _DEV(tun, 40) _DEV(tuner, 49) _DEV(uk, 20) Index: sys/dev/ic/tcpa.c =================================================================== RCS file: sys/dev/ic/tcpa.c diff -N sys/dev/ic/tcpa.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/dev/ic/tcpa.c 16 Jan 2005 02:03:42 -0000 @@ -0,0 +1,645 @@ +/* + * Copyright (c) 2003 Rick Wash + * + * 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 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. + */ +/* + * TCPA TPM driver, bus independent code + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Debugging define. Turn it on if you want a lot of debugging + * information spewed out onto console/dmesg. Since this is a + * developmental driver, its on by default right now. Just + * comment this line out to disable it. + */ +/* #define TCPA_DEBUG */ + +/* TCPA Base */ +#define TCPA_ATMEL_BASE 0x400 + +/* PCI configuration addresses */ +#define PCI_GEN_PMCON_1 0xA0 +#define PCI_GEN1_DEC 0xE4 +#define PCI_LPC_EN 0xE6 +#define PCI_GEN2_DEC 0xEC + +/* TPM addresses */ +#define TPM_ADDR 0x4E +#define TPM_DATA 0x4F + +/* write status bits */ +#define STATUS_BIT_ABORT 0x01 +#define STATUS_BIT_LASTBYTE 0x04 + +/* read status bits */ +#define STATUS_BIT_BUSY 0x01 +#define STATUS_BIT_DATA_AVAIL 0x02 +#define STATUS_BIT_REWRITE 0x04 + +/* Timeout Numbers */ +#define TCPA_DELAY 50 /* in milliseconds */ +#define TCPA_TIMEOUT ((2*2*60*60)/TCPA_DELAY) +#define TCPA_TSLEEP_TIMEOUT 2*60*hz +#define TCPA_CALLOUT_TIMEOUT TCPA_DELAY + +#ifdef __OpenBSD__ +#ifndef PCI_PRODUCT_INTEL_82801DB_ISA +#define PCI_PRODUCT_INTEL_82801DB_ISA PCI_PRODUCT_INTEL_82801DBM_LPC +#endif +#endif + +int tcpaopen(dev_t dev, int flag, int mode, struct proc *p); +int tcpaclose(dev_t dev, int flag, int mode, struct proc *p); +int tcpawrite(dev_t dev, struct uio *uio, int flags); +int tcparead(dev_t dev, struct uio *uio, int flags); +int tcpaioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p); + +int tcpa_init(struct tcpa_softc *sc, pci_chipset_tag_t pa_pc, pcitag_t pa_tag); +int tcpa_recv(struct tcpa_softc *sc, int count); +int tcpa_send(struct tcpa_softc *sc, int count); + +void tcpa_intr(void *data); +void tcparead_data(struct tcpa_softc *sc); +void tcpa_send_data(struct tcpa_softc *sc); + +#ifdef __OpenBSD__ +struct cfdriver tcpa_cd = { + NULL, "tcpa", DV_DULL +}; +#endif + +const struct cdevsw tcpa_cdevsw = { + tcpaopen, + tcpaclose, + tcparead, + tcpawrite, + tcpaioctl, + NULL, /* tty */ + NULL, /* poll */ + NULL, /* mmap */ + 0 +}; + +struct tcpa_softc *tcpa_sc; + +/* Chip types */ +enum { + ICH2LPC = 0, + ICH3LPCM, + ICH4LPC, + ICH4LPCM +}; + +static char *tcpa_chip_names[] = { + "Intel ICH2 LPC", + "Intel ICH3 LPC-M", + "Intel ICH4 LPC", + "Intel ICH4 LPC-M" +}; + +/* poll states */ +enum { + TCPA_STATE_READY = 0, + TCPA_STATE_READ_START, + TCPA_STATE_WAIT_FOR_DATA, + TCPA_STATE_READ_DONE, + TCPA_STATE_WRITE_START, + TCPA_STATE_WRITE_BUSY, + TCPA_STATE_WRITE_WORKING, + TCPA_STATE_WRITE_DONE, + TCPA_STATE_ERROR, + TCPA_STATE_MAX +}; + +int +tcpaopen(dev_t dev, int flag, int mode, struct proc *p) +{ + int error = 0; + +#ifdef TCPA_DEBUG + printf("in tcpaopen\n"); +#endif /* TCPA_DEBUG */ + + /* Make sure it has been initialized */ + if (tcpa_sc->initialized != 1) + return ENODEV; + + /* Only can be opened by one process at a time */ + /* XXX: concurrency hack */ + if (tcpa_sc->open != 0) + return EBUSY; + + tcpa_sc->open = 1; + + return (error); +} + +int +tcpaclose(dev_t dev, int flag, int mode, struct proc *p) +{ + int error = 0; + +#ifdef TCPA_DEBUG + printf("in tcpaclose\n"); +#endif /* TCPA_DEBUG */ + + tcpa_sc->open = 0; + + return (error); +} + +int +tcpawrite(dev_t dev, struct uio *uio, int flags) +{ + int error = 0; + int len; + struct tcpa_softc *sc = tcpa_sc; + + if (sc->state != TCPA_STATE_READY) + return EBUSY; + + len = min(uio->uio_resid, TCPA_BUFFER_LEN); + + uiomove(sc->buffer, len, uio); + + sc->len = len; + sc->state = TCPA_STATE_WRITE_START; +#ifdef __OpenBSD__ + timeout_add(&sc->callout, 1); +#else + callout_reset(&sc->callout, 1, tcpa_intr, sc); +#endif + while((sc->state != TCPA_STATE_WRITE_DONE) && (sc->state != TCPA_STATE_ERROR)) { + tsleep(sc->buffer, PRIBIO, "tcpawrite", TCPA_TSLEEP_TIMEOUT); + } + + error = sc->retval; + sc->retval = 0; + + sc->state = TCPA_STATE_READY; + +#ifdef TCPA_DEBUG + printf("in tcpawrite\n"); +#endif /* TCPA_DEBUG */ + + return (error); +} + +int +tcparead(dev_t dev, struct uio *uio, int flags) +{ + int len; + struct tcpa_softc *sc = tcpa_sc; + int retval = 0; + + if (sc->state != TCPA_STATE_READY) + return EBUSY; + +#ifdef TCPA_DEBUG + printf("in tcparead\n"); +#endif /* TCPA_DEBUG */ + + len = min(uio->uio_resid, TCPA_BUFFER_LEN); + + if (len < 6) + return EIO; + + sc->len = len; + sc->state = TCPA_STATE_READ_START; +#ifdef __OpenBSD__ + timeout_add(&sc->callout, 1); +#else + callout_reset(&sc->callout, 1, tcpa_intr, sc); +#endif + while ((sc->state != TCPA_STATE_READ_DONE) && (sc->state != TCPA_STATE_ERROR)) { + tsleep(sc->buffer, PRIBIO, "tcparead", TCPA_TSLEEP_TIMEOUT); + } + + retval = sc->retval; + sc->retval = 0; + + if (sc->len > 0) + uiomove(sc->buffer, sc->len, uio); + + sc->state = TCPA_STATE_READY; + + return (retval); +} + +int +tcpaioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + int error = 0; + + error = EINVAL; + +#ifdef TCPA_DEBUG + printf("in tcpaioctl\n"); +#endif /* TCPA_DEBUG */ + + return (error); +} + +int +tcpa_init(struct tcpa_softc *sc, pci_chipset_tag_t pa_pc, pcitag_t pa_tag) +{ + int lpcenable; + int tpminfo; + int pwrinfo; + int x; + + /* Enable the LPC */ + lpcenable = pci_conf_read(pa_pc, pa_tag, PCI_GEN1_DEC); + lpcenable |= 0x20000000; + pci_conf_write(pa_pc, pa_tag, PCI_GEN1_DEC, lpcenable); + /* Verify it was turned on */ + if ((sc->type == ICH3LPCM) || (sc->type == ICH4LPCM)) { + lpcenable = pci_conf_read(pa_pc, pa_tag, PCI_GEN1_DEC); + if ( (lpcenable & 0x20000000) == 0) { + printf("tcpa: cannot enable LPC\n"); + return ENODEV; + } + } + + /* Initialize TPM */ + tpminfo = pci_conf_read(pa_pc, pa_tag, PCI_GEN2_DEC); + tpminfo = (tpminfo & 0xffff0000) | (sc->base & 0xfff0); + /* if ((sc->type == ICH3LPCM) || (sc->type == ICH4LPCM)) */ + tpminfo |= 0x00000001; + pci_conf_write(pa_pc, pa_tag, PCI_GEN2_DEC, tpminfo); + + /* Enable Power Management */ + if ((sc->type == ICH3LPCM) || (sc->type == ICH4LPCM)) { + pwrinfo = pci_conf_read(pa_pc, pa_tag, PCI_GEN_PMCON_1); + pwrinfo |= 0x40000000; + pci_conf_write(pa_pc, pa_tag, PCI_GEN_PMCON_1, pwrinfo); + } + + x = splhigh(); + /* talk directly to chip */ + outb(TPM_ADDR, 0x0D); /* unlock 4F */ + outb(TPM_DATA, 0x55); + outb(TPM_ADDR, 0x0A); /* int disable */ + outb(TPM_DATA, 0x00); + outb(TPM_ADDR, 0x08); /* base addr lo */ + outb(TPM_DATA, sc->base & 0xFF); + outb(TPM_ADDR, 0x09); /* base addr hi */ + outb(TPM_DATA, (sc->base & 0xFF00) >> 8); + outb(TPM_ADDR, 0x0D); /* lock 4F */ + outb(TPM_DATA, 0xAA); + splx(x); + + return 0; +} + +void +tcpaattach(struct tcpa_softc *sc, u_int32_t vendor, pci_chipset_tag_t pa_pc, pcitag_t pa_tag) +{ + int error; + + tcpa_sc = sc; + + if (vendor == PCI_PRODUCT_INTEL_82801BA_LPC) + sc->type = ICH2LPC; + else if (vendor == PCI_PRODUCT_INTEL_82801CAM_LPC) + sc->type = ICH3LPCM; + else if (vendor == PCI_PRODUCT_INTEL_82801DB_LPC) + sc->type = ICH4LPC; + else if (vendor == PCI_PRODUCT_INTEL_82801DB_ISA) + sc->type = ICH4LPCM; + else { + /* panic("Unknown TCPA Chip\n"); */ + } + + sc->base = TCPA_ATMEL_BASE; + + error = tcpa_init(tcpa_sc, pa_pc, pa_tag); + + if (error != 0) { + printf("tcpa: error initializing chip\n"); + return; + } + + /* Query the chip for its version */ + outb(TPM_ADDR, 0x00); + sc->version[0] = inb(TPM_DATA); + if (sc->version[0] == 0xFF) { + printf("tcpa: version query failed\n"); + return; + } + outb(TPM_ADDR, 0x01); + sc->version[1] = inb(TPM_DATA); + outb(TPM_ADDR, 0x02); + sc->version[2] = inb(TPM_DATA); + outb(TPM_ADDR, 0x03); + sc->version[3] = inb(TPM_DATA); + + /* Query the chip for its vendor */ + outb(TPM_ADDR, 0x04); + sc->vendor[0] = inb(TPM_DATA); + if (sc->version[0] == 0xFF) { + printf("tcpa: vendor query failed\n"); + return; + } + outb(TPM_ADDR, 0x05); + sc->vendor[1] = inb(TPM_DATA); + outb(TPM_ADDR, 0x06); + sc->vendor[2] = inb(TPM_DATA); + outb(TPM_ADDR, 0x07); + sc->vendor[3] = inb(TPM_DATA); + sc->vendor[4] = '\0'; + + printf(" at 0x%x (%s), version %d.%d.%d.%d, vendor %s\n", + sc->base, tcpa_chip_names[sc->type], + sc->version[0], sc->version[1], sc->version[2], sc->version[3], + sc->vendor); + +#ifdef __OpenBSD__ + timeout_set(&sc->callout, tcpa_intr, sc); + timeout_add(&sc->callout, 1); +#else + callout_init(&sc->callout); +#endif + + sc->initialized = 1; +} + +int +tcpadetach(void) +{ + int error = 0; + +#ifdef __OpenBSD__ + timeout_del(&tcpa_sc->callout); +#else + callout_ack(&tcpa_sc->callout); + callout_stop(&tcpa_sc->callout); +#endif + + tcpa_sc->initialized = 0; + + return error; +} + +/* Lower half of the device driver. This does the actual polling of the device + * Uses NetBSD's callout to delay, so the kernel stays useful while polling + */ +void +tcpa_intr(void *data) +{ + struct tcpa_softc *sc = data; + int status; +#ifdef __OpenBSD__ + int s; + + s = splnet(); +#endif + + switch (sc->state) { + case TCPA_STATE_READY: + /* XXX: Should this be here? */ +#ifdef TCPA_DEBUG + printf("tcpa: state ready\n"); +#endif /* TCPA_DEBUG */ +#ifdef __OpenBSD__ + timeout_add(&sc->callout, TCPA_CALLOUT_TIMEOUT); +#else + callout_reset(&sc->callout, TCPA_CALLOUT_TIMEOUT, tcpa_intr, data); +#endif + break; + case TCPA_STATE_READ_START: /* Wait till the chip is not busy */ +#ifdef TCPA_DEBUG + printf("tcpa: state read start\n"); +#endif /* TCPA_DEBUG */ + sc->wait_timeout++; + if (sc->wait_timeout > TCPA_TIMEOUT) { + printf("tcpa: timeout on read\n"); + sc->state = TCPA_STATE_ERROR; + sc->retval = EIO; + wakeup(sc->buffer); + break; + } + status = inb(sc->base + 1); + if ((status & STATUS_BIT_BUSY) != 0) { +#ifdef __OpenBSD__ + timeout_add(&sc->callout, TCPA_CALLOUT_TIMEOUT); +#else + callout_reset(&sc->callout, TCPA_CALLOUT_TIMEOUT, tcpa_intr, data); +#endif + break; + } + sc->state = TCPA_STATE_WAIT_FOR_DATA; + sc->wait_timeout = 0; + /* fallthrough */ + case TCPA_STATE_WAIT_FOR_DATA: /* Wait till there is data available */ +#ifdef TCPA_DEBUG + printf("tcpa: state wait for data\n"); +#endif /* TCPA_DEBUG */ + sc->wait_timeout++; + if (sc->wait_timeout > TCPA_TIMEOUT) { + printf("tcpa: timeout waiting for data\n"); + sc->state = TCPA_STATE_ERROR; + sc->retval = EIO; + wakeup(sc->buffer); + break; + } + status = inb(sc->base + 1); + status &= (STATUS_BIT_BUSY | STATUS_BIT_DATA_AVAIL); + if ( status != STATUS_BIT_DATA_AVAIL ) { +#ifdef __OpenBSD__ + timeout_add(&sc->callout, TCPA_CALLOUT_TIMEOUT); +#else + callout_reset(&sc->callout, TCPA_CALLOUT_TIMEOUT, tcpa_intr, data); +#endif + break; + } + + /* Read Data */ + sc->wait_timeout = 0; + sc->retval = 0; + sc->state = TCPA_STATE_READ_DONE; + tcparead_data(sc); + wakeup(sc->buffer); + break; + case TCPA_STATE_WRITE_START: /* Wait till the chip is not busy */ + outb(sc->base+1, STATUS_BIT_ABORT); +#ifdef TCPA_DEBUG + printf("tcpa: state write start\n"); +#endif /* TCPA_DEBUG */ + sc->state = TCPA_STATE_WRITE_BUSY; + case TCPA_STATE_WRITE_BUSY: + sc->wait_timeout++; +#ifdef TCPA_DEBUG + printf("tcpa:state write busy\n"); +#endif /* TCPA_DEBUG */ + if (sc->wait_timeout > TCPA_TIMEOUT) { + printf("tcpa: timeout waiting to write\n"); + sc->state = TCPA_STATE_ERROR; + sc->retval = EIO; + wakeup(sc->buffer); + break; + } + status = 0; + status = inb(sc->base + 1); +#ifdef TCPA_DEBUG + printf("tcpa: base: %08x, status bit: %08x\n", sc->base, status); +#endif /* TCPA_DEBUG */ + if ( (status & STATUS_BIT_BUSY) != 0) { +#ifdef __OpenBSD__ + timeout_add(&sc->callout, TCPA_CALLOUT_TIMEOUT); +#else + callout_reset(&sc->callout, TCPA_CALLOUT_TIMEOUT, tcpa_intr, data); +#endif + break; + } + sc->wait_timeout = 0; + sc->retval = 0; + sc->state = TCPA_STATE_WRITE_WORKING; + + /* Send Data */ + tcpa_send_data(sc); + /* fallthrough */ + case TCPA_STATE_WRITE_WORKING: /* Wait till the chip is working, done, or an error */ +#ifdef TCPA_DEBUG + printf("tcpa: state write working\n"); +#endif /* TCPA_DEBUG */ + sc->wait_timeout++; + if (sc->wait_timeout > TCPA_TIMEOUT) { + printf("tcpa: timeout after writing\n"); + sc->state = TCPA_STATE_ERROR; + sc->retval = EIO; + wakeup(sc->buffer); + break; + } + status = inb(sc->base + 1); + if ( (status & (STATUS_BIT_BUSY | STATUS_BIT_DATA_AVAIL | STATUS_BIT_REWRITE)) == 0) { +#ifdef __OpenBSD__ + timeout_add(&sc->callout, TCPA_CALLOUT_TIMEOUT); +#else + callout_reset(&sc->callout, TCPA_CALLOUT_TIMEOUT, tcpa_intr, data); +#endif + break; + } + sc->state = TCPA_STATE_WRITE_DONE; + + if ( (status & STATUS_BIT_REWRITE) != 0) { + sc->retval = EIO; + sc->state = TCPA_STATE_ERROR; + } + wakeup(sc->buffer); + break; + default: + printf("tcpa: error in interrupt\n"); + sc->state = TCPA_STATE_ERROR; + sc->retval = EIO; + wakeup(sc->buffer); + } + +#ifdef __OpenBSD__ + splx(s); +#endif +} + +void +tcparead_data(struct tcpa_softc *sc) +{ + int i; + int status; + char *buffer = sc->buffer; + u_int32_t size; + + for (i=0; i<6; i++) { + status = inb(sc->base+1); + if ( (status & STATUS_BIT_DATA_AVAIL) == 0) { + printf("tcpa: error reading header\n"); + sc->len = 0; + sc->retval = EIO; + sc->state = TCPA_STATE_ERROR;; + return; + } + *buffer++ = inb(sc->base); + } + +#ifdef __OpenBSD__ + size = betoh32(*(u_int32_t *)(sc->buffer + 2)); +#else + size = be32toh(*(u_int32_t *)(sc->buffer + 2)); +#endif + if (sc->len < size) { + sc->len = 0; + sc->retval = EIO; + sc->state = TCPA_STATE_ERROR; + return; + } + + for (; i < size; i++) { + status = inb(sc->base+1); + if ( (status & STATUS_BIT_DATA_AVAIL) == 0) { + printf("tcpa: error reading data\n"); + sc->len = 0; + sc->retval = EIO; + sc->state = TCPA_STATE_ERROR; + return; + } + *buffer++ = inb(sc->base); + } + + /* Make sure data available is gone */ + status = inb(sc->base+1); + if ( (status & STATUS_BIT_DATA_AVAIL) != 0) { + printf("tcpa: data avail is stuck\n"); + sc->len = 0; + sc->retval = EIO; + sc->state = TCPA_STATE_ERROR; + return; + } + + /* Send an abort */ + outb(sc->base+1, STATUS_BIT_ABORT); + + sc->len = size; + /* TODO: crc check? */ +} + +void +tcpa_send_data(struct tcpa_softc *sc) +{ + int i; + + /* Write everything but the last byte */ + for (i = 0; i < sc->len; i++) { + outb(sc->base, sc->buffer[i]); + } + + /* Send last byte */ + outb(sc->base+1, STATUS_BIT_LASTBYTE); + + /* Send last byte */ + outb(sc->base, sc->buffer[i]); +} Index: sys/dev/ic/tcpa.h =================================================================== RCS file: sys/dev/ic/tcpa.h diff -N sys/dev/ic/tcpa.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/dev/ic/tcpa.h 16 Jan 2005 02:03:42 -0000 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003 Rick Wash + * + * 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 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. + */ +#ifndef TCPA_H +#define TCPA_H + +#ifdef __OpenBSD__ +#include +#endif + +#define TCPA_BUFFER_LEN 2048 + +struct tcpa_softc { + struct device sc_dev; /* generic device info */ + /* device specific info */ + int type; /* chipset type */ + u_int16_t base; /* base address */ + u_int8_t buffer[TCPA_BUFFER_LEN];/* memory for requests and replys */ + int initialized; /* flag - initialized chip */ + int open; /* exclusive open flag */ + int state; /* interrupt poll state */ + int wait_timeout; /* poll timeout counter */ + int retval; /* return value (lenght or error) */ + int len; /* size of data */ +#ifdef __OpenBSD__ + struct timeout callout; /* for polling */ +#else + struct callout callout; /* for polling */ +#endif + unsigned char version[4]; /* Version number */ + unsigned char vendor[5]; /* vendor name */ +}; + +#ifdef __OpenBSD__ +int tcpa_pci_match (struct device *, void *, void *); +void tcpa_pci_attach (struct device *, struct device *, void *); +void tcpaattach (struct tcpa_softc *sc, u_int32_t cendor, pci_chipset_tag_t pa_pc, pcitag_t pa_tag); +int tcpadetach (void); +#else +int tcpa_pci_match __P((struct device *, struct cfdata *, void *)); +void tcpa_pci_attach __P((struct device *, struct device *, void *)); +void tcpaattach __P((struct tcpa_softc *sc, u_int32_t cendor, pci_chipset_tag_t pa_pc, pcitag_t pa_tag)); +int tcpadetach __P((void)); +#endif + +#endif /* TCPA_H */ Index: sys/dev/pci/tcpa_pci.c =================================================================== RCS file: sys/dev/pci/tcpa_pci.c diff -N sys/dev/pci/tcpa_pci.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/dev/pci/tcpa_pci.c 16 Jan 2005 02:03:42 -0000 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003 Rick Wash + * + * 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 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. + */ +/* + * TCPA TPM driver, pci specific code + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +struct cfattach tcpa_pci_ca = { + sizeof(struct tcpa_softc), tcpa_pci_match, tcpa_pci_attach +}; + +/* define products, write match function */ +const struct tcpa_pci_product { + u_int32_t app_vendor; /* PCI vendor ID */ + u_int32_t app_product; /* PCI product ID */ +} tcpa_pci_products[] = { + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_LPC }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CAM_LPC }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_LPC }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DBM_LPC }, + { 0, 0} +}; + +int +tcpa_pci_match(struct device *parent, void *match, void *aux) +{ + struct pci_attach_args *pa = aux; + const struct tcpa_pci_product *app; + + for (app = tcpa_pci_products; app->app_vendor != 0; app++) { + if (PCI_VENDOR(pa->pa_id) == app->app_vendor && + PCI_PRODUCT(pa->pa_id) == app->app_product) + return 1; + } + + return 0; +} + +void +tcpa_pci_attach(struct device *parent, struct device *self, void *aux) +{ + struct tcpa_softc *sc = (struct tcpa_softc *)self; + struct pci_attach_args *pa = aux; + + tcpaattach(sc, PCI_VENDOR(pa->pa_id), pa->pa_pc, pa->pa_tag); +} Index: sys/arch/i386/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/i386/conf/GENERIC,v retrieving revision 1.401 diff -u -r1.401 GENERIC --- sys/arch/i386/conf/GENERIC 14 Jan 2005 20:53:13 -0000 1.401 +++ sys/arch/i386/conf/GENERIC 16 Jan 2005 02:03:42 -0000 @@ -47,7 +47,7 @@ isa0 at mainbus0 isa0 at pcib? -isa0 at ichpcib? +#isa0 at ichpcib? isa0 at gscpcib? eisa0 at mainbus0 pci* at mainbus0 @@ -61,7 +61,7 @@ pci* at ppb? pci* at pchb? pcib* at pci? # PCI-ISA bridge -ichpcib* at pci? # Intel ICHx/ICHx-M LPC bridges +#ichpcib* at pci? # Intel ICHx/ICHx-M LPC bridges gscpcib* at pci? # NS Geode SC1100 PCI-ISA bridge gpio* at gscpcib? @@ -584,6 +584,9 @@ iop* at pci? # I2O ioprbs* at iop? # Random block storage scsibus* at ioprbs? + +# TCPA +tcpa0 at pci? pseudo-device pctr 1 pseudo-device mtrr 1 # Memory range attributes control Index: sys/arch/i386/conf/files.i386 =================================================================== RCS file: /cvs/src/sys/arch/i386/conf/files.i386,v retrieving revision 1.130 diff -u -r1.130 files.i386 --- sys/arch/i386/conf/files.i386 8 Oct 2004 13:04:36 -0000 1.130 +++ sys/arch/i386/conf/files.i386 16 Jan 2005 02:03:42 -0000 @@ -127,6 +127,12 @@ attach gscpm at pci file arch/i386/pci/gscpm.c gscpm +# TCPA +device tcpa +file dev/ic/tcpa.c tcpa needs-flag +attach tcpa at pci with tcpa_pci +file dev/pci/tcpa_pci.c tcpa_pci + # PCI-ISA bridge chipsets device pcib: isabus attach pcib at pci Index: sys/arch/i386/i386/conf.c =================================================================== RCS file: /cvs/src/sys/arch/i386/i386/conf.c,v retrieving revision 1.109 diff -u -r1.109 conf.c --- sys/arch/i386/i386/conf.c 3 Oct 2004 21:28:34 -0000 1.109 +++ sys/arch/i386/i386/conf.c 16 Jan 2005 02:03:42 -0000 @@ -127,6 +127,12 @@ (dev_type_stop((*))) enodev, 0, seltrue, \ (dev_type_mmap((*))) enodev, 0 } +/* open, close, read, write, ioctl */ +#define cdev_tcpa_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, (dev_type_poll((*))) enodev, (dev_type_mmap((*))) enodev } + #define mmread mmrw #define mmwrite mmrw @@ -193,6 +199,8 @@ #include "gpr.h" #include "nvram.h" cdev_decl(nvram); +#include "tcpa.h" +cdev_decl(tcpa); /* XXX -- this needs to be supported by config(8)! */ #if (NCOM > 0) && (NPCCOM > 0) @@ -324,6 +332,7 @@ cdev_hotplug_init(NHOTPLUG,hotplug), /* 82: devices hot plugging */ cdev_gpio_init(NGPIO,gpio), /* 83: GPIO interface */ cdev_nvram_init(NNVRAM,nvram), /* 84: NVRAM interface */ + cdev_tcpa_init(NTCPA,tcpa), /* 85: TCPA interface */ }; int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);