OpenCores
URL https://opencores.org/ocsvn/igor/igor/trunk

Subversion Repositories igor

[/] [igor/] [trunk/] [avr/] [eth-test/] [dispatch.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 atypic
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "global.h"
4
 
5
#include <stdint.h>
6
#include <stdlib.h>
7
#include <stdio.h>
8
#include <string.h>
9
 
10
#include "encdec.h"
11
#include "req.h"
12
#include "device.h"
13
#include "dispatch.h"
14
#include "dev/7seg.h"
15
#include "dev/spi.h"
16
 
17
#include "req.h"
18
#include "bus.h"
19
 
20
#include "uip/telnetd.h"
21
#include "uip/uip.h"
22
#include "uip/uip-conf.h"
23
#include "uip/uip_arp.h"
24
#include "uip/timer.h"
25
#include "uip/clock.h"
26
#include "dev/nic.h"
27
#include "dev/enc28j60-uip.c"
28
 
29
#define swap32(x)                       \
30
        ((((x) & 0xff000000) >> 24) |   \
31
        (((x) & 0x00ff0000) >>  8) |    \
32
        (((x) & 0x0000ff00) <<  8) |    \
33
        (((x) & 0x000000ff) << 24))
34
 
35
/* Peripherals we know of. */
36
//extern struct igordev igordev_boot;
37
extern struct igordev igordev_usart;
38
//extern struct igordev igordev_mmc;
39
//extern struct igordev igordev_kvga;
40
#define NUMDEV 1
41
struct igordev *idevs[NUMDEV];
42
 
43
// Currently seleted device
44
volatile uint32_t curdev;
45
// Last device performing interrupt.
46
volatile uint32_t intrdev;
47
 
48
volatile struct req *rqueue[MAXREQ];
49
 
50
static void     dispatch_request_perform(volatile struct req *);
51
 
52
void init_network_stuff(void);
53
void do_network_stuff(void);
54
 
55
#ifdef WITH_DEBUG
56
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
57
#else
58
#define DEBUG(...)
59
#endif
60
/* Contains the dispatcher and its routines. */
61
int
62
main(void)
63
{
64
        struct idev_mgmt *imgmt;
65
        volatile struct req *req;
66
        uint32_t i, data;
67
 
68
        cli();
69
        curdev = DEVTYPE_BOOT;
70
 
71
        /* Initialize device structure with the different device types. */
72
//      idevs[DEVTYPE_BOOT] = &igordev_boot;
73
        idevs[DEVTYPE_SERIAL] = &igordev_usart;
74
//      idevs[DEVTYPE_STORAGE] = &igordev_mmc;
75
//      idevs[DEVTYPE_TERM] = &igordev_kvga;
76
 
77
        for (i = 0; i < MAXREQ; i++)
78
                rqueue[i] = NULL;
79
 
80
        init_fpgabus();
81
        req_init();
82
        _delay_ms(1);
83
//      display_init(); // 7Seg init
84
        DEBUG("Initializing devices\n");
85
        configure_spi(); //Must run before Ethernet/MMC init
86
        for (i = 0; i < NUMDEV; i++) {
87
                idevs[i]->init();
88
                imgmt = &idevs[i]->imgmt;
89
                imgmt->irqenable = 0;
90
                imgmt->baseaddr = 0;
91
                imgmt->curaddr = 0;
92
                imgmt->size = 0;
93
        }
94
        init_network_stuff();
95
        DEBUG("Done initializing devices\n");
96
 
97
        /* Boot load test. */
98
//      for (i = 0; i < 10; i++) {
99
//              display_char(i);
100
//              _delay_ms(50.0);
101
//      }
102
//      display_char(curdev);
103
/*
104
   BOOT BLOCK LAYOUT
105
 
106
   +---------------------------+----------+
107
   | Boot program size         | 4 bytes  |
108
   +---------------------------+----------+
109
   | Data area size            | 4 bytes  |
110
   +---------------------------+----------+
111
   |                           |          |
112
   |  Boot program             | Variable |
113
   |                           |          |
114
   +---------------------------+----------+
115
   |                           |          |
116
   |  Data area                | Variable |
117
   |                           |          |
118
   +---------------------------+----------+
119
 
120
 */
121
        /* Initialize the device boot block layout. */
122
        /* Read boot program size */
123
//      igordev_mmc.read(0, (uint8_t *)&data, 4);
124
//      igordev_boot.imgmt.size = swap32(data);
125
//      igordev_mmc.read(0, (uint8_t *)&data, 4);
126
//      igordev_mmc.imgmt.size = swap32(data);
127
        /* Set up segments. */
128
//      igordev_boot.imgmt.baseaddr = 8;
129
//      igordev_mmc.imgmt.baseaddr = 8 + igordev_boot.imgmt.size;
130
        _delay_ms(10);
131
        sei();
132
//      avr_online();
133
 
134
        while (1) {
135
 
136
                /* Look through all active requests. */
137
                for (i = 0; i < MAXREQ; i++) {
138
                        if (rqueue[i] == NULL)
139
                                continue;
140
                        req = rqueue[i];
141
                        dispatch_request_perform(req);
142
                        rqueue[i] = NULL;
143
                        req_free(req);
144
                }
145
                do_network_stuff();
146
        }
147
        return (0);
148
}
149
 
150
static void
151
dispatch_request_perform(volatile struct req *req)
152
{
153
        struct igordev *idev;
154
        struct idev_mgmt *imgmt;
155
        volatile struct req *nreq;
156
        uint32_t data, d;
157
        uint8_t num, osize, total, *ptr;
158
 
159
        idev = req->dev;
160
        imgmt = &idev->imgmt;
161
        switch (req->type) {
162
        case REQ_TYPE_READ:
163
                /* Wait until device is ready. */
164
                while (idev->read_status != IDEV_STATUS_OK);
165
                total = DATA_SIZE_TYPE(DATA_TYPE_DEV(req->devnum));
166
                ptr = (uint8_t *)&data;
167
                while (idev->read_status != IDEV_STATUS_ERROR) {
168
                        num = idev->read(imgmt->curaddr + imgmt->baseaddr, ptr,
169
                            total);
170
                        total -= num;
171
                        imgmt->curaddr += num;
172
                        if (total <= 0)
173
                                break;
174
                        ptr += num;
175
                }
176
                if (idev->read_status == IDEV_STATUS_ERROR)
177
                        return;
178
                if (req->flags & REQ_CALLBACK) {
179
                        d = encode_object(data, req->devnum);
180
 
181
                        DEBUG("Perform buffer read from main: '%c'\n", d);
182
                        fpga_finish_read(d);
183
                }
184
                break;
185
        case REQ_TYPE_WRITE:
186
                /* Wait until device is ready. */
187
                while (idev->write_status != IDEV_STATUS_OK);
188
 
189
                data = decode_object(fpga_delayed_write(), req->devnum, &osize);
190
                total = osize;
191
//              if (imgmt->curaddr + total >= imgmt->size)
192
//                      imgmt->curaddr = 0;
193
                /* Write until we have been able to write the data. */
194
                ptr = (uint8_t *)&data;
195
                while (idev->write_status != IDEV_STATUS_ERROR) {
196
                        num = idev->write(imgmt->curaddr + imgmt->baseaddr, ptr,
197
                            osize);
198
                        // Try and flush if we can't write
199
                        // XXX: Should count and report error if it doesn't
200
                        // help.
201
                        if (num == 0)
202
                                idev->flush();
203
                        total -= num;
204
                        imgmt->curaddr += num;
205
                        if (total <= 0)
206
                                break;
207
                        ptr += num;
208
                }
209
                if (idev->write_status == IDEV_STATUS_ERROR)
210
                        return;
211
                // Request a flush now that we finished the write.
212
                nreq = req_make(idev, REQ_TYPE_FLUSH, 0, req->devnum, NULL);
213
                if (nreq != NULL)
214
                        dispatch_request_notify(nreq);
215
                break;
216
        case REQ_TYPE_FLUSH:
217
                idev->flush();
218
                break;
219
        case REQ_TYPE_FUNC:
220
                req->func(idev->priv);
221
                break;
222
        }
223
}
224
 
225
/*
226
 * Notify the dispatcher of an I/O request. Note that the request is dropped if
227
 * there is no space for it in the queue!
228
 */
229
void
230
dispatch_request_notify(volatile struct req *req)
231
{
232
        uint8_t i;
233
 
234
        for (i = 0; i < MAXREQ; i++) {
235
                if (rqueue[i] == NULL) {
236
                        rqueue[i] = req;
237
                        return;
238
                }
239
        }
240
}
241
 
242
int8_t
243
dispatch_request_read(uint8_t addr, uint32_t *data)
244
{
245
        struct igordev *idev;
246
        struct idev_mgmt *imgmt;
247
        volatile struct req *req;
248
        uint32_t status;
249
 
250
        /* See what address we want to read from. */
251
        switch (addr) {
252
        case DEVICES:
253
                *data = OBJECT_NEW(TYPE_INT, NUMDEV);
254
                return (0);
255
        case CURDEV:
256
                *data = OBJECT_NEW(TYPE_INT, curdev);
257
                return (0);
258
        case CLI:
259
        case SAI:
260
                *data = 0;
261
                return (0);
262
        case INTRDEV:
263
                *data = OBJECT_NEW(TYPE_INT, intrdev);
264
                return (0);
265
        };
266
 
267
        /* Device-specific operation, so fetch currently enabled device. */
268
        idev = idevs[curdev];
269
        imgmt = &idev->imgmt;
270
 
271
        switch (addr) {
272
        /* Read an object from current device. */
273
        case OBJECT:
274
                break;
275
        /* Read lower 26 bits of current address from device. */
276
        case ADDR_L:
277
                *data = OBJECT_NEW(TYPE_INT, (uint32_t)(imgmt->curaddr >> 2));
278
                return (0);
279
        /* Read upper 26 bits of current address from device. */
280
        case ADDR_H:
281
                *data = OBJECT_NEW(TYPE_INT, (uint32_t)((imgmt->curaddr >> 2) >>
282
                    SIZE_INT));
283
                return (0);
284
        /* Read lower 26 bits of device size. */
285
        case SIZE_L:
286
                *data = OBJECT_NEW(TYPE_INT, (uint32_t)(imgmt->size >> 2));
287
                return (0);
288
        /* Read upper 26 bits of device size. */
289
        case SIZE_H:
290
                *data = OBJECT_NEW(TYPE_INT, (uint32_t)((imgmt->size >> 2) >>
291
                    SIZE_INT));
292
                return (0);
293
        /* Read status register of device. */
294
        case STATUS:
295
                status = (idev->read_status == IDEV_STATUS_OK);
296
                status |= ((idev->write_status == IDEV_STATUS_OK) <<
297
                    1);
298
                /* XXX: Error codes. */
299
                *data = OBJECT_NEW(TYPE_INT, status);
300
                return (0);
301
        /* Device identification. */
302
        case IDENTIFICATION:
303
                *data = OBJECT_NEW(TYPE_INT, idev->id);
304
                return (0);
305
        /* Read irq enable for device. */
306
        case IRQENABLE:
307
                *data = OBJECT_NEW(TYPE_INT, (uint32_t)imgmt->irqenable);
308
                return (0);
309
        default: /* XXX: Invalid address. */
310
                return (0);
311
        }
312
 
313
        DEBUG("Reading object of size %d\n", osize);
314
        /* Request for a read. */
315
        req = req_make(idev, REQ_TYPE_READ, REQ_CALLBACK, curdev, NULL);
316
        if (req == NULL)
317
                return (-1); /* XXX: Set error. */
318
        dispatch_request_notify(req);
319
        return (-1);
320
}
321
 
322
int8_t
323
dispatch_request_write(uint8_t addr, uint32_t data)
324
{
325
        struct igordev *idev;
326
        struct idev_mgmt *imgmt;
327
        volatile struct req *req;
328
        uint32_t status;
329
        uint64_t newaddr;
330
        uint8_t i; //num, osize;
331
 
332
        /* See what address we want to read from. */
333
        switch (addr) {
334
        /* Read-only */
335
        case DEVICES:
336
        case INTRDEV:
337
                return (0);
338
        case CURDEV:
339
                DEBUG("Setting current device\n");
340
                /* Should perhaps have some error signalling. */
341
                if (OBJECT_DATUM(data) >= NUMDEV)
342
                        return (0); /* Invalid device. */
343
                curdev = OBJECT_DATUM(data);
344
                display_char(curdev);
345
                return (0);
346
        case CLI:
347
                for (i = 0; i < NUMDEV; i++)
348
                        idevs[i]->imgmt.irqenable = 0;
349
                return (0);
350
        case SAI:
351
                for (i = 0; i < NUMDEV; i++)
352
                        idevs[i]->imgmt.irqenable = 1;
353
                return (0);
354
        };
355
        idev = idevs[curdev];
356
        imgmt = &idev->imgmt;
357
        switch (addr) {
358
        /* Read-only. */
359
        case SIZE_L:
360
        case SIZE_H:
361
        case IDENTIFICATION:
362
                return (0);
363
        /* Write an object from current device. */
364
        case OBJECT:
365
                break;
366
        /* Write lower 26 bits of current address from device. */
367
        case ADDR_L:
368
                newaddr = (OBJECT_DATUM(data) << 2) |
369
                    ((uint64_t)((uint32_t)(imgmt->curaddr >> BSIZE_INT)) <<
370
                    BSIZE_INT);
371
                // Only set it if it does not exceed the device space.
372
                if (newaddr + imgmt->baseaddr < imgmt->size)
373
                        imgmt->curaddr = newaddr;
374
                return (0);
375
        /* Read upper 26 bits of current address from device. */
376
        case ADDR_H:
377
                newaddr = ((OBJECT_DATUM(data) << 2) << BSIZE_INT) |
378
                    ((uint32_t)imgmt->curaddr);
379
                // Only set it if it does not exceed the device space.
380
                if (newaddr + imgmt->baseaddr < imgmt->size)
381
                        imgmt->curaddr = newaddr;
382
                return (0);
383
        /* Read status register of device. */
384
        case STATUS:
385
                /* Writing 0 resets the error codes. */
386
                status = OBJECT_DATUM(data);
387
                if (status != 0)
388
                        return (0); /* Not allowed. */
389
                /* XXX: reset error codes. */
390
                return (0);
391
        /* Set irq enable for device. */
392
        case IRQENABLE:
393
                imgmt->irqenable = OBJECT_DATUM(data);
394
                return (0);
395
        default: /* XXX: Invalid address. */
396
                return (0);
397
        }
398
        display_char(11);
399
        if ( idev == NULL )
400
            display_char(13);
401
        req = req_make(idev, REQ_TYPE_WRITE, REQ_CALLBACK, curdev, NULL);
402
        display_char(4);
403
        if (req == NULL) {
404
                display_char(5);
405
                return (-2); /* XXX: panic */
406
        }
407
        display_char(6);
408
        dispatch_request_notify(req);
409
        display_char(7);
410
        return (-1);
411
}
412
 
413
/* Read data from kvga and put it in usart output buffer. */
414
/*void
415
dispatch_vga_to_usart(void *args)
416
{
417
        uint8_t data[MAXBUFLEN];
418
        uint8_t num;
419
 
420
        num = igordev_kvga.read(1, data, MAXBUFLEN);
421
        igordev_usart.write(1, data, num);
422
        while (igordev_usart.write_status != IDEV_STATUS_OK);
423
}
424
*/
425
//Network stuff - cleanup and integrate into driver framework later
426
 
427
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
428
struct timer periodic_timer, arp_timer;
429
 
430
void init_network_stuff(void)
431
{
432
        uip_ipaddr_t ipaddr;
433
 
434
        clock_init(); //This also activates interrupts
435
 
436
        timer_set(&periodic_timer, (clock_time_t)(F_CPU / 2));
437
        timer_set(&arp_timer, (clock_time_t)(F_CPU * 10));
438
 
439
        network_init();
440
 
441
        uip_init();
442
 
443
        uip_ipaddr(ipaddr, 192,168,0,25);
444
        uip_sethostaddr(ipaddr);
445
 
446
        uip_ipaddr(ipaddr, 255,255,255,0);
447
        uip_setnetmask(ipaddr);
448
 
449
        //Init applications
450
        telnetd_init();
451
}
452
 
453
void do_network_stuff(void)
454
{
455
        int i;
456
        uip_len = network_read();
457
        if(uip_len > 0) {
458
                if(BUF->type == htons(UIP_ETHTYPE_IP)) {
459
                        uip_arp_ipin();
460
                        uip_input();
461
        /* If the above function invocation resulted in data that
462
           should be sent out on the network, the global variable
463
           uip_len is set to a value > 0. */
464
                        if(uip_len > 0) {
465
                                uip_arp_out();
466
                                network_send();
467
                        }
468
                } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
469
                        uip_arp_arpin();
470
        /* If the above function invocation resulted in data that
471
           should be sent out on the network, the global variable
472
           uip_len is set to a value > 0. */
473
                        if(uip_len > 0) {
474
                                network_send();
475
                        }
476
                }
477
 
478
        } else if(timer_expired(&periodic_timer)) {
479
                timer_reset(&periodic_timer);
480
                for(i = 0; i < UIP_CONNS; i++) {
481
                        uip_periodic(i);
482
        /* If the above function invocation resulted in data that
483
           should be sent out on the network, the global variable
484
           uip_len is set to a value > 0. */
485
                        if(uip_len > 0) {
486
                                uip_arp_out();
487
                                network_send();
488
                        }
489
                }
490
 
491
#if UIP_UDP
492
                for(i = 0; i < UIP_UDP_CONNS; i++) {
493
                        uip_udp_periodic(i);
494
        /* If the above function invocation resulted in data that
495
           should be sent out on the network, the global variable
496
           uip_len is set to a value > 0. */
497
                        if(uip_len > 0) {
498
                                uip_arp_out();
499
                                network_send();
500
                        }
501
                }
502
#endif /* UIP_UDP */
503
 
504
        /* Call the ARP timer function every 10 seconds. */
505
                if(timer_expired(&arp_timer)) {
506
                        timer_reset(&arp_timer);
507
                        uip_arp_timer();
508
                }
509
        }
510
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.