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