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