aboutsummaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/drm/via_dma.c10
-rw-r--r--drivers/char/drm/via_drm.h2
-rw-r--r--drivers/char/drm/via_ds.c4
-rw-r--r--drivers/char/drm/via_ds.h4
-rw-r--r--drivers/char/drm/via_map.c3
-rw-r--r--drivers/char/drm/via_mm.c15
-rw-r--r--drivers/char/drm/via_video.c3
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c6
-rw-r--r--drivers/char/rio/rioboot.c12
-rw-r--r--drivers/char/rio/rioroute.c2
-rw-r--r--drivers/char/rio/riotable.c2
-rw-r--r--drivers/char/tpm/Kconfig11
-rw-r--r--drivers/char/tpm/Makefile2
-rw-r--r--drivers/char/tpm/tpm_infineon.c467
-rw-r--r--drivers/char/watchdog/acquirewdt.c7
-rw-r--r--drivers/char/watchdog/advantechwdt.c7
-rw-r--r--drivers/char/watchdog/alim1535_wdt.c9
-rw-r--r--drivers/char/watchdog/alim7101_wdt.c7
-rw-r--r--drivers/char/watchdog/eurotechwdt.c7
-rw-r--r--drivers/char/watchdog/i8xx_tco.c7
-rw-r--r--drivers/char/watchdog/ib700wdt.c7
-rw-r--r--drivers/char/watchdog/indydog.c7
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c6
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c6
-rw-r--r--drivers/char/watchdog/machzwd.c7
-rw-r--r--drivers/char/watchdog/mixcomwd.c7
-rw-r--r--drivers/char/watchdog/pcwd.c7
-rw-r--r--drivers/char/watchdog/pcwd_pci.c7
-rw-r--r--drivers/char/watchdog/pcwd_usb.c7
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c7
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c6
-rw-r--r--drivers/char/watchdog/sbc60xxwdt.c7
-rw-r--r--drivers/char/watchdog/sc1200wdt.c7
-rw-r--r--drivers/char/watchdog/sc520_wdt.c7
-rw-r--r--drivers/char/watchdog/scx200_wdt.c6
-rw-r--r--drivers/char/watchdog/shwdt.c6
-rw-r--r--drivers/char/watchdog/softdog.c7
-rw-r--r--drivers/char/watchdog/w83627hf_wdt.c7
-rw-r--r--drivers/char/watchdog/w83877f_wdt.c7
-rw-r--r--drivers/char/watchdog/wafer5823wdt.c7
-rw-r--r--drivers/char/watchdog/wdt.c7
-rw-r--r--drivers/char/watchdog/wdt977.c7
-rw-r--r--drivers/char/watchdog/wdt_pci.c7
45 files changed, 543 insertions, 204 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 43d0cb19ef6..4f27e551929 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -735,7 +735,7 @@ config SGI_IP27_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM
+ depends on RTC!=y && !IA64 && !ARM && !PPC64
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index 82f83945162..4f60f7f4193 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -231,7 +231,7 @@ int via_dma_init(DRM_IOCTL_ARGS)
drm_via_dma_init_t init;
int retcode = 0;
- DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t *) data,
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t __user *) data,
sizeof(init));
switch (init.func) {
@@ -343,7 +343,7 @@ int via_cmdbuffer(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN( dev, filp );
- DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t *) data,
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
sizeof(cmdbuf));
DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
@@ -386,7 +386,7 @@ int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN( dev, filp );
- DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t *) data,
+ DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
sizeof(cmdbuf));
DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf,
@@ -701,7 +701,7 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
return DRM_ERR(EFAULT);
}
- DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t *) data,
+ DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t __user *) data,
sizeof(d_siz));
@@ -735,7 +735,7 @@ via_cmdbuf_size(DRM_IOCTL_ARGS)
}
d_siz.size = tmp_size;
- DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t *) data, d_siz,
+ DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t __user *) data, d_siz,
sizeof(d_siz));
return ret;
}
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index 4588c9bd181..be346bb0a26 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -158,7 +158,7 @@ typedef struct _drm_via_dma_init {
} drm_via_dma_init_t;
typedef struct _drm_via_cmdbuffer {
- char *buf;
+ char __user *buf;
unsigned long size;
} drm_via_cmdbuffer_t;
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
index daf3df75a20..5c71e089246 100644
--- a/drivers/char/drm/via_ds.c
+++ b/drivers/char/drm/via_ds.c
@@ -133,7 +133,7 @@ memHeap_t *via_mmInit(int ofs, int size)
PMemBlock blocks;
if (size <= 0)
- return 0;
+ return NULL;
blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
@@ -143,7 +143,7 @@ memHeap_t *via_mmInit(int ofs, int size)
blocks->free = 1;
return (memHeap_t *) blocks;
} else
- return 0;
+ return NULL;
}
static TMemBlock *SliceBlock(TMemBlock * p,
diff --git a/drivers/char/drm/via_ds.h b/drivers/char/drm/via_ds.h
index be9c7f9f1ae..d2bb9f37ca3 100644
--- a/drivers/char/drm/via_ds.h
+++ b/drivers/char/drm/via_ds.h
@@ -61,8 +61,8 @@ struct mem_block_t {
struct mem_block_t *heap;
int ofs, size;
int align;
- int free:1;
- int reserved:1;
+ unsigned int free:1;
+ unsigned int reserved:1;
};
typedef struct mem_block_t TMemBlock;
typedef struct mem_block_t *PMemBlock;
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index 0be829b6ec6..bb171139e73 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -95,7 +95,8 @@ int via_map_init(DRM_IOCTL_ARGS)
DRM_DEBUG("%s\n", __FUNCTION__);
- DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t *) data, sizeof(init));
+ DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t __user *) data,
+ sizeof(init));
switch (init.func) {
case VIA_INIT_MAP:
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index c22712f44d4..13921f3c0ec 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -76,7 +76,8 @@ int via_agp_init(DRM_IOCTL_ARGS)
{
drm_via_agp_t agp;
- DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t *) data, sizeof(agp));
+ DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
+ sizeof(agp));
AgpHeap = via_mmInit(agp.offset, agp.size);
@@ -92,7 +93,7 @@ int via_fb_init(DRM_IOCTL_ARGS)
{
drm_via_fb_t fb;
- DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t *) data, sizeof(fb));
+ DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
FBHeap = via_mmInit(fb.offset, fb.size);
@@ -193,19 +194,20 @@ int via_mem_alloc(DRM_IOCTL_ARGS)
{
drm_via_mem_t mem;
- DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));
+ DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
+ sizeof(mem));
switch (mem.type) {
case VIDEO:
if (via_fb_alloc(&mem) < 0)
return -EFAULT;
- DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
+ DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
sizeof(mem));
return 0;
case AGP:
if (via_agp_alloc(&mem) < 0)
return -EFAULT;
- DRM_COPY_TO_USER_IOCTL((drm_via_mem_t *) data, mem,
+ DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
sizeof(mem));
return 0;
}
@@ -289,7 +291,8 @@ int via_mem_free(DRM_IOCTL_ARGS)
{
drm_via_mem_t mem;
- DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t *) data, sizeof(mem));
+ DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
+ sizeof(mem));
switch (mem.type) {
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
index 37a61c67b29..1e2d444587b 100644
--- a/drivers/char/drm/via_video.c
+++ b/drivers/char/drm/via_video.c
@@ -76,7 +76,8 @@ via_decoder_futex(DRM_IOCTL_ARGS)
DRM_DEBUG("%s\n", __FUNCTION__);
- DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t *) data, sizeof(fx));
+ DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t __user *) data,
+ sizeof(fx));
if (fx.lock > VIA_NR_XVMC_LOCKS)
return -EFAULT;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 298574e1606..a44b97304e9 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1726,7 +1726,7 @@ static int dmi_table(u32 base, int len, int num)
return status;
}
-inline static int dmi_checksum(u8 *buf)
+static inline int dmi_checksum(u8 *buf)
{
u8 sum=0;
int a;
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index fcd1c02a32c..d35a953961c 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -131,11 +131,7 @@
#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
#endif
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int nowayout = 1;
-#else
-static int nowayout;
-#endif
+static int nowayout = WATCHDOG_NOWAYOUT;
static ipmi_user_t watchdog_user = NULL;
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index a8be11dfcba..34cbb13aad4 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -902,7 +902,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
(HostP->Mapping[entry].RtaUniqueNum==RtaUniq))
{
HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT;
-#if NEED_TO_FIX
+#ifdef NEED_TO_FIX
RIO_SV_BROADCAST(HostP->svFlags[entry]);
#endif
if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT )
@@ -918,7 +918,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
{
entry2 = HostP->Mapping[entry].ID2 - 1;
HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT;
-#if NEED_TO_FIX
+#ifdef NEED_TO_FIX
RIO_SV_BROADCAST(HostP->svFlags[entry2]);
#endif
sysport = HostP->Mapping[entry2].SysPort;
@@ -1143,7 +1143,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN );
HostP->Mapping[entry].Flags =
SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
-#if NEED_TO_FIX
+#ifdef NEED_TO_FIX
RIO_SV_BROADCAST(HostP->svFlags[entry]);
#endif
RIOReMapPorts( p, HostP, &HostP->Mapping[entry] );
@@ -1159,7 +1159,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
"This RTA has a tentative entry on another host - delete that entry (1)\n");
HostP->Mapping[entry].Flags =
SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
-#if NEED_TO_FIX
+#ifdef NEED_TO_FIX
RIO_SV_BROADCAST(HostP->svFlags[entry]);
#endif
}
@@ -1169,7 +1169,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
{
HostP->Mapping[entry2].Flags = SLOT_IN_USE |
RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-#if NEED_TO_FIX
+#ifdef NEED_TO_FIX
RIO_SV_BROADCAST(HostP->svFlags[entry2]);
#endif
HostP->Mapping[entry2].SysPort = MapP2->SysPort;
@@ -1188,7 +1188,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
else
HostP->Mapping[entry2].Flags = SLOT_TENTATIVE |
RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-#if NEED_TO_FIX
+#ifdef NEED_TO_FIX
RIO_SV_BROADCAST(HostP->svFlags[entry2]);
#endif
bzero( (caddr_t)MapP2, sizeof(struct Map) );
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
index 106b31f48a2..e9564c9fb37 100644
--- a/drivers/char/rio/rioroute.c
+++ b/drivers/char/rio/rioroute.c
@@ -1023,7 +1023,7 @@ RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
if (link < LINKS_PER_UNIT)
return 1;
-#if NEED_TO_FIX_THIS
+#ifdef NEED_TO_FIX_THIS
/* Ok so all the links are disconnected. But we may have only just
** made this slot tentative and not yet received a topology update.
** Lets check how long ago we made it tentative.
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
index 8fb26ad2aa1..e45bc275907 100644
--- a/drivers/char/rio/riotable.c
+++ b/drivers/char/rio/riotable.c
@@ -771,7 +771,7 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP )
if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
-#if NEED_TO_FIX
+#ifdef NEED_TO_FIX
RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]);
#endif
if (MapP->Flags & RTA16_SECOND_SLOT)
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 7a969778915..94a3b3e20bf 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -35,5 +35,16 @@ config TCG_ATMEL
will be accessible from within Linux. To compile this driver
as a module, choose M here; the module will be called tpm_atmel.
+config TCG_INFINEON
+ tristate "Infineon Technologies SLD 9630 TPM Interface"
+ depends on TCG_TPM
+ ---help---
+ If you have a TPM security chip from Infineon Technologies
+ say Yes and it will be accessible from within Linux. To
+ compile this driver as a module, choose M here; the module
+ will be called tpm_infineon.
+ Further information on this driver and the supported hardware
+ can be found at http://www.prosec.rub.de/tpm
+
endmenu
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 736d3df266f..2392e404e8d 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_TCG_TPM) += tpm.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
-
+obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
new file mode 100644
index 00000000000..0e3241645c1
--- /dev/null
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -0,0 +1,467 @@
+/*
+ * Description:
+ * Device Driver for the Infineon Technologies
+ * SLD 9630 TT Trusted Platform Module
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
+ * Applied Data Security Group, Ruhr-University Bochum, Germany
+ * Project-Homepage: http://www.prosec.rub.de/tpm
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* Infineon specific definitions */
+/* maximum number of WTX-packages */
+#define TPM_MAX_WTX_PACKAGES 50
+/* msleep-Time for WTX-packages */
+#define TPM_WTX_MSLEEP_TIME 20
+/* msleep-Time --> Interval to check status register */
+#define TPM_MSLEEP_TIME 3
+/* gives number of max. msleep()-calls before throwing timeout */
+#define TPM_MAX_TRIES 5000
+#define TCPA_INFINEON_DEV_VEN_VALUE 0x15D1
+#define TPM_DATA (TPM_ADDR + 1) & 0xff
+
+/* TPM header definitions */
+enum infineon_tpm_header {
+ TPM_VL_VER = 0x01,
+ TPM_VL_CHANNEL_CONTROL = 0x07,
+ TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
+ TPM_VL_CHANNEL_TPM = 0x0B,
+ TPM_VL_CONTROL = 0x00,
+ TPM_INF_NAK = 0x15,
+ TPM_CTRL_WTX = 0x10,
+ TPM_CTRL_WTX_ABORT = 0x18,
+ TPM_CTRL_WTX_ABORT_ACK = 0x18,
+ TPM_CTRL_ERROR = 0x20,
+ TPM_CTRL_CHAININGACK = 0x40,
+ TPM_CTRL_CHAINING = 0x80,
+ TPM_CTRL_DATA = 0x04,
+ TPM_CTRL_DATA_CHA = 0x84,
+ TPM_CTRL_DATA_CHA_ACK = 0xC4
+};
+
+enum infineon_tpm_register {
+ WRFIFO = 0x00,
+ RDFIFO = 0x01,
+ STAT = 0x02,
+ CMD = 0x03
+};
+
+enum infineon_tpm_command_bits {
+ CMD_DIS = 0x00,
+ CMD_LP = 0x01,
+ CMD_RES = 0x02,
+ CMD_IRQC = 0x06
+};
+
+enum infineon_tpm_status_bits {
+ STAT_XFE = 0x00,
+ STAT_LPA = 0x01,
+ STAT_FOK = 0x02,
+ STAT_TOK = 0x03,
+ STAT_IRQA = 0x06,
+ STAT_RDA = 0x07
+};
+
+/* some outgoing values */
+enum infineon_tpm_values {
+ CHIP_ID1 = 0x20,
+ CHIP_ID2 = 0x21,
+ TPM_DAR = 0x30,
+ RESET_LP_IRQC_DISABLE = 0x41,
+ ENABLE_REGISTER_PAIR = 0x55,
+ IOLIMH = 0x60,
+ IOLIML = 0x61,
+ DISABLE_REGISTER_PAIR = 0xAA,
+ IDVENL = 0xF1,
+ IDVENH = 0xF2,
+ IDPDL = 0xF3,
+ IDPDH = 0xF4
+};
+
+static int number_of_wtx;
+
+static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
+{
+ int status;
+ int check = 0;
+ int i;
+
+ if (clear_wrfifo) {
+ for (i = 0; i < 4096; i++) {
+ status = inb(chip->vendor->base + WRFIFO);
+ if (status == 0xff) {
+ if (check == 5)
+ break;
+ else
+ check++;
+ }
+ }
+ }
+ /* Note: The values which are currently in the FIFO of the TPM
+ are thrown away since there is no usage for them. Usually,
+ this has nothing to say, since the TPM will give its answer
+ immediately or will be aborted anyway, so the data here is
+ usually garbage and useless.
+ We have to clean this, because the next communication with
+ the TPM would be rubbish, if there is still some old data
+ in the Read FIFO.
+ */
+ i = 0;
+ do {
+ status = inb(chip->vendor->base + RDFIFO);
+ status = inb(chip->vendor->base + STAT);
+ i++;
+ if (i == TPM_MAX_TRIES)
+ return -EIO;
+ } while ((status & (1 << STAT_RDA)) != 0);
+ return 0;
+}
+
+static int wait(struct tpm_chip *chip, int wait_for_bit)
+{
+ int status;
+ int i;
+ for (i = 0; i < TPM_MAX_TRIES; i++) {
+ status = inb(chip->vendor->base + STAT);
+ /* check the status-register if wait_for_bit is set */
+ if (status & 1 << wait_for_bit)
+ break;
+ msleep(TPM_MSLEEP_TIME);
+ }
+ if (i == TPM_MAX_TRIES) { /* timeout occurs */
+ if (wait_for_bit == STAT_XFE)
+ dev_err(&chip->pci_dev->dev,
+ "Timeout in wait(STAT_XFE)\n");
+ if (wait_for_bit == STAT_RDA)
+ dev_err(&chip->pci_dev->dev,
+ "Timeout in wait(STAT_RDA)\n");
+ return -EIO;
+ }
+ return 0;
+};
+
+static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
+{
+ wait(chip, STAT_XFE);
+ outb(sendbyte, chip->vendor->base + WRFIFO);
+}
+
+ /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
+ calculation time, it sends a WTX-package, which has to be acknowledged
+ or aborted. This usually occurs if you are hammering the TPM with key
+ creation. Set the maximum number of WTX-packages in the definitions
+ above, if the number is reached, the waiting-time will be denied
+ and the TPM command has to be resend.
+ */
+
+static void tpm_wtx(struct tpm_chip *chip)
+{
+ number_of_wtx++;
+ dev_info(&chip->pci_dev->dev, "Granting WTX (%02d / %02d)\n",
+ number_of_wtx, TPM_MAX_WTX_PACKAGES);
+ wait_and_send(chip, TPM_VL_VER);
+ wait_and_send(chip, TPM_CTRL_WTX);
+ wait_and_send(chip, 0x00);
+ wait_and_send(chip, 0x00);
+ msleep(TPM_WTX_MSLEEP_TIME);
+}
+
+static void tpm_wtx_abort(struct tpm_chip *chip)
+{
+ dev_info(&chip->pci_dev->dev, "Aborting WTX\n");
+ wait_and_send(chip, TPM_VL_VER);
+ wait_and_send(chip, TPM_CTRL_WTX_ABORT);
+ wait_and_send(chip, 0x00);
+ wait_and_send(chip, 0x00);
+ number_of_wtx = 0;
+ msleep(TPM_WTX_MSLEEP_TIME);
+}
+
+static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ int i;
+ int ret;
+ u32 size = 0;
+
+recv_begin:
+ /* start receiving header */
+ for (i = 0; i < 4; i++) {
+ ret = wait(chip, STAT_RDA);
+ if (ret)
+ return -EIO;
+ buf[i] = inb(chip->vendor->base + RDFIFO);
+ }
+
+ if (buf[0] != TPM_VL_VER) {
+ dev_err(&chip->pci_dev->dev,
+ "Wrong transport protocol implementation!\n");
+ return -EIO;
+ }
+
+ if (buf[1] == TPM_CTRL_DATA) {
+ /* size of the data received */
+ size = ((buf[2] << 8) | buf[3]);
+
+ for (i = 0; i < size; i++) {
+ wait(chip, STAT_RDA);
+ buf[i] = inb(chip->vendor->base + RDFIFO);
+ }
+
+ if ((size == 0x6D00) && (buf[1] == 0x80)) {
+ dev_err(&chip->pci_dev->dev,
+ "Error handling on vendor layer!\n");
+ return -EIO;
+ }
+
+ for (i = 0; i < size; i++)
+ buf[i] = buf[i + 6];
+
+ size = size - 6;
+ return size;
+ }
+
+ if (buf[1] == TPM_CTRL_WTX) {
+ dev_info(&chip->pci_dev->dev, "WTX-package received\n");
+ if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
+ tpm_wtx(chip);
+ goto recv_begin;
+ } else {
+ tpm_wtx_abort(chip);
+ goto recv_begin;
+ }
+ }
+
+ if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
+ dev_info(&chip->pci_dev->dev, "WTX-abort acknowledged\n");
+ return size;
+ }
+
+ if (buf[1] == TPM_CTRL_ERROR) {
+ dev_err(&chip->pci_dev->dev, "ERROR-package received:\n");
+ if (buf[4] == TPM_INF_NAK)
+ dev_err(&chip->pci_dev->dev,
+ "-> Negative acknowledgement"
+ " - retransmit command!\n");
+ return -EIO;
+ }
+ return -EIO;
+}
+
+static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ int i;
+ int ret;
+ u8 count_high, count_low, count_4, count_3, count_2, count_1;
+
+ /* Disabling Reset, LP and IRQC */
+ outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
+
+ ret = empty_fifo(chip, 1);
+ if (ret) {
+ dev_err(&chip->pci_dev->dev, "Timeout while clearing FIFO\n");
+ return -EIO;
+ }
+
+ ret = wait(chip, STAT_XFE);
+ if (ret)
+ return -EIO;
+
+ count_4 = (count & 0xff000000) >> 24;
+ count_3 = (count & 0x00ff0000) >> 16;
+ count_2 = (count & 0x0000ff00) >> 8;
+ count_1 = (count & 0x000000ff);
+ count_high = ((count + 6) & 0xffffff00) >> 8;
+ count_low = ((count + 6) & 0x000000ff);
+
+ /* Sending Header */
+ wait_and_send(chip, TPM_VL_VER);
+ wait_and_send(chip, TPM_CTRL_DATA);
+ wait_and_send(chip, count_high);
+ wait_and_send(chip, count_low);
+
+ /* Sending Data Header */
+ wait_and_send(chip, TPM_VL_VER);
+ wait_and_send(chip, TPM_VL_CHANNEL_TPM);
+ wait_and_send(chip, count_4);
+ wait_and_send(chip, count_3);
+ wait_and_send(chip, count_2);
+ wait_and_send(chip, count_1);
+
+ /* Sending Data */
+ for (i = 0; i < count; i++) {
+ wait_and_send(chip, buf[i]);
+ }
+ return count;
+}
+
+static void tpm_inf_cancel(struct tpm_chip *chip)
+{
+ /* Nothing yet!
+ This has something to do with the internal functions
+ of the TPM. Abort isn't really necessary...
+ */
+}
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *inf_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr,
+ NULL,
+};
+
+static struct attribute_group inf_attr_grp = {.attrs = inf_attrs };
+
+static struct file_operations inf_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_inf = {
+ .recv = tpm_inf_recv,
+ .send = tpm_inf_send,
+ .cancel = tpm_inf_cancel,
+ .req_complete_mask = 0,
+ .req_complete_val = 0,
+ .attr_group = &inf_attr_grp,
+ .miscdev = {.fops = &inf_ops,},
+};
+
+static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ int rc = 0;
+ u8 iol, ioh;
+ int vendorid[2];
+ int version[2];
+ int productid[2];
+
+ if (pci_enable_device(pci_dev))
+ return -EIO;
+
+ dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
+
+ /* query chip for its vendor, its version number a.s.o. */
+ outb(ENABLE_REGISTER_PAIR, TPM_ADDR);
+ outb(IDVENL, TPM_ADDR);
+ vendorid[1] = inb(TPM_DATA);
+ outb(IDVENH, TPM_ADDR);
+ vendorid[0] = inb(TPM_DATA);
+ outb(IDPDL, TPM_ADDR);
+ productid[1] = inb(TPM_DATA);
+ outb(IDPDH, TPM_ADDR);
+ productid[0] = inb(TPM_DATA);
+ outb(CHIP_ID1, TPM_ADDR);
+ version[1] = inb(TPM_DATA);
+ outb(CHIP_ID2, TPM_ADDR);
+ version[0] = inb(TPM_DATA);
+
+ if ((vendorid[0] << 8 | vendorid[1]) == (TCPA_INFINEON_DEV_VEN_VALUE)) {
+
+ /* read IO-ports from TPM */
+ outb(IOLIMH, TPM_ADDR);
+ ioh = inb(TPM_DATA);
+ outb(IOLIML, TPM_ADDR);
+ iol = inb(TPM_DATA);
+ tpm_inf.base = (ioh << 8) | iol;
+
+ if (tpm_inf.base == 0) {
+ dev_err(&pci_dev->dev, "No IO-ports set!\n");
+ pci_disable_device(pci_dev);
+ return -ENODEV;