tcg: fix size of local variables in tcg_gen_bswap64_i64
[qemu] / hw / pl181.c
1 /*
2  * Arm PrimeCell PL181 MultiMedia Card Interface
3  *
4  * Copyright (c) 2007 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licenced under the GPL.
8  */
9
10 #include "sysbus.h"
11 #include "sd.h"
12 #include "sysemu.h"
13
14 //#define DEBUG_PL181 1
15
16 #ifdef DEBUG_PL181
17 #define DPRINTF(fmt, ...) \
18 do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
19 #else
20 #define DPRINTF(fmt, ...) do {} while(0)
21 #endif
22
23 #define PL181_FIFO_LEN 16
24
25 typedef struct {
26     SysBusDevice busdev;
27     SDState *card;
28     uint32_t clock;
29     uint32_t power;
30     uint32_t cmdarg;
31     uint32_t cmd;
32     uint32_t datatimer;
33     uint32_t datalength;
34     uint32_t respcmd;
35     uint32_t response[4];
36     uint32_t datactrl;
37     uint32_t datacnt;
38     uint32_t status;
39     uint32_t mask[2];
40     int fifo_pos;
41     int fifo_len;
42     /* The linux 2.6.21 driver is buggy, and misbehaves if new data arrives
43        while it is reading the FIFO.  We hack around this be defering
44        subsequent transfers until after the driver polls the status word.
45        http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
46      */
47     int linux_hack;
48     uint32_t fifo[PL181_FIFO_LEN];
49     qemu_irq irq[2];
50 } pl181_state;
51
52 #define PL181_CMD_INDEX     0x3f
53 #define PL181_CMD_RESPONSE  (1 << 6)
54 #define PL181_CMD_LONGRESP  (1 << 7)
55 #define PL181_CMD_INTERRUPT (1 << 8)
56 #define PL181_CMD_PENDING   (1 << 9)
57 #define PL181_CMD_ENABLE    (1 << 10)
58
59 #define PL181_DATA_ENABLE             (1 << 0)
60 #define PL181_DATA_DIRECTION          (1 << 1)
61 #define PL181_DATA_MODE               (1 << 2)
62 #define PL181_DATA_DMAENABLE          (1 << 3)
63
64 #define PL181_STATUS_CMDCRCFAIL       (1 << 0)
65 #define PL181_STATUS_DATACRCFAIL      (1 << 1)
66 #define PL181_STATUS_CMDTIMEOUT       (1 << 2)
67 #define PL181_STATUS_DATATIMEOUT      (1 << 3)
68 #define PL181_STATUS_TXUNDERRUN       (1 << 4)
69 #define PL181_STATUS_RXOVERRUN        (1 << 5)
70 #define PL181_STATUS_CMDRESPEND       (1 << 6)
71 #define PL181_STATUS_CMDSENT          (1 << 7)
72 #define PL181_STATUS_DATAEND          (1 << 8)
73 #define PL181_STATUS_DATABLOCKEND     (1 << 10)
74 #define PL181_STATUS_CMDACTIVE        (1 << 11)
75 #define PL181_STATUS_TXACTIVE         (1 << 12)
76 #define PL181_STATUS_RXACTIVE         (1 << 13)
77 #define PL181_STATUS_TXFIFOHALFEMPTY  (1 << 14)
78 #define PL181_STATUS_RXFIFOHALFFULL   (1 << 15)
79 #define PL181_STATUS_TXFIFOFULL       (1 << 16)
80 #define PL181_STATUS_RXFIFOFULL       (1 << 17)
81 #define PL181_STATUS_TXFIFOEMPTY      (1 << 18)
82 #define PL181_STATUS_RXFIFOEMPTY      (1 << 19)
83 #define PL181_STATUS_TXDATAAVLBL      (1 << 20)
84 #define PL181_STATUS_RXDATAAVLBL      (1 << 21)
85
86 #define PL181_STATUS_TX_FIFO (PL181_STATUS_TXACTIVE \
87                              |PL181_STATUS_TXFIFOHALFEMPTY \
88                              |PL181_STATUS_TXFIFOFULL \
89                              |PL181_STATUS_TXFIFOEMPTY \
90                              |PL181_STATUS_TXDATAAVLBL)
91 #define PL181_STATUS_RX_FIFO (PL181_STATUS_RXACTIVE \
92                              |PL181_STATUS_RXFIFOHALFFULL \
93                              |PL181_STATUS_RXFIFOFULL \
94                              |PL181_STATUS_RXFIFOEMPTY \
95                              |PL181_STATUS_RXDATAAVLBL)
96
97 static const unsigned char pl181_id[] =
98 { 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
99
100 static void pl181_update(pl181_state *s)
101 {
102     int i;
103     for (i = 0; i < 2; i++) {
104         qemu_set_irq(s->irq[i], (s->status & s->mask[i]) != 0);
105     }
106 }
107
108 static void pl181_fifo_push(pl181_state *s, uint32_t value)
109 {
110     int n;
111
112     if (s->fifo_len == PL181_FIFO_LEN) {
113         fprintf(stderr, "pl181: FIFO overflow\n");
114         return;
115     }
116     n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
117     s->fifo_len++;
118     s->fifo[n] = value;
119     DPRINTF("FIFO push %08x\n", (int)value);
120 }
121
122 static uint32_t pl181_fifo_pop(pl181_state *s)
123 {
124     uint32_t value;
125
126     if (s->fifo_len == 0) {
127         fprintf(stderr, "pl181: FIFO underflow\n");
128         return 0;
129     }
130     value = s->fifo[s->fifo_pos];
131     s->fifo_len--;
132     s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
133     DPRINTF("FIFO pop %08x\n", (int)value);
134     return value;
135 }
136
137 static void pl181_send_command(pl181_state *s)
138 {
139     SDRequest request;
140     uint8_t response[16];
141     int rlen;
142
143     request.cmd = s->cmd & PL181_CMD_INDEX;
144     request.arg = s->cmdarg;
145     DPRINTF("Command %d %08x\n", request.cmd, request.arg);
146     rlen = sd_do_command(s->card, &request, response);
147     if (rlen < 0)
148         goto error;
149     if (s->cmd & PL181_CMD_RESPONSE) {
150 #define RWORD(n) ((response[n] << 24) | (response[n + 1] << 16) \
151                   | (response[n + 2] << 8) | response[n + 3])
152         if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP)))
153             goto error;
154         if (rlen != 4 && rlen != 16)
155             goto error;
156         s->response[0] = RWORD(0);
157         if (rlen == 4) {
158             s->response[1] = s->response[2] = s->response[3] = 0;
159         } else {
160             s->response[1] = RWORD(4);
161             s->response[2] = RWORD(8);
162             s->response[3] = RWORD(12) & ~1;
163         }
164         DPRINTF("Response received\n");
165         s->status |= PL181_STATUS_CMDRESPEND;
166 #undef RWORD
167     } else {
168         DPRINTF("Command sent\n");
169         s->status |= PL181_STATUS_CMDSENT;
170     }
171     return;
172
173 error:
174     DPRINTF("Timeout\n");
175     s->status |= PL181_STATUS_CMDTIMEOUT;
176 }
177
178 /* Transfer data between the card and the FIFO.  This is complicated by
179    the FIFO holding 32-bit words and the card taking data in single byte
180    chunks.  FIFO bytes are transferred in little-endian order.  */
181
182 static void pl181_fifo_run(pl181_state *s)
183 {
184     uint32_t bits;
185     uint32_t value;
186     int n;
187     int limit;
188     int is_read;
189
190     is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
191     if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
192             && !s->linux_hack) {
193         limit = is_read ? PL181_FIFO_LEN : 0;
194         n = 0;
195         value = 0;
196         while (s->datacnt && s->fifo_len != limit) {
197             if (is_read) {
198                 value |= (uint32_t)sd_read_data(s->card) << (n * 8);
199                 n++;
200                 if (n == 4) {
201                     pl181_fifo_push(s, value);
202                     value = 0;
203                     n = 0;
204                 }
205             } else {
206                 if (n == 0) {
207                     value = pl181_fifo_pop(s);
208                     n = 4;
209                 }
210                 sd_write_data(s->card, value & 0xff);
211                 value >>= 8;
212                 n--;
213             }
214             s->datacnt--;
215         }
216         if (n && is_read) {
217             pl181_fifo_push(s, value);
218         }
219     }
220     s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
221     if (s->datacnt == 0) {
222         s->status |= PL181_STATUS_DATAEND;
223         /* HACK: */
224         s->status |= PL181_STATUS_DATABLOCKEND;
225         DPRINTF("Transfer Complete\n");
226     }
227     if (s->datacnt == 0 && s->fifo_len == 0) {
228         s->datactrl &= ~PL181_DATA_ENABLE;
229         DPRINTF("Data engine idle\n");
230     } else {
231         /* Update FIFO bits.  */
232         bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
233         if (s->fifo_len == 0) {
234             bits |= PL181_STATUS_TXFIFOEMPTY;
235             bits |= PL181_STATUS_RXFIFOEMPTY;
236         } else {
237             bits |= PL181_STATUS_TXDATAAVLBL;
238             bits |= PL181_STATUS_RXDATAAVLBL;
239         }
240         if (s->fifo_len == 16) {
241             bits |= PL181_STATUS_TXFIFOFULL;
242             bits |= PL181_STATUS_RXFIFOFULL;
243         }
244         if (s->fifo_len <= 8) {
245             bits |= PL181_STATUS_TXFIFOHALFEMPTY;
246         }
247         if (s->fifo_len >= 8) {
248             bits |= PL181_STATUS_RXFIFOHALFFULL;
249         }
250         if (s->datactrl & PL181_DATA_DIRECTION) {
251             bits &= PL181_STATUS_RX_FIFO;
252         } else {
253             bits &= PL181_STATUS_TX_FIFO;
254         }
255         s->status |= bits;
256     }
257 }
258
259 static uint32_t pl181_read(void *opaque, target_phys_addr_t offset)
260 {
261     pl181_state *s = (pl181_state *)opaque;
262     uint32_t tmp;
263
264     if (offset >= 0xfe0 && offset < 0x1000) {
265         return pl181_id[(offset - 0xfe0) >> 2];
266     }
267     switch (offset) {
268     case 0x00: /* Power */
269         return s->power;
270     case 0x04: /* Clock */
271         return s->clock;
272     case 0x08: /* Argument */
273         return s->cmdarg;
274     case 0x0c: /* Command */
275         return s->cmd;
276     case 0x10: /* RespCmd */
277         return s->respcmd;
278     case 0x14: /* Response0 */
279         return s->response[0];
280     case 0x18: /* Response1 */
281         return s->response[1];
282     case 0x1c: /* Response2 */
283         return s->response[2];
284     case 0x20: /* Response3 */
285         return s->response[3];
286     case 0x24: /* DataTimer */
287         return s->datatimer;
288     case 0x28: /* DataLength */
289         return s->datalength;
290     case 0x2c: /* DataCtrl */
291         return s->datactrl;
292     case 0x30: /* DataCnt */
293         return s->datacnt;
294     case 0x34: /* Status */
295         tmp = s->status;
296         if (s->linux_hack) {
297             s->linux_hack = 0;
298             pl181_fifo_run(s);
299             pl181_update(s);
300         }
301         return tmp;
302     case 0x3c: /* Mask0 */
303         return s->mask[0];
304     case 0x40: /* Mask1 */
305         return s->mask[1];
306     case 0x48: /* FifoCnt */
307         /* The documentation is somewhat vague about exactly what FifoCnt
308            does.  On real hardware it appears to be when decrememnted
309            when a word is transfered between the FIFO and the serial
310            data engine.  DataCnt is decremented after each byte is
311            transfered between the serial engine and the card.
312            We don't emulate this level of detail, so both can be the same.  */
313         tmp = (s->datacnt + 3) >> 2;
314         if (s->linux_hack) {
315             s->linux_hack = 0;
316             pl181_fifo_run(s);
317             pl181_update(s);
318         }
319         return tmp;
320     case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
321     case 0x90: case 0x94: case 0x98: case 0x9c:
322     case 0xa0: case 0xa4: case 0xa8: case 0xac:
323     case 0xb0: case 0xb4: case 0xb8: case 0xbc:
324         if (s->fifo_len == 0) {
325             fprintf(stderr, "pl181: Unexpected FIFO read\n");
326             return 0;
327         } else {
328             uint32_t value;
329             value = pl181_fifo_pop(s);
330             s->linux_hack = 1;
331             pl181_fifo_run(s);
332             pl181_update(s);
333             return value;
334         }
335     default:
336         hw_error("pl181_read: Bad offset %x\n", (int)offset);
337         return 0;
338     }
339 }
340
341 static void pl181_write(void *opaque, target_phys_addr_t offset,
342                           uint32_t value)
343 {
344     pl181_state *s = (pl181_state *)opaque;
345
346     switch (offset) {
347     case 0x00: /* Power */
348         s->power = value & 0xff;
349         break;
350     case 0x04: /* Clock */
351         s->clock = value & 0xff;
352         break;
353     case 0x08: /* Argument */
354         s->cmdarg = value;
355         break;
356     case 0x0c: /* Command */
357         s->cmd = value;
358         if (s->cmd & PL181_CMD_ENABLE) {
359             if (s->cmd & PL181_CMD_INTERRUPT) {
360                 fprintf(stderr, "pl181: Interrupt mode not implemented\n");
361                 abort();
362             } if (s->cmd & PL181_CMD_PENDING) {
363                 fprintf(stderr, "pl181: Pending commands not implemented\n");
364                 abort();
365             } else {
366                 pl181_send_command(s);
367                 pl181_fifo_run(s);
368             }
369             /* The command has completed one way or the other.  */
370             s->cmd &= ~PL181_CMD_ENABLE;
371         }
372         break;
373     case 0x24: /* DataTimer */
374         s->datatimer = value;
375         break;
376     case 0x28: /* DataLength */
377         s->datalength = value & 0xffff;
378         break;
379     case 0x2c: /* DataCtrl */
380         s->datactrl = value & 0xff;
381         if (value & PL181_DATA_ENABLE) {
382             s->datacnt = s->datalength;
383             pl181_fifo_run(s);
384         }
385         break;
386     case 0x38: /* Clear */
387         s->status &= ~(value & 0x7ff);
388         break;
389     case 0x3c: /* Mask0 */
390         s->mask[0] = value;
391         break;
392     case 0x40: /* Mask1 */
393         s->mask[1] = value;
394         break;
395     case 0x80: case 0x84: case 0x88: case 0x8c: /* FifoData */
396     case 0x90: case 0x94: case 0x98: case 0x9c:
397     case 0xa0: case 0xa4: case 0xa8: case 0xac:
398     case 0xb0: case 0xb4: case 0xb8: case 0xbc:
399         if (s->datacnt == 0) {
400             fprintf(stderr, "pl181: Unexpected FIFO write\n");
401         } else {
402             pl181_fifo_push(s, value);
403             pl181_fifo_run(s);
404         }
405         break;
406     default:
407         hw_error("pl181_write: Bad offset %x\n", (int)offset);
408     }
409     pl181_update(s);
410 }
411
412 static CPUReadMemoryFunc * const pl181_readfn[] = {
413    pl181_read,
414    pl181_read,
415    pl181_read
416 };
417
418 static CPUWriteMemoryFunc * const pl181_writefn[] = {
419    pl181_write,
420    pl181_write,
421    pl181_write
422 };
423
424 static void pl181_reset(void *opaque)
425 {
426     pl181_state *s = (pl181_state *)opaque;
427
428     s->power = 0;
429     s->cmdarg = 0;
430     s->cmd = 0;
431     s->datatimer = 0;
432     s->datalength = 0;
433     s->respcmd = 0;
434     s->response[0] = 0;
435     s->response[1] = 0;
436     s->response[2] = 0;
437     s->response[3] = 0;
438     s->datatimer = 0;
439     s->datalength = 0;
440     s->datactrl = 0;
441     s->datacnt = 0;
442     s->status = 0;
443     s->linux_hack = 0;
444     s->mask[0] = 0;
445     s->mask[1] = 0;
446 }
447
448 static int pl181_init(SysBusDevice *dev)
449 {
450     int iomemtype;
451     pl181_state *s = FROM_SYSBUS(pl181_state, dev);
452     BlockDriverState *bd;
453
454     iomemtype = cpu_register_io_memory(pl181_readfn,
455                                        pl181_writefn, s);
456     sysbus_init_mmio(dev, 0x1000, iomemtype);
457     sysbus_init_irq(dev, &s->irq[0]);
458     sysbus_init_irq(dev, &s->irq[1]);
459     bd = qdev_init_bdrv(&dev->qdev, IF_SD);
460     s->card = sd_init(bd, 0);
461     qemu_register_reset(pl181_reset, s);
462     pl181_reset(s);
463     /* ??? Save/restore.  */
464     return 0;
465 }
466
467 static void pl181_register_devices(void)
468 {
469     sysbus_register_dev("pl181", sizeof(pl181_state), pl181_init);
470 }
471
472 device_init(pl181_register_devices)