1
|
|
2
|
/* R E S O U R C E M A N A G E R - An FPGA driver */
|
3
|
|
4
|
/* Project Name: "fpga" */
|
5
|
|
6
|
/* What is a Resource Manager under QNX Neutrino?
|
7
|
* A resource manager is a superset of a device driver. The QNX
|
8
|
* resource manager framework is used to create the POSIX
|
9
|
* interface (open, read, write, etc.) for any resource you
|
10
|
* can think of. Imagine you are coding a device driver for
|
11
|
* a device that reads credit cards. Your application would then
|
12
|
* be able to just use open() to access the card, read() to retrieve
|
13
|
* data from the card, and write() to store data on the card.
|
14
|
* If later your hardware changes, and you don't need to read
|
15
|
* credit cards any more but are reading serial data from some
|
16
|
* field bus instead, you replace/update the resource manager
|
17
|
* while your application still just uses open(), read() and write()!
|
18
|
*/
|
19
|
|
20
|
/*
|
21
|
* This project is an fpga driver. It provides a means of programming
|
22
|
* the fpga and displaying the status of the fpga.
|
23
|
*
|
24
|
* Start the driver as:
|
25
|
* fpga-variant -b 0x01e26000 -f 0x66000000 &
|
26
|
*
|
27
|
* It will create the following devices:
|
28
|
* /dev/fpga/cmd Writes to this device perform different commands
|
29
|
* 1 Assert FPGA reset
|
30
|
* 2 Initiate programming cycle
|
31
|
* 3 Check if programming worked (enumerate cores?)
|
32
|
* /dev/fpga/image Writes to this device send data to the fpga when being programmed
|
33
|
* /dev/fpga/state Reads from this device give current state of fpga. Possible states
|
34
|
* UNKNOWN fpga might or might not be programmed
|
35
|
* RESET fpga is being reset
|
36
|
* PROGRAM_FAIL an attempt was made to program the fpga and it failed
|
37
|
* PROGRAMMING fpga is currently being programmed
|
38
|
* PROGRAMMED fpga has been successfully programmed
|
39
|
* /dev/fpga/version Reads from this device give version numbers when device is programmed
|
40
|
* /dev/fpga/int_status Reads from this device give interrupt information (not implemented now)
|
41
|
*/
|
42
|
|
43
|
#include <errno.h>
|
44
|
#include <stdio.h>
|
45
|
#include <stdlib.h>
|
46
|
#include <string.h>
|
47
|
#include <unistd.h>
|
48
|
struct fpga_attr; // This overrides the default structure so we can add our own fields
|
49
|
#define IOFUNC_ATTR_T struct fpga_attr
|
50
|
#include <sys/iofunc.h>
|
51
|
#include <sys/dispatch.h>
|
52
|
#include <sys/neutrino.h>
|
53
|
#include <sys/resmgr.h>
|
54
|
#include <sys/mman.h>
|
55
|
#include <hw/inout.h>
|
56
|
#define FPGA_CTRL_C
|
57
|
#include "core_ids.h"
|
58
|
|
59
|
/*
|
60
|
* Enumeration for different directions of pins
|
61
|
*/
|
62
|
enum gpio_direct { GPIO_IN, GPIO_OUT };
|
63
|
typedef enum gpio_direct gpio_direct_t;
|
64
|
|
65
|
/*
|
66
|
* Our attribute structure. This includes the default structure
|
67
|
* at the front and then specifies our own added fields.
|
68
|
*/
|
69
|
#define PAGE_SIZE 4096
|
70
|
typedef struct fpga_attr fpga_attr_t;
|
71
|
struct fpga_attr
|
72
|
{
|
73
|
iofunc_attr_t attr; /* must be first, this is the regular structure */
|
74
|
// unsigned bank; /* bank of the pin */
|
75
|
// unsigned pin; /* pin number within the bank (0-15) */
|
76
|
// gpio_direct_t direction; /* direction of pin */
|
77
|
// unsigned init_value; /* initial value if direction is GPIO_OUT */
|
78
|
char buffer[PAGE_SIZE]; /* buffer for values being read */
|
79
|
int id; /* resmgr id associated with the file, filled in after attach */
|
80
|
// gpio_attr_t* next; /* pointer to next gpio_attr structure */
|
81
|
// const char * name; /* pointer to name for the device */
|
82
|
};
|
83
|
|
84
|
/*
|
85
|
* defines to specify register offsets within each bank.
|
86
|
*/
|
87
|
#define GPIO_DIR (0x00)
|
88
|
#define GPIO_OUT_DATA (0x04)
|
89
|
#define GPIO_SET_DATA (0x08)
|
90
|
#define GPIO_CLR_DATA (0x0C)
|
91
|
#define GPIO_IN_DATA (0x10)
|
92
|
#define GPIO_SET_RIS_TRIG (0x14)
|
93
|
#define GPIO_CLR_RIS_TRIG (0x18)
|
94
|
#define GPIO_SET_FAL_TRIG (0x1C)
|
95
|
#define GPIO_CLR_FAL_TRIG (0x20)
|
96
|
#define GPIO_INTSTAT (0x24)
|
97
|
#define BANKSIZE (0x28)
|
98
|
#define NUM_BANKS (9)
|
99
|
|
100
|
/*
|
101
|
* Macros to help calculate the bank offset from the base address
|
102
|
* and to generate the pin-mask for each pin.
|
103
|
*
|
104
|
* Note that each bank of registers actually has 2 banks of pins.
|
105
|
* Each bank of pins has 16 pins. The even number banks are in the
|
106
|
* low 16 bits and the odd number banks are in the high 16 bits.
|
107
|
*/
|
108
|
#define BANKOFF(bank) (0x10 + ((bank)>>1) * BANKSIZE)
|
109
|
#define PINMASK(bank,pin) (1 << ((pin) + (((bank)&1)? 16 : 0 ) ) )
|
110
|
|
111
|
static uintptr_t gpio_base = 0x01e26000; /* base address of the gpio peripheral */
|
112
|
static uintptr_t gpio_vbase; /* mmap version of base */
|
113
|
|
114
|
#define FPGA_BASE_ADDR 0x66000000
|
115
|
#define FPGA_CORE_SIZE 0x80
|
116
|
#define FPGA_MAX_CORES 32
|
117
|
#define FPGA_BASEMODULE_OFFSET 0
|
118
|
|
119
|
static uintptr_t fpga_base = FPGA_BASE_ADDR; /* base address of the FPGA */
|
120
|
static uintptr_t fpga_vbase; /* mmap version of fpga base */
|
121
|
|
122
|
#define GPIO_TO_PIN( bank, pinno ) (((bank)<<16)|(pinno))
|
123
|
#define PIN_TO_BANK(gpiopin) (((gpiopin)>>16)&0xff)
|
124
|
#define PIN_TO_PIN(gpiopin) ((gpiopin)&0xff)
|
125
|
#define FPGA_PROGRAM GPIO_TO_PIN(6,15)
|
126
|
#define FPGA_INIT GPIO_TO_PIN(1,15)
|
127
|
#define FPGA_RDWR GPIO_TO_PIN(3,9)
|
128
|
#define FPGA_INT0 GPIO_TO_PIN(6,12)
|
129
|
#define FPGA_INT1 GPIO_TO_PIN(6,13)
|
130
|
|
131
|
#define FPGA_STATE_UNKNOWN 0 /* FPGA is not in a known state */
|
132
|
#define FPGA_STATE_RESET 1 /* FPGA has been reset, but we aren't programming */
|
133
|
#define FPGA_STATE_PROGRAMMING 2 /* FPGA is being programmed */
|
134
|
#define FPGA_STATE_PROGRAM_FAIL 3 /* FPGA failed programming */
|
135
|
#define FPGA_STATE_PROGRAMMED 4 /* FPGA has been programmed */
|
136
|
|
137
|
#define FPGA_CMD_RESET 1 /* Assert FPGA reset */
|
138
|
#define FPGA_CMD_PROGRAM 2 /* Initiate programming cycle */
|
139
|
#define FPGA_CMD_FINISHPROGRAM 3 /* Check if programming worked, then enumerate cores */
|
140
|
|
141
|
|
142
|
/**
|
143
|
* Core Version Register, FIFO_no = 0
|
144
|
*/
|
145
|
typedef union corever0 {
|
146
|
struct bits0 {
|
147
|
unsigned int core_id : 8; /* Core ID 0xF0-0xFF are reserved for customers */
|
148
|
unsigned int vector : 4; /* interrupt vector level */
|
149
|
unsigned int level : 2; /* interrupt level */
|
150
|
unsigned int FIFO_no : 2; /* = 00 */
|
151
|
} bits;
|
152
|
uint16_t word;
|
153
|
} corever0;
|
154
|
|
155
|
/**
|
156
|
* Core Version Register, FIFO_no = 1
|
157
|
*/
|
158
|
typedef union corever1 {
|
159
|
struct bits1 {
|
160
|
unsigned int minor : 4; /* minor revision */
|
161
|
unsigned int major : 4; /* major revision */
|
162
|
unsigned int year : 5; /* years since 2000 */
|
163
|
unsigned int reserved : 1; /* not used */
|
164
|
unsigned int FIFO_no : 2; /* = 01 */
|
165
|
} bits;
|
166
|
uint16_t word;
|
167
|
} corever1;
|
168
|
|
169
|
/**
|
170
|
* Core Version Register, FIFO_no = 2
|
171
|
*/
|
172
|
typedef union corever2 {
|
173
|
struct bits2 {
|
174
|
unsigned int day : 5; /* minor revision */
|
175
|
unsigned int reserved : 3; /* not used */
|
176
|
unsigned int month : 4; /* major revision */
|
177
|
unsigned int reserved1 : 2; /* not used */
|
178
|
unsigned int FIFO_no : 2; /* = 10 */
|
179
|
} bits;
|
180
|
uint16_t word;
|
181
|
} corever2;
|
182
|
/**
|
183
|
* Core Version Register, FIFO_no = 3
|
184
|
*/
|
185
|
typedef union corever3 {
|
186
|
struct bits3 {
|
187
|
unsigned int reserved1 : 14; /* not used */
|
188
|
unsigned int FIFO_no : 2; /* = 10 */
|
189
|
} bits;
|
190
|
uint16_t word;
|
191
|
} corever3;
|
192
|
|
193
|
/**
|
194
|
* This structure holds the FPGA core version information.
|
195
|
*/
|
196
|
struct coreversion {
|
197
|
corever0 ver0;
|
198
|
corever1 ver1;
|
199
|
corever2 ver2;
|
200
|
corever3 ver3;
|
201
|
};
|
202
|
|
203
|
struct fpga_ctrl
|
204
|
{
|
205
|
unsigned int state;
|
206
|
uintptr_t vbaseaddr;
|
207
|
uintptr_t baseaddr;
|
208
|
struct coreversion bm_version;
|
209
|
struct coreversion app_version;
|
210
|
} fpga_ctrl = {
|
211
|
.state = FPGA_STATE_UNKNOWN
|
212
|
};
|
213
|
static struct fpga_ctrl *fpgactrl = &fpga_ctrl;
|
214
|
|
215
|
|
216
|
/*
|
217
|
* options processing
|
218
|
*
|
219
|
* This routine handles the command-line options.
|
220
|
* -v verbose operation
|
221
|
* -b addr gpio base address (default is 0x01e26000)
|
222
|
* -f addr fpga base address (default is 0x66000000)
|
223
|
*/
|
224
|
static int optv; // -v for verbose operation
|
225
|
#if NEVER
|
226
|
enum gpio_pinoptions { IN, OUT, END };
|
227
|
static char * gpio_pinopts[] =
|
228
|
{
|
229
|
[IN] = "in",
|
230
|
[OUT] = "out",
|
231
|
[END] = NULL
|
232
|
};
|
233
|
#endif
|
234
|
static void
|
235
|
options (int argc, char **argv)
|
236
|
{
|
237
|
int opt;
|
238
|
optv = 0;
|
239
|
|
240
|
while (optind < argc) {
|
241
|
while ((opt = getopt (argc, argv, "vb:f:")) != -1) {
|
242
|
switch (opt) {
|
243
|
case 'v':
|
244
|
optv = 1;
|
245
|
break;
|
246
|
case 'b':
|
247
|
gpio_base = strtoul( optarg, 0, 0 );
|
248
|
break;
|
249
|
case 'f':
|
250
|
fpga_base = strtoul( optarg, 0, 0 );
|
251
|
break;
|
252
|
}
|
253
|
}
|
254
|
}
|
255
|
}
|
256
|
|
257
|
/* A resource manager mainly consists of callbacks for POSIX
|
258
|
* functions a client could call. In the example, we have
|
259
|
* callbacks for the open(), read() and write() calls. More are
|
260
|
* possible. If we don't supply own functions (e.g. for stat(),
|
261
|
* seek(), etc.), the resource manager framework will use default
|
262
|
* system functions, which in most cases return with an error
|
263
|
* code to indicate that this resource manager doesn't support
|
264
|
* this function.*/
|
265
|
|
266
|
/* These prototypes are needed since we are using their names
|
267
|
* in main(). */
|
268
|
|
269
|
//static int io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb);
|
270
|
static int io_cmd_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb);
|
271
|
static int io_image_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb);
|
272
|
//static int io_version_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb);
|
273
|
static int io_state_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb);
|
274
|
static int io_devices_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb);
|
275
|
|
276
|
/*
|
277
|
* Attribute structures for each of the files to be created
|
278
|
*/
|
279
|
static IOFUNC_ATTR_T attr_cmd;
|
280
|
static IOFUNC_ATTR_T attr_image;
|
281
|
static IOFUNC_ATTR_T attr_version;
|
282
|
static IOFUNC_ATTR_T attr_state;
|
283
|
static IOFUNC_ATTR_T attr_devices;
|
284
|
|
285
|
/*
|
286
|
* Our connect and I/O functions - we supply two tables
|
287
|
* which will be filled with pointers to callback functions
|
288
|
* for each POSIX function. The connect functions are all
|
289
|
* functions that take a path, e.g. open(), while the I/O
|
290
|
* functions are those functions that are used with a file
|
291
|
* descriptor (fd), e.g. read().
|
292
|
*/
|
293
|
|
294
|
static resmgr_connect_funcs_t connect_funcs;
|
295
|
static resmgr_io_funcs_t io_cmd_funcs;
|
296
|
static resmgr_io_funcs_t io_image_funcs;
|
297
|
static resmgr_io_funcs_t io_version_funcs;
|
298
|
static resmgr_io_funcs_t io_state_funcs;
|
299
|
static resmgr_io_funcs_t io_devices_funcs;
|
300
|
|
301
|
/*
|
302
|
* Our dispatch, resource manager, and iofunc variables
|
303
|
* are declared here. These are some small administrative things
|
304
|
* for our resource manager.
|
305
|
*/
|
306
|
|
307
|
static dispatch_t *dpp;
|
308
|
static resmgr_attr_t rattr;
|
309
|
static dispatch_context_t *ctp;
|
310
|
|
311
|
|
312
|
static char *progname = "fpga";
|
313
|
|
314
|
void attachFile( IOFUNC_ATTR_T *pAttr, const char *name, mode_t mode, resmgr_io_funcs_t *pio_funcs )
|
315
|
{
|
316
|
iofunc_attr_init (&pAttr->attr, 0660, NULL, NULL);
|
317
|
pAttr->attr.nbytes=sizeof(pAttr->buffer); /* we have a buffer size of 128 byte */
|
318
|
|
319
|
pAttr -> id = resmgr_attach (dpp, &rattr, name,
|
320
|
_FTYPE_ANY, 0,
|
321
|
&connect_funcs,
|
322
|
pio_funcs,
|
323
|
pAttr);
|
324
|
if (pAttr -> id == -1) {
|
325
|
fprintf (stderr, "%s: couldn't attach pathname(%s): %s\n",
|
326
|
progname, name, strerror (errno));
|
327
|
exit (1);
|
328
|
}
|
329
|
}
|
330
|
void gpio_init( unsigned gpiopin, gpio_direct_t direction, unsigned init_value )
|
331
|
{
|
332
|
unsigned bankoff = BANKOFF(PIN_TO_BANK(gpiopin));
|
333
|
unsigned reg_direction = in32( gpio_vbase+bankoff+GPIO_DIR );
|
334
|
unsigned pinmask = PINMASK( PIN_TO_BANK(gpiopin), PIN_TO_PIN(gpiopin) );
|
335
|
if( direction == GPIO_OUT )
|
336
|
{
|
337
|
/*
|
338
|
* Turn off pin position for output
|
339
|
*/
|
340
|
reg_direction &= ~(pinmask) ;
|
341
|
}
|
342
|
else
|
343
|
{
|
344
|
/*
|
345
|
* Turn on pin position for input
|
346
|
*/
|
347
|
reg_direction |= pinmask;
|
348
|
}
|
349
|
/*
|
350
|
* No interrupts for rising or falling
|
351
|
*/
|
352
|
out32( gpio_vbase + bankoff + GPIO_CLR_RIS_TRIG, pinmask );
|
353
|
out32( gpio_vbase + bankoff + GPIO_CLR_FAL_TRIG, pinmask );
|
354
|
/*
|
355
|
* Write the new direction register with this pin set properly
|
356
|
* Leave the other pin positions the same
|
357
|
*/
|
358
|
out32( gpio_vbase + bankoff + GPIO_DIR, reg_direction );
|
359
|
|
360
|
if( direction == GPIO_OUT )
|
361
|
{
|
362
|
/*
|
363
|
* Set the initial value. For the initial value,
|
364
|
* binary zero says to clear the value, non-zero
|
365
|
* says to set the value.
|
366
|
*/
|
367
|
if( init_value )
|
368
|
{
|
369
|
out32( gpio_vbase + bankoff + GPIO_SET_DATA, pinmask );
|
370
|
}
|
371
|
else
|
372
|
{
|
373
|
out32( gpio_vbase + bankoff + GPIO_CLR_DATA, pinmask );
|
374
|
}
|
375
|
}
|
376
|
}
|
377
|
void gpio_direction_output( unsigned int pin, unsigned value )
|
378
|
{
|
379
|
unsigned bankoff = BANKOFF( PIN_TO_BANK(pin) );
|
380
|
unsigned pinmask = PINMASK( PIN_TO_BANK(pin), PIN_TO_PIN(pin) );
|
381
|
out32( gpio_vbase + bankoff + (value == 1 ? GPIO_SET_DATA : GPIO_CLR_DATA), pinmask );
|
382
|
}
|
383
|
void setFPGAState( unsigned state )
|
384
|
{
|
385
|
char *state_name;
|
386
|
fpgactrl->state = state;
|
387
|
|
388
|
switch( fpgactrl->state )
|
389
|
{
|
390
|
default:
|
391
|
case FPGA_STATE_UNKNOWN: state_name = "UNKNOWN"; break;
|
392
|
case FPGA_STATE_RESET: state_name = "RESET"; break;
|
393
|
case FPGA_STATE_PROGRAMMING: state_name = "PROGRAMMING"; break;
|
394
|
case FPGA_STATE_PROGRAM_FAIL: state_name = "PROGRAM_FAIL"; break;
|
395
|
case FPGA_STATE_PROGRAMMED: state_name = "PROGRAMMED"; break;
|
396
|
}
|
397
|
attr_state.attr.nbytes = snprintf( attr_state.buffer, PAGE_SIZE, state_name );
|
398
|
}
|
399
|
void setVersion()
|
400
|
{
|
401
|
int rv = 0;
|
402
|
char *buf = &attr_version.buffer[0];
|
403
|
switch( fpgactrl->state )
|
404
|
{
|
405
|
default:
|
406
|
case FPGA_STATE_UNKNOWN:
|
407
|
case FPGA_STATE_RESET:
|
408
|
case FPGA_STATE_PROGRAMMING:
|
409
|
case FPGA_STATE_PROGRAM_FAIL:
|
410
|
rv += snprintf( &buf[rv], PAGE_SIZE-rv, "NOT_PROGRAMMED" );
|
411
|
break;
|
412
|
case FPGA_STATE_PROGRAMMED:
|
413
|
rv += snprintf(&buf[rv], PAGE_SIZE-rv, "PROGRAMMED\n");
|
414
|
rv += snprintf(&buf[rv], PAGE_SIZE-rv, "FPGA Version : %02d.%02d\n",
|
415
|
fpgactrl->app_version.ver1.bits.major, fpgactrl->app_version.ver1.bits.minor);
|
416
|
rv += snprintf(&buf[rv], PAGE_SIZE-rv, "FPGA Date : %04d-%02d-%02d\n",
|
417
|
fpgactrl->app_version.ver1.bits.year,
|
418
|
fpgactrl->app_version.ver2.bits.month,
|
419
|
fpgactrl->app_version.ver2.bits.day);
|
420
|
|
421
|
rv += snprintf(&buf[rv], PAGE_SIZE-rv, "Base Module Version : %02d.%02d\n",
|
422
|
fpgactrl->bm_version.ver1.bits.major,
|
423
|
fpgactrl->bm_version.ver1.bits.minor);
|
424
|
rv += snprintf(&buf[rv], PAGE_SIZE-rv, "Base Module Date : %04d-%02d-%02d\n",
|
425
|
fpgactrl->bm_version.ver1.bits.year,
|
426
|
fpgactrl->bm_version.ver2.bits.month,
|
427
|
fpgactrl->bm_version.ver2.bits.day);
|
428
|
break;
|
429
|
}
|
430
|
attr_version.attr.nbytes = rv;
|
431
|
}
|
432
|
/**
|
433
|
* Reads the core version information out of a spot in the
|
434
|
* FPGA.
|
435
|
*
|
436
|
* \param[in] baseaddr location of the core version register
|
437
|
* \param[in] pdata location to store the core version data
|
438
|
*
|
439
|
* \return non-zero if the core data is invalid
|
440
|
*/
|
441
|
int read_core_version(uintptr_t baseaddr, struct coreversion* pdata)
|
442
|
{
|
443
|
int i;
|
444
|
corever0 ver;
|
445
|
int found = 0;
|
446
|
int rv = -1;
|
447
|
|
448
|
for (i = 0; i < 4; i++)
|
449
|
{
|
450
|
ver.word = in16(baseaddr);
|
451
|
switch(ver.bits.FIFO_no)
|
452
|
{
|
453
|
case 0:
|
454
|
pdata->ver0.word = ver.word;
|
455
|
break;
|
456
|
case 1:
|
457
|
pdata->ver1.word = ver.word;
|
458
|
break;
|
459
|
case 2:
|
460
|
pdata->ver2.word = ver.word;
|
461
|
break;
|
462
|
case 3:
|
463
|
pdata->ver3.word = ver.word;
|
464
|
break;
|
465
|
}
|
466
|
found |= (1<<ver.bits.FIFO_no);
|
467
|
}
|
468
|
if (found == 0x0F)
|
469
|
rv = 0;
|
470
|
return rv;
|
471
|
}
|
472
|
int main (int argc, char **argv)
|
473
|
{
|
474
|
progname = argv[0];
|
475
|
|
476
|
/* Check for command line options (-v and pin specifications) */
|
477
|
options (argc, argv);
|
478
|
|
479
|
/* Allocate and initialize a dispatch structure for use
|
480
|
* by our main loop. This is for the resource manager
|
481
|
* framework to use. It will receive messages for us,
|
482
|
* analyze the message type integer and call the matching
|
483
|
* handler callback function (i.e. io_open, io_read, etc.) */
|
484
|
dpp = dispatch_create ();
|
485
|
if (dpp == NULL) {
|
486
|
fprintf (stderr, "%s: couldn't dispatch_create: %s\n",
|
487
|
argv[0], strerror (errno));
|
488
|
exit (1);
|
489
|
}
|
490
|
|
491
|
/* Set up the resource manager attributes structure. We'll
|
492
|
* use this as a way of passing information to
|
493
|
* resmgr_attach(). The attributes are used to specify
|
494
|
* the maximum message length to be received at once,
|
495
|
* and the number of message fragments (iov's) that
|
496
|
* are possible for the reply.
|
497
|
* For now, we'll just use defaults by setting the
|
498
|
* attribute structure to zeroes. */
|
499
|
memset (&rattr, 0, sizeof (rattr));
|
500
|
|
501
|
/* Now, let's initialize the tables of connect functions and
|
502
|
* I/O functions to their defaults (system fallback
|
503
|
* routines) and then override the defaults with the
|
504
|
* functions that we are providing. */
|
505
|
iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
|
506
|
_RESMGR_IO_NFUNCS, &io_cmd_funcs);
|
507
|
iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
|
508
|
_RESMGR_IO_NFUNCS, &io_image_funcs);
|
509
|
iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
|
510
|
_RESMGR_IO_NFUNCS, &io_state_funcs);
|
511
|
iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
|
512
|
_RESMGR_IO_NFUNCS, &io_version_funcs);
|
513
|
iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_funcs,
|
514
|
_RESMGR_IO_NFUNCS, &io_devices_funcs);
|
515
|
|
516
|
/* Now we override the default function pointers with
|
517
|
* some of our own coded functions: */
|
518
|
//connect_funcs.open = io_open;
|
519
|
//io_funcs.read = io_read;
|
520
|
//io_funcs.write = io_write;
|
521
|
|
522
|
/*
|
523
|
* Map the GPIO registers so we can access them.
|
524
|
*/
|
525
|
gpio_vbase = mmap_device_io( BANKSIZE*(NUM_BANKS+1)/2+0x10, gpio_base );
|
526
|
if( gpio_vbase == (uintptr_t)MAP_FAILED )
|
527
|
{
|
528
|
fprintf( stderr, "mmap_device_io gpio failed: errno = %d\n", errno );
|
529
|
exit(1);
|
530
|
}
|
531
|
|
532
|
/*
|
533
|
* Map the FPGA memory so we can access them.
|
534
|
*/
|
535
|
fpga_vbase = mmap_device_io( FPGA_CORE_SIZE, fpga_base );
|
536
|
if( fpga_vbase == (uintptr_t)MAP_FAILED )
|
537
|
{
|
538
|
fprintf( stderr, "mmap_device_io fpga failed: errno = %d\n", errno );
|
539
|
exit(1);
|
540
|
}
|
541
|
fpgactrl->vbaseaddr = fpga_vbase;
|
542
|
fpgactrl->baseaddr = fpga_base;
|
543
|
|
544
|
/*
|
545
|
* Create all the different resource files. (cmd, image, state, and version)
|
546
|
*/
|
547
|
io_cmd_funcs.write = io_cmd_write;
|
548
|
attachFile( &attr_cmd, "/dev/fpga/cmd", S_IFCHR | S_IWUSR | S_IWGRP | S_IWOTH, &io_cmd_funcs );
|
549
|
io_image_funcs.write = io_image_write;
|
550
|
attachFile( &attr_image, "/dev/fpga/image", S_IFCHR | S_IWUSR | S_IWGRP | S_IWOTH, &io_image_funcs );
|
551
|
io_state_funcs.read = io_state_read;
|
552
|
attachFile( &attr_state, "/dev/fpga/state", S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, &io_state_funcs );
|
553
|
io_version_funcs.read = io_state_read; // version and state share a read function
|
554
|
attachFile( &attr_version, "/dev/fpga/version", S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, &io_version_funcs );
|
555
|
io_devices_funcs.read = io_devices_read;
|
556
|
attachFile( &attr_devices, "/dev/fpga/devices", S_IFCHR | S_IRUSR | S_IRGRP | S_IROTH, &io_devices_funcs );
|
557
|
|
558
|
gpio_init( FPGA_PROGRAM, GPIO_OUT, 1 );
|
559
|
gpio_init( FPGA_INIT, GPIO_IN, 0 );
|
560
|
gpio_init( FPGA_RDWR, GPIO_OUT, 1 );
|
561
|
gpio_init( FPGA_INT0, GPIO_IN, 0 );
|
562
|
gpio_init( FPGA_INT1, GPIO_IN, 0 );
|
563
|
setFPGAState( FPGA_STATE_UNKNOWN );
|
564
|
setVersion();
|
565
|
|
566
|
#if NEVER
|
567
|
if( gpio_attr_head )
|
568
|
{
|
569
|
gpio_attr_t *pAttr;
|
570
|
|
571
|
for( pAttr = gpio_attr_head; pAttr; pAttr = pAttr -> next )
|
572
|
{
|
573
|
unsigned bankoff = BANKOFF(pAttr -> bank);
|
574
|
unsigned reg_direction = in32( gpio_vbase+bankoff+GPIO_DIR );
|
575
|
unsigned pinmask = PINMASK( pAttr -> bank, pAttr -> pin );
|
576
|
char devname[PATH_MAX+1];
|
577
|
if( pAttr -> direction == GPIO_OUT )
|
578
|
{
|
579
|
/*
|
580
|
* Turn off pin position for output
|
581
|
*/
|
582
|
reg_direction &= ~(pinmask) ;
|
583
|
}
|
584
|
else
|
585
|
{
|
586
|
/*
|
587
|
* Turn on pin position for input
|
588
|
*/
|
589
|
reg_direction |= pinmask;
|
590
|
}
|
591
|
/*
|
592
|
* No interrupts for rising or falling
|
593
|
*/
|
594
|
out32( gpio_vbase + bankoff + GPIO_CLR_RIS_TRIG, pinmask );
|
595
|
out32( gpio_vbase + bankoff + GPIO_CLR_FAL_TRIG, pinmask );
|
596
|
/*
|
597
|
* Write the new direction register with this pin set properly
|
598
|
* Leave the other pin positions the same
|
599
|
*/
|
600
|
out32( gpio_vbase + bankoff + GPIO_DIR, reg_direction );
|
601
|
|
602
|
if( pAttr -> direction == GPIO_OUT )
|
603
|
{
|
604
|
/*
|
605
|
* Set the initial value. For the initial value,
|
606
|
* binary zero says to clear the value, non-zero
|
607
|
* says to set the value.
|
608
|
*/
|
609
|
if( pAttr ->init_value )
|
610
|
{
|
611
|
out32( gpio_vbase + bankoff + GPIO_SET_DATA, pinmask );
|
612
|
}
|
613
|
else
|
614
|
{
|
615
|
out32( gpio_vbase + bankoff + GPIO_CLR_DATA, pinmask );
|
616
|
}
|
617
|
}
|
618
|
|
619
|
iofunc_attr_init (&pAttr->attr, S_IFCHR | 0666, NULL, NULL);
|
620
|
pAttr->attr.nbytes=1; /* we have a buffer size of 1 byte */
|
621
|
|
622
|
/*
|
623
|
* Create the file name with 3 possibilities:
|
624
|
* No name provided: use /dev/gpBpP
|
625
|
* Name provided that starts with a /, use the provided name
|
626
|
* Name provided that is relative, use /dev/name
|
627
|
*/
|
628
|
if( pAttr->name == NULL )
|
629
|
{
|
630
|
snprintf(devname, PATH_MAX, "/dev/gp%dp%d", pAttr->bank, pAttr->pin);
|
631
|
}
|
632
|
else if( pAttr->name[0] == '/' )
|
633
|
{
|
634
|
snprintf(devname, PATH_MAX, "%s", pAttr->name );
|
635
|
}
|
636
|
else
|
637
|
{
|
638
|
snprintf(devname, PATH_MAX, "/dev/%s", pAttr->name );
|
639
|
}
|
640
|
|
641
|
pAttr -> id = resmgr_attach (dpp, &rattr, devname,
|
642
|
_FTYPE_ANY, 0,
|
643
|
&connect_funcs,
|
644
|
&io_funcs,
|
645
|
pAttr);
|
646
|
if (pAttr -> id == -1) {
|
647
|
fprintf (stderr, "%s: couldn't attach pathname: %s\n",
|
648
|
argv[0], strerror (errno));
|
649
|
exit (1);
|
650
|
}
|
651
|
}
|
652
|
}
|
653
|
else
|
654
|
{
|
655
|
fprintf( stderr, "%s: no pins specified\n", argv[0] );
|
656
|
exit(1);
|
657
|
}
|
658
|
#endif
|
659
|
|
660
|
/* Now we allocate some memory for the dispatch context
|
661
|
* structure, which will later be used when we receive
|
662
|
* messages. */
|
663
|
ctp = dispatch_context_alloc (dpp);
|
664
|
|
665
|
/* Done! We can now go into our "receive loop" and wait
|
666
|
* for messages. The dispatch_block() function is calling
|
667
|
* MsgReceive() under the covers, and receives for us.
|
668
|
* The dispatch_handler() function analyzes the message
|
669
|
* for us and calls the appropriate callback function. */
|
670
|
while (1) {
|
671
|
if ((ctp = dispatch_block (ctp)) == NULL) {
|
672
|
fprintf (stderr, "%s: dispatch_block failed: %s\n",
|
673
|
argv[0], strerror (errno));
|
674
|
exit (1);
|
675
|
}
|
676
|
/* Call the correct callback function for the message
|
677
|
* received. This is a single-threaded resource manager,
|
678
|
* so the next request will be handled only when this
|
679
|
* call returns. Consult QNX documentation if you want
|
680
|
* to create a multi-threaded resource manager. */
|
681
|
dispatch_handler (ctp);
|
682
|
}
|
683
|
}
|
684
|
|
685
|
/*
|
686
|
* io_read
|
687
|
*
|
688
|
* At this point, the client has called the library read()
|
689
|
* function, and expects zero or more bytes. If this is a read
|
690
|
* for exactly 1 byte, we will always return the current
|
691
|
* value for the pin. If this is a read for multiple bytes,
|
692
|
* then we use our "buffer" and return one byte and then
|
693
|
* on the next request for multiple bytes, we will return
|
694
|
* EOF. This allows repeated reads for polling and convenient
|
695
|
* access from the command line.
|
696
|
*/
|
697
|
|
698
|
|
699
|
/* The message that we received can be accessed via the
|
700
|
* pointer *msg. A pointer to the OCB that belongs to this
|
701
|
* read is the *ocb. The *ctp pointer points to a context
|
702
|
* structure that is used by the resource manager framework
|
703
|
* to determine whom to reply to, and more.
|
704
|
*/
|
705
|
|
706
|
static int
|
707
|
io_state_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
|
708
|
{
|
709
|
int status;
|
710
|
int nparts;
|
711
|
int nbytes = 0;
|
712
|
int offset = ocb->offset;
|
713
|
|
714
|
if (optv) {
|
715
|
printf ("%s: in io_read, id=%d\n", progname, ctp->id);
|
716
|
}
|
717
|
|
718
|
/* Here we verify if the client has the access
|
719
|
* rights needed to read from our device */
|
720
|
if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) {
|
721
|
return (status);
|
722
|
}
|
723
|
|
724
|
/* We check if our read callback was called because of
|
725
|
* a pread() or a normal read() call. If pread(), we return
|
726
|
* with an error code indicating that we don't support it.*/
|
727
|
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
|
728
|
return (ENOSYS);
|
729
|
}
|
730
|
/*
|
731
|
* Get the number of bytes to read. If requested is >1, look
|
732
|
* at the current offset to see if we have a byte to return.
|
733
|
* If the requested number is exactly 1, then read 1 byte.
|
734
|
*/
|
735
|
if( msg -> i.nbytes > 0 )
|
736
|
{
|
737
|
int nleft;
|
738
|
nleft = ocb -> attr -> attr.nbytes - ocb -> offset;
|
739
|
nbytes = min( msg -> i.nbytes, nleft );
|
740
|
if( nleft )
|
741
|
ocb -> offset += nbytes;
|
742
|
}
|
743
|
|
744
|
if( nbytes > 0 )
|
745
|
{
|
746
|
/* Here we set the number of bytes we will return. */
|
747
|
_IO_SET_READ_NBYTES(ctp, nbytes);
|
748
|
|
749
|
/* The next line is used to tell the system how
|
750
|
* large your buffer is in which you want to return your
|
751
|
* data for the read() call.
|
752
|
*
|
753
|
*/
|
754
|
SETIOV( ctp->iov, &ocb -> attr -> buffer[offset], nbytes);
|
755
|
nparts = 1;
|
756
|
|
757
|
}
|
758
|
else
|
759
|
{
|
760
|
_IO_SET_READ_NBYTES(ctp, 0);
|
761
|
nparts = 0;
|
762
|
}
|
763
|
|
764
|
if (msg->i.nbytes > 0) {
|
765
|
ocb->attr->attr.flags |= IOFUNC_ATTR_ATIME;
|
766
|
}
|
767
|
|
768
|
/*
|
769
|
* Return the number of parts specified above (1 or 0).
|
770
|
*/
|
771
|
return (_RESMGR_NPARTS (nparts));
|
772
|
|
773
|
|
774
|
}
|
775
|
/**
|
776
|
* Retrieve human readable core description.
|
777
|
*
|
778
|
* \param[in] ID core number
|
779
|
* \return string description of core
|
780
|
*/
|
781
|
const char* CoreName(unsigned char ID)
|
782
|
{
|
783
|
int i = 0;
|
784
|
for (i = 0; i < ARRAY_SIZE(KnownCores); i++)
|
785
|
{
|
786
|
if (ID == KnownCores[i].ID)
|
787
|
{
|
788
|
return KnownCores[i].Name;
|
789
|
}
|
790
|
}
|
791
|
return "Unknown";
|
792
|
}
|
793
|
static int
|
794
|
io_devices_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
|
795
|
{
|
796
|
int status;
|
797
|
int nparts;
|
798
|
int nbytes = 0;
|
799
|
int offset = ocb->offset;
|
800
|
int rv = 0;
|
801
|
char *buf = &ocb->attr->buffer[0];
|
802
|
|
803
|
if( offset == 0 )
|
804
|
{
|
805
|
rv += snprintf( &buf[rv], PAGE_SIZE-rv, "Enumerating Devices\n" );
|
806
|
int i;
|
807
|
struct coreversion cv;
|
808
|
|
809
|
for (i = 0; i < FPGA_MAX_CORES; i++)
|
810
|
{
|
811
|
uintptr_t vbaseaddr = (uintptr_t)((char*)(fpgactrl->vbaseaddr)+FPGA_CORE_SIZE*i);
|
812
|
uintptr_t baseaddr = (uintptr_t)((char*)(fpgactrl->baseaddr )+FPGA_CORE_SIZE*i);
|
813
|
if (0 == read_core_version(vbaseaddr,&cv))
|
814
|
{
|
815
|
//struct fpga_device* fpgadev;
|
816
|
//int ret;
|
817
|
|
818
|
rv += snprintf( &buf[rv], PAGE_SIZE-rv, "Found Device ID %02d-%s (%02d.%02d) at %08X\n",
|
819
|
cv.ver0.bits.core_id,
|
820
|
CoreName(cv.ver0.bits.core_id),
|
821
|
cv.ver1.bits.major, cv.ver1.bits.minor,baseaddr);
|
822
|
}
|
823
|
}
|
824
|
ocb->attr->attr.nbytes = rv;
|
825
|
}
|
826
|
if (optv) {
|
827
|
printf ("%s: in io_read, id=%d\n", progname, ctp->id);
|
828
|
}
|
829
|
|
830
|
/* Here we verify if the client has the access
|
831
|
* rights needed to read from our device */
|
832
|
if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) {
|
833
|
return (status);
|
834
|
}
|
835
|
|
836
|
/* We check if our read callback was called because of
|
837
|
* a pread() or a normal read() call. If pread(), we return
|
838
|
* with an error code indicating that we don't support it.*/
|
839
|
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
|
840
|
return (ENOSYS);
|
841
|
}
|
842
|
/*
|
843
|
* Get the number of bytes to read. If requested is >1, look
|
844
|
* at the current offset to see if we have a byte to return.
|
845
|
* If the requested number is exactly 1, then read 1 byte.
|
846
|
*/
|
847
|
if( msg -> i.nbytes > 0 )
|
848
|
{
|
849
|
int nleft;
|
850
|
nleft = ocb -> attr -> attr.nbytes - ocb -> offset;
|
851
|
nbytes = min( msg -> i.nbytes, nleft );
|
852
|
if( nleft )
|
853
|
ocb -> offset += nbytes;
|
854
|
}
|
855
|
|
856
|
if( nbytes > 0 )
|
857
|
{
|
858
|
/* Here we set the number of bytes we will return. */
|
859
|
_IO_SET_READ_NBYTES(ctp, nbytes);
|
860
|
|
861
|
/* The next line is used to tell the system how
|
862
|
* large your buffer is in which you want to return your
|
863
|
* data for the read() call.
|
864
|
*
|
865
|
*/
|
866
|
SETIOV( ctp->iov, &ocb -> attr -> buffer[offset], nbytes);
|
867
|
nparts = 1;
|
868
|
|
869
|
}
|
870
|
else
|
871
|
{
|
872
|
_IO_SET_READ_NBYTES(ctp, 0);
|
873
|
nparts = 0;
|
874
|
}
|
875
|
|
876
|
if (msg->i.nbytes > 0) {
|
877
|
ocb->attr->attr.flags |= IOFUNC_ATTR_ATIME;
|
878
|
}
|
879
|
|
880
|
/*
|
881
|
* Return the number of parts specified above (1 or 0).
|
882
|
*/
|
883
|
return (_RESMGR_NPARTS (nparts));
|
884
|
|
885
|
|
886
|
}
|
887
|
#if NEVER
|
888
|
static int
|
889
|
io_version_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
|
890
|
{
|
891
|
int status;
|
892
|
int nparts;
|
893
|
int nbytes = 0;
|
894
|
int offset = ocb->offset;
|
895
|
|
896
|
if (optv) {
|
897
|
printf ("%s: in io_read, id=%d\n", progname, ctp->id);
|
898
|
}
|
899
|
|
900
|
/* Here we verify if the client has the access
|
901
|
* rights needed to read from our device */
|
902
|
if ((status = iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) {
|
903
|
return (status);
|
904
|
}
|
905
|
|
906
|
/* We check if our read callback was called because of
|
907
|
* a pread() or a normal read() call. If pread(), we return
|
908
|
* with an error code indicating that we don't support it.*/
|
909
|
if (msg->i.xtype & _IO_XTYPE_MASK != _IO_XTYPE_NONE) {
|
910
|
return (ENOSYS);
|
911
|
}
|
912
|
/*
|
913
|
* Get the number of bytes to read. If requested is >1, look
|
914
|
* at the current offset to see if we have a byte to return.
|
915
|
* If the requested number is exactly 1, then read 1 byte.
|
916
|
*/
|
917
|
if( msg -> i.nbytes > 0)
|
918
|
{
|
919
|
int nleft;
|
920
|
nleft = ocb -> attr -> attr.nbytes - ocb -> offset;
|
921
|
nbytes = min( msg -> i.nbytes, nleft );
|
922
|
if( nleft )
|
923
|
ocb -> offset += nbytes;
|
924
|
}
|
925
|
if( nbytes )
|
926
|
{
|
927
|
|
928
|
/* Here we set the number of bytes we will return. */
|
929
|
_IO_SET_READ_NBYTES(ctp, nbytes);
|
930
|
|
931
|
/* The next line is used to tell the system how
|
932
|
* large your buffer is in which you want to return your
|
933
|
* data for the read() call.
|
934
|
*
|
935
|
* We get the pin value by reading the IN_DATA register, masking
|
936
|
* with the pinmask and if the value is 0, returning an ascii '0'.
|
937
|
* If the value is not 0, then we return an ascii '1'.
|
938
|
*/
|
939
|
SETIOV( ctp->iov, &ocb -> attr -> buffer[ocb->offset], nbytes);
|
940
|
nparts = 1;
|
941
|
|
942
|
}
|
943
|
else
|
944
|
{
|
945
|
_IO_SET_READ_NBYTES(ctp, 0);
|
946
|
nparts = 0;
|
947
|
}
|
948
|
|
949
|
if (msg->i.nbytes > 0) {
|
950
|
ocb->attr->attr.flags |= IOFUNC_ATTR_ATIME;
|
951
|
}
|
952
|
|
953
|
/*
|
954
|
* Return the number of parts specified above (1 or 0).
|
955
|
*/
|
956
|
return (_RESMGR_NPARTS (nparts));
|
957
|
|
958
|
|
959
|
}
|
960
|
#endif
|
961
|
|
962
|
/*
|
963
|
* io_write
|
964
|
*
|
965
|
* At this point, the client has called the library write()
|
966
|
* function, and expects that our resource manager will write
|
967
|
* the number of bytes that have been specified to the device.
|
968
|
*
|
969
|
* Since this is /dev/Null, all of the clients' writes always
|
970
|
* work -- they just go into Deep Outer Space.
|
971
|
*/
|
972
|
|
973
|
static int
|
974
|
io_cmd_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
|
975
|
{
|
976
|
int status;
|
977
|
char *buf;
|
978
|
char free_buf = 0;
|
979
|
//char value;
|
980
|
|
981
|
if (optv) {
|
982
|
printf ("%s: in io_write, id=%d\n", progname, ctp->id);
|
983
|
}
|
984
|
|
985
|
/* Check the access permissions of the client */
|
986
|
if ((status = iofunc_write_verify(ctp, msg, ocb, NULL)) != EOK) {
|
987
|
return (status);
|
988
|
}
|
989
|
|
990
|
/* Check if pwrite() or normal write() */
|
991
|
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
|
992
|
return (ENOSYS);
|
993
|
}
|
994
|
|
995
|
/* Set the number of bytes successfully written for
|
996
|
* the client. This information will be passed to the
|
997
|
* client by the resource manager framework upon reply.
|
998
|
* In this example, we just take the number of bytes that
|
999
|
* were sent to us and we always write them. */
|
1000
|
_IO_SET_WRITE_NBYTES (ctp, msg -> i.nbytes);
|
1001
|
|
1002
|
if( optv ) printf("got write of %d bytes, data:\n", msg->i.nbytes);
|
1003
|
|
1004
|
/* First check if our message buffer was large enough
|
1005
|
* to receive the whole write at once. If yes, print data.*/
|
1006
|
if( (msg->i.nbytes <= ctp->info.msglen - ctp->offset - sizeof(msg->i)) &&
|
1007
|
(ctp->info.msglen < ctp->msg_max_size)) { // space for NUL byte
|
1008
|
buf = (char *)(msg+1);
|
1009
|
|
1010
|
} else {
|
1011
|
/* If we did not receive the whole message because the
|
1012
|
* client wanted to send more than we could receive, we
|
1013
|
* allocate memory for all the data and use resmgr_msgread()
|
1014
|
* to read all the data at once. Although we did not receive
|
1015
|
* the data completely first, because our buffer was not big
|
1016
|
* enough, the data is still fully available on the client
|
1017
|
* side, because its write() call blocks until we return
|
1018
|
* from this callback! */
|
1019
|
buf = malloc( msg->i.nbytes + 1);
|
1020
|
free_buf = 1;
|
1021
|
if( buf )
|
1022
|
{
|
1023
|
resmgr_msgread( ctp, buf, msg->i.nbytes, sizeof(msg->i));
|
1024
|
}
|
1025
|
}
|
1026
|
/*
|
1027
|
* Write all the values to the pin.
|
1028
|
* The bytes passed in can be 3 types of values:
|
1029
|
* '1' causes the pin to be set
|
1030
|
* '0' causes the pin to be cleared
|
1031
|
* other values have no effect
|
1032
|
*/
|
1033
|
if( buf )
|
1034
|
{
|
1035
|
|
1036
|
int rv;
|
1037
|
int tmp;
|
1038
|
unsigned int cmd;
|
1039
|
rv = sscanf( buf, "%d", &cmd );
|
1040
|
switch( cmd )
|
1041
|
{
|
1042
|
case FPGA_CMD_RESET:
|
1043
|
gpio_direction_output( FPGA_PROGRAM, 0 );
|
1044
|
setFPGAState( FPGA_STATE_RESET );
|
1045
|
break;
|
1046
|
case FPGA_CMD_PROGRAM:
|
1047
|
gpio_direction_output( FPGA_PROGRAM, 1 );
|
1048
|
gpio_direction_output( FPGA_RDWR, 0 );
|
1049
|
setFPGAState( FPGA_STATE_PROGRAMMING );
|
1050
|
break;
|
1051
|
case FPGA_CMD_FINISHPROGRAM:
|
1052
|
gpio_direction_output( FPGA_RDWR, 1 );
|
1053
|
tmp = read_core_version( fpgactrl->vbaseaddr, &fpgactrl->app_version );
|
1054
|
if( !tmp )
|
1055
|
{
|
1056
|
tmp = read_core_version( fpgactrl->vbaseaddr, &fpgactrl->bm_version );
|
1057
|
setFPGAState( FPGA_STATE_PROGRAMMED );
|
1058
|
setVersion();
|
1059
|
}
|
1060
|
else
|
1061
|
{
|
1062
|
setFPGAState( FPGA_STATE_PROGRAM_FAIL );
|
1063
|
}
|
1064
|
break;
|
1065
|
}
|
1066
|
|
1067
|
|
1068
|
if( free_buf )
|
1069
|
free( buf );
|
1070
|
}
|
1071
|
|
1072
|
|
1073
|
/* Finally, if we received more than 0 bytes, we mark the
|
1074
|
* file information for the device to be updated:
|
1075
|
* modification time and change of file status time. To
|
1076
|
* avoid constant update of the real file status information
|
1077
|
* (which would involve overhead getting the current time), we
|
1078
|
* just set these flags. The actual update is done upon
|
1079
|
* closing, which is valid according to POSIX. */
|
1080
|
if (msg->i.nbytes > 0) {
|
1081
|
ocb->attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
|
1082
|
}
|
1083
|
|
1084
|
return (_RESMGR_NPARTS (0));
|
1085
|
}
|
1086
|
/*
|
1087
|
* io_write
|
1088
|
*
|
1089
|
* At this point, the client has called the library write()
|
1090
|
* function, and expects that our resource manager will write
|
1091
|
* the number of bytes that have been specified to the device.
|
1092
|
*
|
1093
|
* Since this is /dev/Null, all of the clients' writes always
|
1094
|
* work -- they just go into Deep Outer Space.
|
1095
|
*/
|
1096
|
|
1097
|
static int
|
1098
|
io_image_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
|
1099
|
{
|
1100
|
int status;
|
1101
|
char *buf;
|
1102
|
char free_buf = 0;
|
1103
|
//char value;
|
1104
|
|
1105
|
if (optv) {
|
1106
|
printf ("%s: in io_write, id=%d\n", progname, ctp->id);
|
1107
|
}
|
1108
|
|
1109
|
/* Check the access permissions of the client */
|
1110
|
if ((status = iofunc_write_verify(ctp, msg, ocb, NULL)) != EOK) {
|
1111
|
return (status);
|
1112
|
}
|
1113
|
|
1114
|
/* Check if pwrite() or normal write() */
|
1115
|
if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
|
1116
|
return (ENOSYS);
|
1117
|
}
|
1118
|
|
1119
|
/* Set the number of bytes successfully written for
|
1120
|
* the client. This information will be passed to the
|
1121
|
* client by the resource manager framework upon reply.
|
1122
|
* In this example, we just take the number of bytes that
|
1123
|
* were sent to us and we always write them. */
|
1124
|
_IO_SET_WRITE_NBYTES (ctp, msg -> i.nbytes);
|
1125
|
|
1126
|
if( optv ) printf("got write of %d bytes, data:\n", msg->i.nbytes);
|
1127
|
|
1128
|
/* First check if our message buffer was large enough
|
1129
|
* to receive the whole write at once. If yes, print data.*/
|
1130
|
if( (msg->i.nbytes <= ctp->info.msglen - ctp->offset - sizeof(msg->i)) &&
|
1131
|
(ctp->info.msglen < ctp->msg_max_size)) { // space for NUL byte
|
1132
|
buf = (char *)(msg+1);
|
1133
|
|
1134
|
} else {
|
1135
|
/* If we did not receive the whole message because the
|
1136
|
* client wanted to send more than we could receive, we
|
1137
|
* allocate memory for all the data and use resmgr_msgread()
|
1138
|
* to read all the data at once. Although we did not receive
|
1139
|
* the data completely first, because our buffer was not big
|
1140
|
* enough, the data is still fully available on the client
|
1141
|
* side, because its write() call blocks until we return
|
1142
|
* from this callback! */
|
1143
|
buf = malloc( msg->i.nbytes + 1);
|
1144
|
free_buf = 1;
|
1145
|
resmgr_msgread( ctp, buf, msg->i.nbytes, sizeof(msg->i));
|
1146
|
}
|
1147
|
/*
|
1148
|
* Write all the values to the pin.
|
1149
|
* The bytes passed in can be 3 types of values:
|
1150
|
* '1' causes the pin to be set
|
1151
|
* '0' causes the pin to be cleared
|
1152
|
* other values have no effect
|
1153
|
*/
|
1154
|
if( buf )
|
1155
|
{
|
1156
|
int i;
|
1157
|
char *p = buf;
|
1158
|
for( i = 0; i < msg -> i.nbytes; i++, p++ )
|
1159
|
{
|
1160
|
out8( fpgactrl->vbaseaddr, *p );
|
1161
|
}
|
1162
|
if( free_buf )
|
1163
|
free( buf );
|
1164
|
}
|
1165
|
|
1166
|
|
1167
|
/* Finally, if we received more than 0 bytes, we mark the
|
1168
|
* file information for the device to be updated:
|
1169
|
* modification time and change of file status time. To
|
1170
|
* avoid constant update of the real file status information
|
1171
|
* (which would involve overhead getting the current time), we
|
1172
|
* just set these flags. The actual update is done upon
|
1173
|
* closing, which is valid according to POSIX. */
|
1174
|
if (msg->i.nbytes > 0) {
|
1175
|
ocb->attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
|
1176
|
}
|
1177
|
|
1178
|
return (_RESMGR_NPARTS (0));
|
1179
|
}
|
1180
|
/* Why we don't have any close callback? Because the default
|
1181
|
* function, iofunc_close_ocb_default(), does all we need in this
|
1182
|
* case: Free the ocb, update the time stamps etc. See the docs
|
1183
|
* for more info.
|
1184
|
*/
|
1185
|
|
1186
|
|