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

Subversion Repositories igor

[/] [igor/] [trunk/] [simulator/] [io.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 atypic
#include <stdio.h>
2
#include <err.h>
3
 
4
#include "io.h"
5
#include "types.h"
6
#include "object.h"
7
 
8
uint32_t n_devices, curdev;
9
 
10
device_t devices[MAX_DEVICES];
11
 
12
void io_init_dev(uint32_t devnr);
13
 
14
void
15
io_init(void)
16
{
17
        int i;
18
        n_devices = MAX_DEVICES;
19
        curdev = DEV_TERMINAL;
20
        for (i = 0; i < MAX_DEVICES; i++) {
21
                io_init_dev(i);
22
        }
23
}
24
 
25
void
26
io_init_dev(uint32_t devnr)
27
{
28
        device_t *dev = &devices[devnr];
29
        dev->make_object = 0;
30
        dev->addr = 0;
31
        dev->size = 0;
32
        dev->status = 0;
33
        dev->irqenable = 0;
34
        dev->fw = dev->fr = NULL;
35
        dev->ident = devnr << DEVTYPE_SHIFT;
36
        switch (devnr) {
37
        case DEV_BOOT:
38
                dev->ident |= CAN_READ | ADDR_READ;
39
                dev->make_object = 1;
40
                break;
41
        case DEV_TERMINAL:
42
        case DEV_SERIAL:
43
        case DEV_NETWORK:
44
                dev->ident |= CAN_READ | CAN_WRITE;
45
                break;
46
        case DEV_STORAGE:
47
                dev->ident |= CAN_READ | CAN_WRITE | ADDR_READ | ADDR_WRITE;
48
                dev->make_object = 1;
49
                break;
50
        default:
51
                errx(1, "unknown device 0x%X", devnr);
52
        }
53
}
54
 
55
void
56
io_find_size(uint32_t devnr, int write)
57
{
58
        device_t *dev = &devices[devnr];
59
        FILE *f = write?dev->fw:dev->fr;
60
        if (dev->ident & (write?ADDR_WRITE:ADDR_READ)) {
61
                if (fseek(f, 0, SEEK_END) == -1) {
62
                        warn("could not find size for device %X", devnr);
63
                        return;
64
                }
65
                dev->size = ftell(f);
66
                if (dev->size == -1) {
67
                        warn("could not find size for device %X", devnr);
68
                        return;
69
                }
70
                if (fseek(f, 0, SEEK_SET) == -1) {
71
                        warn("could not rewind device %X", devnr);
72
                        return;
73
                }
74
                if (dev->make_object)
75
                        dev->size /= 4;
76
                printf("size of device %X: 0x%lX\n", devnr, (long)dev->size);
77
        }
78
}
79
 
80
void
81
io_set_file(uint32_t devnr, char *filename)
82
{
83
        printf("set_file(%X, %s)\n", devnr, filename);
84
        device_t *dev = &devices[devnr];
85
        char *mode =
86
                (dev->ident & (CAN_READ|CAN_WRITE)) ?
87
                "r+" :
88
                ((dev->ident & CAN_WRITE) ? "w" : "r");
89
        dev->fr = dev->fw = fopen(filename, mode);
90
        if (dev->fr == NULL)
91
                warn("could not open %s", filename);
92
        io_find_size(devnr, 0);
93
        io_find_size(devnr, 1);
94
}
95
 
96
void
97
io_set_files(uint32_t devnr, char *readfile, char *writefile)
98
{
99
        printf("set_files(%X, %s, %s)\n", devnr,
100
               readfile==NULL?"NULL":readfile, writefile==NULL?"NULL":writefile);
101
        device_t *dev = &devices[devnr];
102
        if (readfile != NULL) {
103
                dev->fr = fopen(readfile, "r");
104
                if (dev->fr == NULL)
105
                        warn("could not open %s for reading", readfile);
106
                printf("fr=%X\n", (int)(dev->fr));
107
                io_find_size(devnr, 0);
108
        }
109
        if (writefile != NULL) {
110
                dev->fw = fopen(writefile, "w");
111
                if (dev->fw == NULL)
112
                        warn("could not open %s for writing", writefile);
113
                io_find_size(devnr, 1);
114
        }
115
}
116
 
117
int
118
check_device_connected(uint32_t devnr, int write)
119
{
120
        device_t *dev = &devices[devnr];
121
        /*
122
        printf("check_conn(%X,%d): fw=%X, fr=%X\n",
123
               devnr, write, (int)(dev->fw), (int)(dev->fr));
124
        */
125
        if ((write?dev->fw:dev->fr) == NULL) {
126
                warnx("(I/O %s) device 0x%X not connected",
127
                      write?"write":"read", curdev);
128
                return 0;
129
        }
130
        return 1;
131
}
132
 
133
void
134
io_update_address(uint32_t devnr)
135
{
136
        device_t *dev = &devices[devnr];
137
 
138
        uint64_t addr = dev->addr;
139
        if (dev->make_object) addr *= 4;
140
 
141
        if ((dev->ident & ADDR_WRITE) && check_device_connected(devnr, 1)) {
142
                if (fseek(dev->fw, addr, SEEK_SET) == -1)
143
                        warn("could not set write address on device %X", curdev);
144
        }
145
        if ((dev->ident & ADDR_READ) && check_device_connected(curdev, 0)) {
146
                if (fseek(dev->fw, addr, SEEK_SET) == -1)
147
                        warn("could not set read address on device %X", curdev);
148
        }
149
}
150
 
151
void
152
io_get_new_address(uint32_t devnr, int write)
153
{
154
        device_t *dev = &devices[devnr];
155
 
156
        if (dev->ident & (write?ADDR_WRITE:ADDR_READ)) {
157
                int addr = ftell(write?dev->fw:dev->fr);
158
                if (addr == -1) {
159
                        warn("could not get new %s address from device %X",
160
                             write?"write":"read", devnr);
161
                } else {
162
                        if (dev->make_object) addr /= 4;
163
                        dev->addr = addr;
164
                }
165
        }
166
}
167
 
168
void
169
io_memory_set(unsigned int pos, reg_t value)
170
{
171
        device_t *dev = &devices[curdev];
172
        uint32_t datum = object_get_datum(value);
173
 
174
        switch (pos) {
175
        case IO_DEVICES:
176
                warnx("write to read-only I/O register DEVICES");
177
                break;
178
        case IO_CURDEV:
179
                curdev = datum;
180
                break;
181
        case IO_CLI:
182
                warnx("CLI: not implemented");
183
                break;
184
        case IO_SAI:
185
                warnx("SAI: not implemented");
186
                break;
187
        case IO_INTRDEV:
188
                warnx("write to read-only I/O register INTRDEV");
189
                break;
190
        case IO_OBJECT:
191
                if (check_device_connected(curdev, 1)) {
192
//                      printf("writing '%c' to device %X\n", datum, curdev);
193
                        if(dev->make_object) {
194
                                object_write(&value, 1, dev->fw);
195
                        }else{
196
                                if (fputc(datum, dev->fw) == EOF ||
197
                                                fflush(dev->fw) == EOF)
198
                                        warn("could not write to device %X", curdev);
199
                        }
200
                        io_get_new_address(curdev, 1);
201
                }
202
                break;
203
        case IO_ADDR_L:
204
                if (dev->ident & (ADDR_READ | ADDR_WRITE)) {
205
                        check_device_connected(curdev, 1);
206
                        dev->addr &= (~0) << 26;
207
                        dev->addr |= datum;
208
                        io_update_address(curdev);
209
                }
210
                break;
211
        case IO_ADDR_H:
212
                if (dev->ident & (ADDR_READ | ADDR_WRITE)) {
213
                        dev->addr &= OBJECT_DATUM_MASK;
214
                        dev->addr |= datum << 26;
215
                        io_update_address(curdev);
216
                }
217
                break;
218
        case IO_SIZE_L:
219
                warnx("write to read-only I/O register SIZE_L");
220
                break;
221
        case IO_SIZE_H:
222
                warnx("write to read-only I/O register SIZE_H");
223
                break;
224
        case IO_STATUS:
225
                if (datum == 0) {
226
                        dev->status &= (~ERRCODE_MASK) << ERRCODE_SHIFT;
227
                } else {
228
                        warnx("nonzero write to I/O register STATUS");
229
                }
230
                break;
231
        case IO_IDENT:
232
                warnx("write to read-only I/O register INDENT");
233
                break;
234
        case IO_IRQENABLE:
235
                dev->irqenable = datum;
236
                break;
237
        default:
238
                warnx("write to unused I/O register 0x%X", pos);
239
        }
240
}
241
 
242
char
243
dev_getchar(uint32_t devnr)
244
{
245
        device_t *dev = &devices[curdev];
246
        char ch;
247
 
248
 getcharrestart:
249
        ch = fgetc(dev->fr);
250
        if (ch == EOF) {
251
                if (devnr == DEV_SERIAL)
252
                        goto getcharrestart;
253
 
254
                warnx("could not read from device %X", curdev);
255
                return EOF;
256
        }
257
        //printf("Char: %d/%c\n", ch, ch);
258
        return ch;
259
}
260
 
261
reg_t
262
io_memory_get(unsigned int pos)
263
{
264
        device_t *dev = &devices[curdev];
265
        reg_t val = object_make(TYPE_INT, 0);
266
        switch (pos) {
267
        case IO_DEVICES:
268
                val = object_make(TYPE_INT, n_devices);
269
                break;
270
        case IO_CURDEV:
271
                val = object_make(TYPE_INT, curdev);
272
                break;
273
        case IO_CLI:
274
                warnx("read from write-only I/O register CLI");
275
                break;
276
        case IO_SAI:
277
                warnx("read from write-only I/O register SAI");
278
                break;
279
        case IO_INTRDEV:
280
                warnx("INTRDEV: not implemented");
281
                break;
282
        case IO_OBJECT:
283
                if (check_device_connected(curdev, 0)) {
284
                        if (dev->make_object) {
285
                                if (!object_read(&val, 1, dev->fr))
286
                                        warn("could not read from any device");
287
                        } else {
288
                                val = object_make(TYPE_CHAR, dev_getchar(curdev));
289
                        }
290
                        io_get_new_address(curdev, 0);
291
                } else {
292
                        warnx("device %X not connected", curdev);
293
                }
294
                break;
295
        case IO_ADDR_L:
296
                val = object_make(TYPE_INT, dev->addr & OBJECT_DATUM_MASK);
297
                break;
298
        case IO_ADDR_H:
299
                val = object_make(TYPE_INT, (dev->addr>>26) & OBJECT_DATUM_MASK);
300
                break;
301
        case IO_SIZE_L:
302
                printf("asking for size (l) of device %X; size is %lX\n",
303
                       curdev, (long)dev->size);
304
                val = object_make(TYPE_INT, dev->size & OBJECT_DATUM_MASK);
305
                break;
306
        case IO_SIZE_H:
307
                printf("asking for size (h) of device %X; size is %lX\n",
308
                       curdev, (long)dev->size);
309
                val = object_make(TYPE_INT, (dev->size>>26) & OBJECT_DATUM_MASK);
310
                break;
311
        case IO_STATUS:
312
                val = object_make(TYPE_INT, dev->status);
313
                break;
314
        case IO_IDENT:
315
                val = object_make(TYPE_INT, dev->ident);
316
                break;
317
        case IO_IRQENABLE:
318
                val = object_make(TYPE_INT, dev->irqenable);
319
                break;
320
        default:
321
                warnx("read from unused I/O register 0x%X", pos);
322
                break;
323
        }
324
 
325
        return val;
326
}

powered by: WebSVN 2.1.0

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