|
|
1.1 ! root 1: /* ! 2: * Intel XScale PXA255/270 PC Card and CompactFlash Interface. ! 3: * ! 4: * Copyright (c) 2006 Openedhand Ltd. ! 5: * Written by Andrzej Zaborowski <[email protected]> ! 6: * ! 7: * This code is licensed under the GPLv2. ! 8: */ ! 9: ! 10: #include "hw.h" ! 11: #include "pcmcia.h" ! 12: #include "pxa.h" ! 13: ! 14: struct pxa2xx_pcmcia_s { ! 15: struct pcmcia_socket_s slot; ! 16: struct pcmcia_card_s *card; ! 17: target_phys_addr_t common_base; ! 18: target_phys_addr_t attr_base; ! 19: target_phys_addr_t io_base; ! 20: ! 21: qemu_irq irq; ! 22: qemu_irq cd_irq; ! 23: }; ! 24: ! 25: static uint32_t pxa2xx_pcmcia_common_read(void *opaque, ! 26: target_phys_addr_t offset) ! 27: { ! 28: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 29: ! 30: if (s->slot.attached) { ! 31: offset -= s->common_base; ! 32: return s->card->common_read(s->card->state, offset); ! 33: } ! 34: ! 35: return 0; ! 36: } ! 37: ! 38: static void pxa2xx_pcmcia_common_write(void *opaque, ! 39: target_phys_addr_t offset, uint32_t value) ! 40: { ! 41: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 42: ! 43: if (s->slot.attached) { ! 44: offset -= s->common_base; ! 45: s->card->common_write(s->card->state, offset, value); ! 46: } ! 47: } ! 48: ! 49: static uint32_t pxa2xx_pcmcia_attr_read(void *opaque, ! 50: target_phys_addr_t offset) ! 51: { ! 52: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 53: ! 54: if (s->slot.attached) { ! 55: offset -= s->attr_base; ! 56: return s->card->attr_read(s->card->state, offset); ! 57: } ! 58: ! 59: return 0; ! 60: } ! 61: ! 62: static void pxa2xx_pcmcia_attr_write(void *opaque, ! 63: target_phys_addr_t offset, uint32_t value) ! 64: { ! 65: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 66: ! 67: if (s->slot.attached) { ! 68: offset -= s->attr_base; ! 69: s->card->attr_write(s->card->state, offset, value); ! 70: } ! 71: } ! 72: ! 73: static uint32_t pxa2xx_pcmcia_io_read(void *opaque, ! 74: target_phys_addr_t offset) ! 75: { ! 76: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 77: ! 78: if (s->slot.attached) { ! 79: offset -= s->io_base; ! 80: return s->card->io_read(s->card->state, offset); ! 81: } ! 82: ! 83: return 0; ! 84: } ! 85: ! 86: static void pxa2xx_pcmcia_io_write(void *opaque, ! 87: target_phys_addr_t offset, uint32_t value) ! 88: { ! 89: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 90: ! 91: if (s->slot.attached) { ! 92: offset -= s->io_base; ! 93: s->card->io_write(s->card->state, offset, value); ! 94: } ! 95: } ! 96: ! 97: static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = { ! 98: pxa2xx_pcmcia_common_read, ! 99: pxa2xx_pcmcia_common_read, ! 100: pxa2xx_pcmcia_common_read, ! 101: }; ! 102: ! 103: static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = { ! 104: pxa2xx_pcmcia_common_write, ! 105: pxa2xx_pcmcia_common_write, ! 106: pxa2xx_pcmcia_common_write, ! 107: }; ! 108: ! 109: static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = { ! 110: pxa2xx_pcmcia_attr_read, ! 111: pxa2xx_pcmcia_attr_read, ! 112: pxa2xx_pcmcia_attr_read, ! 113: }; ! 114: ! 115: static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = { ! 116: pxa2xx_pcmcia_attr_write, ! 117: pxa2xx_pcmcia_attr_write, ! 118: pxa2xx_pcmcia_attr_write, ! 119: }; ! 120: ! 121: static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = { ! 122: pxa2xx_pcmcia_io_read, ! 123: pxa2xx_pcmcia_io_read, ! 124: pxa2xx_pcmcia_io_read, ! 125: }; ! 126: ! 127: static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = { ! 128: pxa2xx_pcmcia_io_write, ! 129: pxa2xx_pcmcia_io_write, ! 130: pxa2xx_pcmcia_io_write, ! 131: }; ! 132: ! 133: static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level) ! 134: { ! 135: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 136: if (!s->irq) ! 137: return; ! 138: ! 139: qemu_set_irq(s->irq, level); ! 140: } ! 141: ! 142: struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base) ! 143: { ! 144: int iomemtype; ! 145: struct pxa2xx_pcmcia_s *s; ! 146: ! 147: s = (struct pxa2xx_pcmcia_s *) ! 148: qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s)); ! 149: ! 150: /* Socket I/O Memory Space */ ! 151: s->io_base = base | 0x00000000; ! 152: iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_io_readfn, ! 153: pxa2xx_pcmcia_io_writefn, s); ! 154: cpu_register_physical_memory(s->io_base, 0x04000000, iomemtype); ! 155: ! 156: /* Then next 64 MB is reserved */ ! 157: ! 158: /* Socket Attribute Memory Space */ ! 159: s->attr_base = base | 0x08000000; ! 160: iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_attr_readfn, ! 161: pxa2xx_pcmcia_attr_writefn, s); ! 162: cpu_register_physical_memory(s->attr_base, 0x04000000, iomemtype); ! 163: ! 164: /* Socket Common Memory Space */ ! 165: s->common_base = base | 0x0c000000; ! 166: iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_common_readfn, ! 167: pxa2xx_pcmcia_common_writefn, s); ! 168: cpu_register_physical_memory(s->common_base, 0x04000000, iomemtype); ! 169: ! 170: if (base == 0x30000000) ! 171: s->slot.slot_string = "PXA PC Card Socket 1"; ! 172: else ! 173: s->slot.slot_string = "PXA PC Card Socket 0"; ! 174: s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0]; ! 175: pcmcia_socket_register(&s->slot); ! 176: ! 177: return s; ! 178: } ! 179: ! 180: /* Insert a new card into a slot */ ! 181: int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card) ! 182: { ! 183: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 184: if (s->slot.attached) ! 185: return -EEXIST; ! 186: ! 187: if (s->cd_irq) { ! 188: qemu_irq_raise(s->cd_irq); ! 189: } ! 190: ! 191: s->card = card; ! 192: ! 193: s->slot.attached = 1; ! 194: s->card->slot = &s->slot; ! 195: s->card->attach(s->card->state); ! 196: ! 197: return 0; ! 198: } ! 199: ! 200: /* Eject card from the slot */ ! 201: int pxa2xx_pcmcia_dettach(void *opaque) ! 202: { ! 203: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 204: if (!s->slot.attached) ! 205: return -ENOENT; ! 206: ! 207: s->card->detach(s->card->state); ! 208: s->card->slot = 0; ! 209: s->card = 0; ! 210: ! 211: s->slot.attached = 0; ! 212: ! 213: if (s->irq) ! 214: qemu_irq_lower(s->irq); ! 215: if (s->cd_irq) ! 216: qemu_irq_lower(s->cd_irq); ! 217: ! 218: return 0; ! 219: } ! 220: ! 221: /* Who to notify on card events */ ! 222: void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq) ! 223: { ! 224: struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque; ! 225: s->irq = irq; ! 226: s->cd_irq = cd_irq; ! 227: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.