From patchwork Mon Jul 6 18:43:44 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Warren Turkal X-Patchwork-Id: 34285 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n66IhplY024395 for ; Mon, 6 Jul 2009 18:43:52 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753001AbZGFSnr (ORCPT ); Mon, 6 Jul 2009 14:43:47 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752217AbZGFSnr (ORCPT ); Mon, 6 Jul 2009 14:43:47 -0400 Received: from smtp-out.google.com ([216.239.33.17]:32627 "EHLO smtp-out.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752013AbZGFSnq (ORCPT ); Mon, 6 Jul 2009 14:43:46 -0400 Received: from spaceape8.eur.corp.google.com (spaceape8.eur.corp.google.com [172.28.16.142]) by smtp-out.google.com with ESMTP id n66IhmDP005295 for ; Mon, 6 Jul 2009 19:43:48 +0100 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=google.com; s=beta; t=1246905828; bh=Syh7DYbeFIsRP6hZXAMRcS/6804=; h=DomainKey-Signature:From:To:Cc:Subject:Date:Message-Id:X-Mailer: In-Reply-To:References; b=dkvvFSN71+Wz/lFkHMAoF1FsdGMT1NstZNc/R/UA HTxdbz90RJvIauFAdxgjiyjwmBN3XH55PwAyrfsKY5hCUg== DomainKey-Signature: a=rsa-sha1; s=beta; d=google.com; c=nofws; q=dns; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=Xgz35fgVeeifYb4GGzQTeQzgPZO8D37qMopeRuJ1aM2NRVp+yCGahEeuCxT/fpLDH gSUO85FlhitEcZsJEXWaQ== Received: from localhost (braindead.mtv.corp.google.com [172.22.65.110]) by spaceape8.eur.corp.google.com with ESMTP id n66IhjpK011653; Mon, 6 Jul 2009 11:43:46 -0700 Received: by localhost (Postfix, from userid 60405) id 4695A1B817F; Mon, 6 Jul 2009 11:43:45 -0700 (PDT) From: Warren Turkal To: linux-pci@vger.kernel.org Cc: Warren Turkal Subject: [PATCH] Add qword read/write support. Date: Mon, 6 Jul 2009 11:43:44 -0700 Message-Id: <1246905824-12695-2-git-send-email-turkal@google.com> X-Mailer: git-send-email 1.5.4.3 In-Reply-To: <1246905824-12695-1-git-send-email-turkal@google.com> References: <> <1246905824-12695-1-git-send-email-turkal@google.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Signed-off-by: Warren Turkal --- lib/access.c | 15 +++++++++++++++ lib/pci.h | 2 ++ lib/sysdep.h | 18 ++++++++++++++++++ lib/types.h | 35 +++++++++++++++++++++++------------ setpci.c | 19 ++++++++++++++++--- setpci.man | 6 +++--- 6 files changed, 77 insertions(+), 18 deletions(-) diff --git a/lib/access.c b/lib/access.c index 691df39..b8addea 100644 --- a/lib/access.c +++ b/lib/access.c @@ -98,6 +98,14 @@ pci_read_long(struct pci_dev *d, int pos) return le32_to_cpu(buf); } +u64 +pci_read_quad(struct pci_dev *d, int pos) +{ + u64 buf; + pci_read_data(d, &buf, pos, 8); + return le64_to_cpu(buf); +} + int pci_read_block(struct pci_dev *d, int pos, byte *buf, int len) { @@ -141,6 +149,13 @@ pci_write_long(struct pci_dev *d, int pos, u32 data) } int +pci_write_quad(struct pci_dev *d, int pos, u64 data) +{ + u64 buf = cpu_to_le64(data); + return pci_write_data(d, &buf, pos, 8); +} + +int pci_write_block(struct pci_dev *d, int pos, byte *buf, int len) { if (pos < d->cache_len) diff --git a/lib/pci.h b/lib/pci.h index 7a5a6b8..71d673f 100644 --- a/lib/pci.h +++ b/lib/pci.h @@ -147,11 +147,13 @@ struct pci_dev { u8 pci_read_byte(struct pci_dev *, int pos) PCI_ABI; /* Access to configuration space */ u16 pci_read_word(struct pci_dev *, int pos) PCI_ABI; u32 pci_read_long(struct pci_dev *, int pos) PCI_ABI; +u64 pci_read_quad(struct pci_dev *, int pos) PCI_ABI; int pci_read_block(struct pci_dev *, int pos, u8 *buf, int len) PCI_ABI; int pci_read_vpd(struct pci_dev *d, int pos, u8 *buf, int len) PCI_ABI; int pci_write_byte(struct pci_dev *, int pos, u8 data) PCI_ABI; int pci_write_word(struct pci_dev *, int pos, u16 data) PCI_ABI; int pci_write_long(struct pci_dev *, int pos, u32 data) PCI_ABI; +int pci_write_quad(struct pci_dev *, int pos, u64 data) PCI_ABI; int pci_write_block(struct pci_dev *, int pos, u8 *buf, int len) PCI_ABI; int pci_fill_info(struct pci_dev *, int flags) PCI_ABI; /* Fill in device information */ diff --git a/lib/sysdep.h b/lib/sysdep.h index 2a25c93..4701884 100644 --- a/lib/sysdep.h +++ b/lib/sysdep.h @@ -27,8 +27,10 @@ typedef u16 word; #include #define cpu_to_le16 __cpu_to_le16 #define cpu_to_le32 __cpu_to_le32 +#define cpu_to_le64 __cpu_to_le64 #define le16_to_cpu __le16_to_cpu #define le32_to_cpu __le32_to_cpu +#define le64_to_cpu __le64_to_cpu #else @@ -63,8 +65,10 @@ typedef u16 word; #if BYTE_ORDER == BIG_ENDIAN #define cpu_to_le16 swab16 #define cpu_to_le32 swab32 +#define cpu_to_le64 swab64 #define le16_to_cpu swab16 #define le32_to_cpu swab32 +#define le64_to_cpu swab64 static inline word swab16(word w) { @@ -78,11 +82,25 @@ static inline u32 swab32(u32 w) ((w & 0x0000ff00) << 8) | ((w & 0x000000ff) << 24); } + +static inline u64 swab64(u64 w) +{ + return ((w & 0xff00000000000000) >> 56) | + ((w & 0x00ff000000000000) >> 40) | + ((w & 0x0000ff0000000000) >> 24) | + ((w & 0x000000ff00000000) >> 8) | + ((w & 0x00000000ff000000) << 8) | + ((w & 0x0000000000ff0000) << 24) | + ((w & 0x000000000000ff00) << 40) | + ((w & 0x00000000000000ff) << 56); +} #else #define cpu_to_le16(x) (x) #define cpu_to_le32(x) (x) +#define cpu_to_le64(x) (x) #define le16_to_cpu(x) (x) #define le32_to_cpu(x) (x) +#define le64_to_cpu(x) (x) #endif #endif diff --git a/lib/types.h b/lib/types.h index 3e0e5c3..818872d 100644 --- a/lib/types.h +++ b/lib/types.h @@ -15,39 +15,50 @@ typedef BYTE u8; typedef WORD u16; typedef DWORD u32; +typedef unsigned __int64 u64; + +#ifdef PCI_HAVE_64BIT_ADDRESS +#include +#if ULONG_MAX > 0xffffffff +#define PRIu64 "l" +#else +#define PRIu64 "ll" +#endif +#endif + #elif defined(PCI_HAVE_STDINT_H) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) -#include +#include typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; +typedef uint64_t u64; #else +#include typedef u_int8_t u8; typedef u_int16_t u16; typedef u_int32_t u32; +typedef u_int64_t u64; #endif +#endif /* PCI_HAVE_Uxx_TYPES */ + #ifdef PCI_HAVE_64BIT_ADDRESS #include #if ULONG_MAX > 0xffffffff -typedef unsigned long u64; -#define PCI_U64_FMT "l" +typedef unsigned long pciaddr_t; #else -typedef unsigned long long u64; -#define PCI_U64_FMT "ll" -#endif +typedef unsigned long long pciaddr_t; #endif -#endif /* PCI_HAVE_Uxx_TYPES */ +#define PCIADDR_T_FMT "%08" PRIu64 "x" +#define PCIADDR_PORT_FMT "%04" PRIu64 "x" -#ifdef PCI_HAVE_64BIT_ADDRESS -typedef u64 pciaddr_t; -#define PCIADDR_T_FMT "%08" PCI_U64_FMT "x" -#define PCIADDR_PORT_FMT "%04" PCI_U64_FMT "x" #else typedef u32 pciaddr_t; #define PCIADDR_T_FMT "%08x" #define PCIADDR_PORT_FMT "%04x" -#endif + +#endif /* PCI_HAVE_64BIT_ADDRESS */ #ifdef PCI_ARCH_SPARC64 /* On sparc64 Linux the kernel reports remapped port addresses and IRQ numbers */ diff --git a/setpci.c b/setpci.c index 97740e8..30195b0 100644 --- a/setpci.c +++ b/setpci.c @@ -12,6 +12,7 @@ #include #include #include +#include #define PCIUTILS_SETPCI #include "pciutils.h" @@ -73,9 +74,10 @@ trace(const char *fmt, ...) static void exec_op(struct op *op, struct pci_dev *dev) { - const char * const formats[] = { NULL, " %02x", " %04x", NULL, " %08x" }; - const char * const mask_formats[] = { NULL, " %02x->(%02x:%02x)->%02x", " %04x->(%04x:%04x)->%04x", NULL, " %08x->(%08x:%08x)->%08x" }; - unsigned int i, x, y; + const char * const formats[] = { NULL, " %02x", " %04x", NULL, " %08x", NULL, NULL, NULL, " %016" PRIu64 "x"}; + const char * const mask_formats[] = { NULL, " %02x->(%02x:%02x)->%02x", " %04x->(%04x:%04x)->%04x", NULL, " %08x->(%08x:%08x)->%08x", NULL, NULL, NULL, " %016" PRIu64 "x->(%016" PRIu64 "x:%016" PRIu64 "x)->%016" PRIu64 "x"}; + unsigned int i; + u64 x, y; int addr = 0; int width = op->width; char slot[16]; @@ -120,6 +122,9 @@ exec_op(struct op *op, struct pci_dev *dev) case 2: y = pci_read_word(dev, addr); break; + case 8: + y = pci_read_quad(dev, addr); + break; default: y = pci_read_long(dev, addr); break; @@ -137,6 +142,9 @@ exec_op(struct op *op, struct pci_dev *dev) case 2: pci_write_word(dev, addr, x); break; + case 8: + pci_write_quad(dev, addr, x); + break; default: pci_write_long(dev, addr, x); break; @@ -157,6 +165,9 @@ exec_op(struct op *op, struct pci_dev *dev) case 2: x = pci_read_word(dev, addr); break; + case 8: + x = pci_read_quad(dev, addr); + break; default: x = pci_read_long(dev, addr); break; @@ -600,6 +611,8 @@ static void parse_op(char *c, struct pci_dev **selected_devices) op->width = 2; break; case 'L': op->width = 4; break; + case 'Q': + op->width = 8; break; default: parse_err("Invalid width \"%c\"", *width); } diff --git a/setpci.man b/setpci.man index 6c1ad8c..21ecf35 100644 --- a/setpci.man +++ b/setpci.man @@ -149,9 +149,9 @@ Each of the previous formats can be followed by \fB+offset\fP to add an offset (a hex number) to the address. This feature can be useful for addressing of registers living within a capability, or to modify parts of standard registers. \IP \(bu -Finally, you should append a width specifier \fB.B\fP, \fB.W\fP, or \fB.L\fP to choose -how many bytes (1, 2, or 4) should be transferred. The width can be omitted if you are -accessing a named register whose width is well known. +Finally, you should append a width specifier \fB.B\fP, \fB.W\fP, \fB.L\fP, or \fB.Q\fP +to choose how many bytes (1, 2, 4, or 8) should be transferred. The width can be +omitted if you are accessing a named register whose width is well known. .PP All names of registers and width specifiers are case-insensitive.