devLib2  2.12
pcish.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * devLib2 is distributed subject to a Software License Agreement found
5 * in file LICENSE that is included with this distribution.
6 \*************************************************************************/
7 /*
8  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
9  */
10 
11 #include <stdlib.h>
12 
13 #include <epicsVersion.h>
14 #include <epicsAssert.h>
15 #include <epicsTypes.h>
16 #include <epicsExport.h>
17 #include <epicsStdio.h>
18 #include <errlog.h>
19 #include <iocsh.h>
20 #include <epicsMMIO.h>
21 #include <devLibPCI.h>
22 
23 static const epicsPCIDevice *diagdev;
24 static volatile void *diagbase;
25 static epicsUInt32 diaglen;
26 
27 struct bdf {
28  unsigned int b,d,f;
30 };
31 
32 static
33 int matchbdf(void* raw,const epicsPCIDevice* dev)
34 {
35  struct bdf *loc=raw;
36 
37  if(dev->bus!=loc->b || dev->device!=loc->d || dev->function!=loc->f)
38  return 0;
39  loc->dev=dev;
40  return 1;
41 }
42 
43 void pcidiagset(int b, int d, int f, int bar, int vendor, int device, int exact)
44 {
45  epicsUInt32 len=0;
46  struct bdf loc;
47  epicsPCIID ids[] = {
48  DEVPCI_DEVICE_VENDOR(device,vendor),
50  };
51 
52  diagbase = NULL;
53  diagdev = NULL;
54  diaglen = 0;
55 
56  printf("Looking for %x:%x.%x\n", b, d, f);
57 
58  if(vendor==0 && !exact)
59  ids[0].vendor=DEVPCI_ANY_VENDOR;
60  if(device==0 && !exact)
61  ids[0].device=DEVPCI_ANY_DEVICE;
62 
63  loc.b=b;
64  loc.d=d;
65  loc.f=f;
66  loc.dev=0;
67 
68  if(devPCIFindCB(ids, &matchbdf, (void*)&loc, 0)) {
69  fprintf(stderr, "Error searching\n");
70  return;
71  }
72 
73  if(!loc.dev) {
74  fprintf(stderr, "No such device\n");
75  return;
76  }
77 
78  printf("Mapping %x:%x.%x\n", loc.dev->bus, loc.dev->device, loc.dev->function);
79 
80 #if defined(linux)
81  if(devPCIBarLen(loc.dev, bar, &len)) {
82  fprintf(stderr, "Failed to get BAR length\n");
83  len=0;
84  }
85 #endif
86 
87  if(devPCIToLocalAddr(loc.dev, bar, &diagbase, 0)) {
88  fprintf(stderr, "Failed to map BAR\n");
89  return;
90  }
91  diagdev = loc.dev;
92  diaglen=len;
93 
94 #if defined(__linux__)
95  printf("BAR %d from %p for %u bytes\n",bar, (void*)diagbase, (unsigned)diaglen);
96 #else
97  printf("BAR %d from %p\n",bar, (void*)diagbase);
98 #endif
99 
100 }
101 
102 static int check_args(int dmod, unsigned int offset, unsigned int count)
103 {
104  switch(dmod){
105  case 8:
106  case 16:
107  case 32:
108  break;
109  default:
110  fprintf(stderr, "Invalid data width %d\n",dmod);
111  return 1;
112  }
113 
114 #if defined(__linux__)
115  if(offset>=diaglen || offset+count>diaglen) {
116  fprintf(stderr, "Invalid offset and/or count\n");
117  return 1;
118  }
119 #endif
120  return 0;
121 }
122 
123 void pciwrite(int dmod, int offset, int value)
124 {
125  epicsUInt32 tval = value;
126  volatile char* dptr = offset + (volatile char*)diagbase;
127 
128  if(!diagbase) {
129  fprintf(stderr, "Run pcidiagset first\n");
130  return;
131  }
132 
133  if(check_args(dmod, offset, 1))
134  return;
135 
136  switch(dmod){
137  case 8: iowrite8(dptr, tval); break;
138  case 16: nat_iowrite16(dptr, tval); break;
139  case 32: nat_iowrite32(dptr, tval); break;
140  }
141 }
142 
143 void pciread(int dmod, int offset, int count)
144 {
145  epicsUInt32 tval;
146  volatile char* dptr;
147  short dbytes;
148  int i;
149 
150  if(!diagbase) {
151  fprintf(stderr, "Run pcidiagset first\n");
152  return;
153  }
154 
155  if(check_args(dmod, offset, count))
156  return;
157 
158  dbytes=dmod/8;
159 
160  count/=dbytes;
161  if(count==0) count=1;
162 
163  for(i=0, dptr=offset+(volatile char*)diagbase; i<count; i++, dptr+=dbytes) {
164  if ((i*dbytes)%16==0)
165  printf("\n0x%08x ",i*dbytes);
166  else if ((i*dbytes)%4==0)
167  printf(" ");
168 
169  switch(dmod){
170  case 8: tval=ioread8(dptr); printf("%02x",tval);break;
171  case 16: tval=nat_ioread16(dptr);printf("%04x",tval);break;
172  case 32: tval=nat_ioread32(dptr);printf("%08x",tval);break;
173  }
174  }
175  printf("\n");
176 }
177 
178 void pciconfread(int dmod, int offset, int count)
179 {
180  int err = 0;
181  short dbytes;
182 
183  if(!diagdev) {
184  fprintf(stderr, "Run pcidiagset first\n");
185  return;
186  }
187 
188  if(check_args(dmod, offset, count))
189  return;
190 
191  dbytes=dmod/8;
192 
193  count/=dbytes;
194  if(count==0) count=1;
195 
196  for(;count && !err;offset+=dbytes,count--) {
197  epicsUInt8 u8;
198  epicsUInt16 u16;
199  epicsUInt32 u32;
200  printf("0x%04x ", offset);
201  switch(dmod) {
202  case 8: err = devPCIConfigRead8(diagdev, offset, &u8); printf("%02x\n", u8); break;
203  case 16: err = devPCIConfigRead16(diagdev, offset, &u16); printf("%04x\n", u16); break;
204  case 32: err = devPCIConfigRead32(diagdev, offset, &u32); printf("%08x\n", u32); break;
205  default:
206  fprintf(stderr, "Invalid dmod %d, must be 8, 16, or 32\n", dmod);
207  break;
208  }
209  }
210  if(err)
211  fprintf(stderr, "read error %d\n", err);
212 }
213 
214 static const iocshArg pcidiagsetArg0 = { "Bus",iocshArgInt};
215 static const iocshArg pcidiagsetArg1 = { "Device",iocshArgInt};
216 static const iocshArg pcidiagsetArg2 = { "Function",iocshArgInt};
217 static const iocshArg pcidiagsetArg3 = { "BAR",iocshArgInt};
218 static const iocshArg pcidiagsetArg4 = { "PCI vendor ID",iocshArgInt};
219 static const iocshArg pcidiagsetArg5 = { "PCI device ID",iocshArgInt};
220 static const iocshArg pcidiagsetArg6 = { "exact",iocshArgInt};
221 static const iocshArg * const pcidiagsetArgs[7] =
222 {&pcidiagsetArg0,&pcidiagsetArg1,&pcidiagsetArg2,&pcidiagsetArg3,&pcidiagsetArg4,&pcidiagsetArg5,&pcidiagsetArg6};
223 static const iocshFuncDef pcidiagsetFuncDef =
224 {"pcidiagset",7,pcidiagsetArgs};
225 
226 static void pcidiagsetCall(const iocshArgBuf *args)
227 {
228  pcidiagset(args[0].ival, args[1].ival, args[2].ival, args[3].ival, args[4].ival, args[5].ival, args[6].ival);
229 }
230 
231 static const iocshArg pciwriteArg0 = { "data width (8,16,32)",iocshArgInt};
232 static const iocshArg pciwriteArg1 = { "offset",iocshArgInt};
233 static const iocshArg pciwriteArg2 = { "value",iocshArgInt};
234 static const iocshArg * const pciwriteArgs[3] =
235 {&pciwriteArg0,&pciwriteArg1,&pciwriteArg2};
236 static const iocshFuncDef pciwriteFuncDef =
237 {"pciwrite",3,pciwriteArgs};
238 
239 static void pciwriteCall(const iocshArgBuf *args)
240 {
241  pciwrite(args[0].ival, args[1].ival, args[2].ival);
242 }
243 
244 static const iocshArg pcireadArg0 = { "data width (8,16,32)",iocshArgInt};
245 static const iocshArg pcireadArg1 = { "offset",iocshArgInt};
246 static const iocshArg pcireadArg2 = { "count",iocshArgInt};
247 static const iocshArg * const pcireadArgs[3] =
248 {&pcireadArg0,&pcireadArg1,&pcireadArg2};
249 static const iocshFuncDef pcireadFuncDef =
250 {"pciread",3,pcireadArgs};
251 
252 static void pcireadCall(const iocshArgBuf *args)
253 {
254  pciread(args[0].ival, args[1].ival, args[2].ival);
255 }
256 
257 static const iocshArg pciconfreadArg0 = { "data width (8,16,32)",iocshArgInt};
258 static const iocshArg pciconfreadArg1 = { "offset",iocshArgInt};
259 static const iocshArg pciconfreadArg2 = { "count",iocshArgInt};
260 static const iocshArg * const pciconfreadArgs[3] =
261 {&pciconfreadArg0,&pciconfreadArg1,&pciconfreadArg2};
262 static const iocshFuncDef pciconfreadFuncDef =
263 {"pciconfread",3,pciconfreadArgs};
264 
265 static void pciconfreadCall(const iocshArgBuf *args)
266 {
267  pciconfread(args[0].ival, args[1].ival, args[2].ival);
268 }
269 
270 static void pcish(void)
271 {
272  iocshRegister(&pciwriteFuncDef,pciwriteCall);
273  iocshRegister(&pcireadFuncDef,pcireadCall);
274  iocshRegister(&pciconfreadFuncDef,pciconfreadCall);
275  iocshRegister(&pcidiagsetFuncDef,pcidiagsetCall);
276 }
277 epicsExportRegistrar(pcish);
278 
void pciconfread(int dmod, int offset, int count)
Definition: pcish.c:178
#define DEVPCI_END
The last item in a list of PCI IDS.
Definition: devLibPCI.h:72
epicsExportRegistrar(pcish)
INLINE void nat_iowrite16(volatile void *addr, epicsUInt16 val)
Write two byte in host order. Not byte swapping.
Definition: epicsMMIODef.h:61
void pcidiagset(int b, int d, int f, int bar, int vendor, int device, int exact)
Definition: pcish.c:43
INLINE epicsUInt32 nat_ioread32(volatile void *addr)
Read four bytes in host order. Not byte swapping.
Definition: epicsMMIODef.h:71
void pciwrite(int dmod, int offset, int value)
Definition: pcish.c:123
#define DEVPCI_DEVICE_VENDOR(dev, vend)
Definition: devLibPCI.h:79
unsigned int bus
Definition: devLibPCI.h:114
int devPCIConfigRead8(const epicsPCIDevice *dev, unsigned offset, epicsUInt8 *pResult)
Read byte from configuration space.
Definition: devLibPCI.c:603
INLINE epicsUInt16 nat_ioread16(volatile void *addr)
Read two bytes in host order. Not byte swapping.
Definition: epicsMMIODef.h:51
unsigned int f
Definition: pcish.c:28
INLINE void iowrite8(volatile void *addr, epicsUInt8 val)
Write a single byte.
Definition: epicsMMIODef.h:41
int devPCIToLocalAddr(const epicsPCIDevice *curdev, unsigned int bar, volatile void **ppLocalAddr, unsigned int opt)
Get pointer to PCI BAR.
Definition: devLibPCI.c:431
#define DEVPCI_ANY_VENDOR
Definition: devLibPCI.h:63
Device token.
Definition: devLibPCI.h:112
int devPCIConfigRead16(const epicsPCIDevice *dev, unsigned offset, epicsUInt16 *pResult)
Read (16-bit) word from configuration space.
Definition: devLibPCI.c:609
unsigned int device
Definition: devLibPCI.h:115
const epicsPCIDevice * dev
Definition: pcish.c:29
unsigned int d
Definition: pcish.c:28
PCI device identifier.
Definition: devLibPCI.h:55
#define DEVPCI_ANY_DEVICE
Definition: devLibPCI.h:62
Definition: pcish.c:27
INLINE epicsUInt8 ioread8(volatile void *addr)
Read a single byte.
Definition: epicsMMIODef.h:32
int devPCIBarLen(const epicsPCIDevice *curdev, unsigned int bar, epicsUInt32 *len)
Find the size of a BAR.
Definition: devLibPCI.c:449
int devPCIConfigRead32(const epicsPCIDevice *dev, unsigned offset, epicsUInt32 *pResult)
Read (32-bit) dword from configuration space.
Definition: devLibPCI.c:615
unsigned int function
Definition: devLibPCI.h:116
void pciread(int dmod, int offset, int count)
Definition: pcish.c:143
int devPCIFindCB(const epicsPCIID *idlist, devPCISearchFn searchfn, void *arg, unsigned int opt)
PCI bus search w/ callback.
Definition: devLibPCI.c:214
unsigned int b
Definition: pcish.c:28
INLINE void nat_iowrite32(volatile void *addr, epicsUInt32 val)
Write four byte in host order. Not byte swapping.
Definition: epicsMMIODef.h:81