Statistics
| Branch: | Revision:

root / hw / tc58128.c @ 87ecb68b

History | View | Annotate | Download (4.2 kB)

1
#include <assert.h>
2
#include "hw.h"
3
#include "sh.h"
4
#include "sysemu.h"
5

    
6
#define CE1  0x0100
7
#define CE2  0x0200
8
#define RE   0x0400
9
#define WE   0x0800
10
#define ALE  0x1000
11
#define CLE  0x2000
12
#define RDY1 0x4000
13
#define RDY2 0x8000
14
#define RDY(n) ((n) == 0 ? RDY1 : RDY2)
15

    
16
typedef enum { WAIT, READ1, READ2, READ3 } state_t;
17

    
18
typedef struct {
19
    uint8_t *flash_contents;
20
    state_t state;
21
    uint32_t address;
22
    uint8_t address_cycle;
23
} tc58128_dev;
24

    
25
static tc58128_dev tc58128_devs[2];
26

    
27
#define FLASH_SIZE (16*1024*1024)
28

    
29
void init_dev(tc58128_dev * dev, char *filename)
30
{
31
    int ret, blocks;
32

    
33
    dev->state = WAIT;
34
    dev->flash_contents = qemu_mallocz(FLASH_SIZE);
35
    memset(dev->flash_contents, 0xff, FLASH_SIZE);
36
    if (!dev->flash_contents) {
37
        fprintf(stderr, "could not alloc memory for flash\n");
38
        exit(1);
39
    }
40
    if (filename) {
41
        /* Load flash image skipping the first block */
42
        ret = load_image(filename, dev->flash_contents + 528 * 32);
43
        if (ret < 0) {
44
            fprintf(stderr, "ret=%d\n", ret);
45
            fprintf(stderr, "qemu: could not load flash image %s\n",
46
                    filename);
47
            exit(1);
48
        } else {
49
            /* Build first block with number of blocks */
50
            blocks = (ret + 528 * 32 - 1) / (528 * 32);
51
            dev->flash_contents[0] = blocks & 0xff;
52
            dev->flash_contents[1] = (blocks >> 8) & 0xff;
53
            dev->flash_contents[2] = (blocks >> 16) & 0xff;
54
            dev->flash_contents[3] = (blocks >> 24) & 0xff;
55
            fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
56
                    filename);
57
        }
58
    }
59
}
60

    
61
void handle_command(tc58128_dev * dev, uint8_t command)
62
{
63
    switch (command) {
64
    case 0xff:
65
        fprintf(stderr, "reset flash device\n");
66
        dev->state = WAIT;
67
        break;
68
    case 0x00:
69
        fprintf(stderr, "read mode 1\n");
70
        dev->state = READ1;
71
        dev->address_cycle = 0;
72
        break;
73
    case 0x01:
74
        fprintf(stderr, "read mode 2\n");
75
        dev->state = READ2;
76
        dev->address_cycle = 0;
77
        break;
78
    case 0x50:
79
        fprintf(stderr, "read mode 3\n");
80
        dev->state = READ3;
81
        dev->address_cycle = 0;
82
        break;
83
    default:
84
        fprintf(stderr, "unknown flash command 0x%02x\n", command);
85
        assert(0);
86
    }
87
}
88

    
89
void handle_address(tc58128_dev * dev, uint8_t data)
90
{
91
    switch (dev->state) {
92
    case READ1:
93
    case READ2:
94
    case READ3:
95
        switch (dev->address_cycle) {
96
        case 0:
97
            dev->address = data;
98
            if (dev->state == READ2)
99
                dev->address |= 0x100;
100
            else if (dev->state == READ3)
101
                dev->address |= 0x200;
102
            break;
103
        case 1:
104
            dev->address += data * 528 * 0x100;
105
            break;
106
        case 2:
107
            dev->address += data * 528;
108
            fprintf(stderr, "address pointer in flash: 0x%08x\n",
109
                    dev->address);
110
            break;
111
        default:
112
            /* Invalid data */
113
            assert(0);
114
        }
115
        dev->address_cycle++;
116
        break;
117
    default:
118
        assert(0);
119
    }
120
}
121

    
122
uint8_t handle_read(tc58128_dev * dev)
123
{
124
#if 0
125
    if (dev->address % 0x100000 == 0)
126
        fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
127
#endif
128
    return dev->flash_contents[dev->address++];
129
}
130

    
131
/* We never mark the device as busy, so interrupts cannot be triggered
132
   XXXXX */
133

    
134
int tc58128_cb(uint16_t porta, uint16_t portb,
135
               uint16_t * periph_pdtra, uint16_t * periph_portadir,
136
               uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
137
{
138
    int dev;
139

    
140
    if ((porta & CE1) == 0)
141
        dev = 0;
142
    else if ((porta & CE2) == 0)
143
        dev = 1;
144
    else
145
        return 0;                /* No device selected */
146

    
147
    if ((porta & RE) && (porta & WE)) {
148
        /* Nothing to do, assert ready and return to input state */
149
        *periph_portadir &= 0xff00;
150
        *periph_portadir |= RDY(dev);
151
        *periph_pdtra |= RDY(dev);
152
        return 1;
153
    }
154

    
155
    if (porta & CLE) {
156
        /* Command */
157
        assert((porta & WE) == 0);
158
        handle_command(&tc58128_devs[dev], porta & 0x00ff);
159
    } else if (porta & ALE) {
160
        assert((porta & WE) == 0);
161
        handle_address(&tc58128_devs[dev], porta & 0x00ff);
162
    } else if ((porta & RE) == 0) {
163
        *periph_portadir |= 0x00ff;
164
        *periph_pdtra &= 0xff00;
165
        *periph_pdtra |= handle_read(&tc58128_devs[dev]);
166
    } else {
167
        assert(0);
168
    }
169
    return 1;
170
}
171

    
172
static sh7750_io_device tc58128 = {
173
    RE | WE,                        /* Port A triggers */
174
    0,                                /* Port B triggers */
175
    tc58128_cb                        /* Callback */
176
};
177

    
178
int tc58128_init(struct SH7750State *s, char *zone1, char *zone2)
179
{
180
    init_dev(&tc58128_devs[0], zone1);
181
    init_dev(&tc58128_devs[1], zone2);
182
    return sh7750_register_io_device(s, &tc58128);
183
}