source: trunk/packages/xen-3.1/xen-3.1/tools/ioemu/hw/tc58128.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 4.2 KB
Line 
1#include <assert.h>
2#include "vl.h"
3
4#define CE1  0x0100
5#define CE2  0x0200
6#define RE   0x0400
7#define WE   0x0800
8#define ALE  0x1000
9#define CLE  0x2000
10#define RDY1 0x4000
11#define RDY2 0x8000
12#define RDY(n) ((n) == 0 ? RDY1 : RDY2)
13
14typedef enum { WAIT, READ1, READ2, READ3 } state_t;
15
16typedef struct {
17    uint8_t *flash_contents;
18    state_t state;
19    uint32_t address;
20    uint8_t address_cycle;
21} tc58128_dev;
22
23static tc58128_dev tc58128_devs[2];
24
25#define FLASH_SIZE (16*1024*1024)
26
27void init_dev(tc58128_dev * dev, char *filename)
28{
29    int ret, blocks;
30
31    dev->state = WAIT;
32    dev->flash_contents = qemu_mallocz(FLASH_SIZE);
33    memset(dev->flash_contents, 0xff, FLASH_SIZE);
34    if (!dev->flash_contents) {
35        fprintf(stderr, "could not alloc memory for flash\n");
36        exit(1);
37    }
38    if (filename) {
39        /* Load flash image skipping the first block */
40        ret = load_image(filename, dev->flash_contents + 528 * 32);
41        if (ret < 0) {
42            fprintf(stderr, "ret=%d\n", ret);
43            fprintf(stderr, "qemu: could not load flash image %s\n",
44                    filename);
45            exit(1);
46        } else {
47            /* Build first block with number of blocks */
48            blocks = (ret + 528 * 32 - 1) / (528 * 32);
49            dev->flash_contents[0] = blocks & 0xff;
50            dev->flash_contents[1] = (blocks >> 8) & 0xff;
51            dev->flash_contents[2] = (blocks >> 16) & 0xff;
52            dev->flash_contents[3] = (blocks >> 24) & 0xff;
53            fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
54                    filename);
55        }
56    }
57}
58
59void handle_command(tc58128_dev * dev, uint8_t command)
60{
61    switch (command) {
62    case 0xff:
63        fprintf(stderr, "reset flash device\n");
64        dev->state = WAIT;
65        break;
66    case 0x00:
67        fprintf(stderr, "read mode 1\n");
68        dev->state = READ1;
69        dev->address_cycle = 0;
70        break;
71    case 0x01:
72        fprintf(stderr, "read mode 2\n");
73        dev->state = READ2;
74        dev->address_cycle = 0;
75        break;
76    case 0x50:
77        fprintf(stderr, "read mode 3\n");
78        dev->state = READ3;
79        dev->address_cycle = 0;
80        break;
81    default:
82        fprintf(stderr, "unknown flash command 0x%02x\n", command);
83        assert(0);
84    }
85}
86
87void handle_address(tc58128_dev * dev, uint8_t data)
88{
89    switch (dev->state) {
90    case READ1:
91    case READ2:
92    case READ3:
93        switch (dev->address_cycle) {
94        case 0:
95            dev->address = data;
96            if (dev->state == READ2)
97                dev->address |= 0x100;
98            else if (dev->state == READ3)
99                dev->address |= 0x200;
100            break;
101        case 1:
102            dev->address += data * 528 * 0x100;
103            break;
104        case 2:
105            dev->address += data * 528;
106            fprintf(stderr, "address pointer in flash: 0x%08x\n",
107                    dev->address);
108            break;
109        default:
110            /* Invalid data */
111            assert(0);
112        }
113        dev->address_cycle++;
114        break;
115    default:
116        assert(0);
117    }
118}
119
120uint8_t handle_read(tc58128_dev * dev)
121{
122#if 0
123    if (dev->address % 0x100000 == 0)
124        fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
125#endif
126    return dev->flash_contents[dev->address++];
127}
128
129/* We never mark the device as busy, so interrupts cannot be triggered
130   XXXXX */
131
132int tc58128_cb(uint16_t porta, uint16_t portb,
133               uint16_t * periph_pdtra, uint16_t * periph_portadir,
134               uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
135{
136    int dev;
137
138    if ((porta & CE1) == 0)
139        dev = 0;
140    else if ((porta & CE2) == 0)
141        dev = 1;
142    else
143        return 0;               /* No device selected */
144
145    if ((porta & RE) && (porta & WE)) {
146        /* Nothing to do, assert ready and return to input state */
147        *periph_portadir &= 0xff00;
148        *periph_portadir |= RDY(dev);
149        *periph_pdtra |= RDY(dev);
150        return 1;
151    }
152
153    if (porta & CLE) {
154        /* Command */
155        assert((porta & WE) == 0);
156        handle_command(&tc58128_devs[dev], porta & 0x00ff);
157    } else if (porta & ALE) {
158        assert((porta & WE) == 0);
159        handle_address(&tc58128_devs[dev], porta & 0x00ff);
160    } else if ((porta & RE) == 0) {
161        *periph_portadir |= 0x00ff;
162        *periph_pdtra &= 0xff00;
163        *periph_pdtra |= handle_read(&tc58128_devs[dev]);
164    } else {
165        assert(0);
166    }
167    return 1;
168}
169
170static sh7750_io_device tc58128 = {
171    RE | WE,                    /* Port A triggers */
172    0,                          /* Port B triggers */
173    tc58128_cb                  /* Callback */
174};
175
176int tc58128_init(struct SH7750State *s, char *zone1, char *zone2)
177{
178    init_dev(&tc58128_devs[0], zone1);
179    init_dev(&tc58128_devs[1], zone2);
180    return sh7750_register_io_device(s, &tc58128);
181}
Note: See TracBrowser for help on using the repository browser.