The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arch/amiga/dev/gayle_pcmcia.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: gayle_pcmcia.c,v 1.34 2021/08/07 16:18:41 thorpej Exp $ */
    2 
    3 /* public domain */
    4 
    5 #include <sys/cdefs.h>
    6 __KERNEL_RCSID(0, "$NetBSD: gayle_pcmcia.c,v 1.34 2021/08/07 16:18:41 thorpej Exp $");
    7 
    8 /* PCMCIA front-end driver for A1200's and A600's. */
    9 
   10 #include <sys/param.h>
   11 #include <sys/device.h>
   12 #include <sys/kernel.h>
   13 #include <sys/kthread.h>
   14 #include <sys/systm.h>
   15 
   16 #include <uvm/uvm.h>
   17 
   18 #include <dev/pcmcia/pcmciareg.h>
   19 #include <dev/pcmcia/pcmciavar.h>
   20 
   21 #include <machine/cpu.h>
   22 #include <amiga/amiga/custom.h>
   23 #include <amiga/amiga/device.h>
   24 #include <amiga/amiga/gayle.h>
   25 #include <amiga/amiga/isr.h>
   26 
   27 
   28 /* There is one of these for each slot. And yes, there is only one slot. */
   29 struct pccard_slot {
   30         struct  pccard_softc *sc;       /* refer to `parent' */
   31         int     (*intr_func)(void *);
   32         void *  intr_arg;
   33         device_t card;
   34         int     flags;
   35 #define SLOT_OCCUPIED           0x01
   36 #define SLOT_NEW_CARD_EVENT     0x02
   37 };
   38 
   39 struct pccard_softc {
   40         struct bus_space_tag io_space;
   41         struct bus_space_tag attr_space;
   42         struct bus_space_tag mem_space;
   43         struct pccard_slot devs[1];
   44         struct isr intr6;
   45         struct isr intr2;
   46 };
   47 
   48 static int      pccard_probe(device_t, cfdata_t, void *);
   49 static void     pccard_attach(device_t, device_t, void *);
   50 static void     pccard_attach_slot(struct pccard_slot *);
   51 static int      pccard_intr6(void *);
   52 static int      pccard_intr2(void *);
   53 static void     pccard_kthread(void *);
   54 
   55 static int pcf_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
   56                 struct pcmcia_mem_handle *);
   57 static void pcf_mem_free(pcmcia_chipset_handle_t, struct pcmcia_mem_handle *);
   58 static int pcf_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
   59                 struct pcmcia_mem_handle *, bus_addr_t *, int *);
   60 static void pcf_mem_unmap(pcmcia_chipset_handle_t, int);
   61 static int pcf_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, bus_size_t,
   62                 bus_size_t, struct pcmcia_io_handle *);
   63 static void pcf_io_free(pcmcia_chipset_handle_t, struct pcmcia_io_handle *);
   64 static int pcf_io_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
   65                 struct pcmcia_io_handle *, int *);
   66 static void pcf_io_unmap(pcmcia_chipset_handle_t, int);
   67 static void *pcf_intr_establish(pcmcia_chipset_handle_t,
   68                 struct pcmcia_function *, int, int (*)(void *), void *);
   69 static void pcf_intr_disestablish(pcmcia_chipset_handle_t, void *);
   70 static void pcf_socket_enable(pcmcia_chipset_handle_t);
   71 static void pcf_socket_disable(pcmcia_chipset_handle_t);
   72 static void pcf_socket_settype(pcmcia_chipset_handle_t, int);
   73 
   74 static bsr(pcmio_bsr1, u_int8_t);
   75 static bsw(pcmio_bsw1, u_int8_t);
   76 static bsrm(pcmio_bsrm1, u_int8_t);
   77 static bswm(pcmio_bswm1, u_int8_t);
   78 static bsrm(pcmio_bsrr1, u_int8_t);
   79 static bswm(pcmio_bswr1, u_int8_t);
   80 static bssr(pcmio_bssr1, u_int8_t);
   81 static bscr(pcmio_bscr1, u_int8_t);
   82 
   83 CFATTACH_DECL_NEW(pccard, sizeof(struct pccard_softc),
   84     pccard_probe, pccard_attach, NULL, NULL);
   85 
   86 static struct pcmcia_chip_functions chip_functions = {
   87         pcf_mem_alloc,          pcf_mem_free,
   88         pcf_mem_map,            pcf_mem_unmap,
   89         pcf_io_alloc,           pcf_io_free,
   90         pcf_io_map,             pcf_io_unmap,
   91         pcf_intr_establish,     pcf_intr_disestablish,
   92         pcf_socket_enable,      pcf_socket_disable,
   93         pcf_socket_settype
   94 };
   95 
   96 static struct amiga_bus_space_methods pcmio_bs_methods;
   97 
   98 static u_int8_t *reset_card_reg;
   99 
  100 static int
  101 pccard_probe(device_t parent, cfdata_t cf, void *aux)
  102 {
  103 
  104         return (is_a600() || is_a1200()) && matchname(aux, "pccard");
  105 }
  106 
  107 static void
  108 pccard_attach(device_t parent, device_t self, void *aux)
  109 {
  110         struct pccard_softc *sc = device_private(self);
  111         struct pcmciabus_attach_args paa;
  112         vaddr_t pcmcia_base;
  113         vaddr_t i;
  114 
  115         printf("\n");
  116 
  117         gayle_init();
  118 
  119         pcmcia_base = uvm_km_alloc(kernel_map,
  120                                    GAYLE_PCMCIA_END - GAYLE_PCMCIA_START,
  121                                    0, UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
  122         if (pcmcia_base == 0) {
  123                 printf("attach failed (no virtual memory)\n");
  124                 return;
  125         }
  126 
  127         for (i = GAYLE_PCMCIA_START; i < GAYLE_PCMCIA_END; i += PAGE_SIZE)
  128                 pmap_enter(vm_map_pmap(kernel_map),
  129                     i - GAYLE_PCMCIA_START + pcmcia_base, i,
  130                     VM_PROT_READ | VM_PROT_WRITE, true);
  131         pmap_update(vm_map_pmap(kernel_map));
  132 
  133         /* override the one-byte access methods for I/O space */
  134         pcmio_bs_methods = amiga_bus_stride_1swap;
  135         pcmio_bs_methods.bsr1 = pcmio_bsr1;
  136         pcmio_bs_methods.bsw1 = pcmio_bsw1;
  137         pcmio_bs_methods.bsrm1 = pcmio_bsrm1;
  138         pcmio_bs_methods.bswm1 = pcmio_bswm1;
  139         pcmio_bs_methods.bsrr1 = pcmio_bsrr1;
  140         pcmio_bs_methods.bswr1 = pcmio_bswr1;
  141         pcmio_bs_methods.bssr1 = pcmio_bssr1;
  142         pcmio_bs_methods.bscr1 = pcmio_bscr1;
  143 
  144         reset_card_reg = (u_int8_t *) pcmcia_base +
  145             (GAYLE_PCMCIA_RESET - GAYLE_PCMCIA_START);
  146 
  147         sc->io_space.base = (bus_addr_t) pcmcia_base +
  148             (GAYLE_PCMCIA_IO_START - GAYLE_PCMCIA_START);
  149         sc->io_space.absm = &pcmio_bs_methods;
  150 
  151         sc->attr_space.base = (bus_addr_t) pcmcia_base +
  152             (GAYLE_PCMCIA_ATTR_START - GAYLE_PCMCIA_START);
  153         sc->attr_space.absm = &amiga_bus_stride_1;
  154 
  155         /* XXX we should check if the 4M of common memory are actually
  156          *      RAM or PCMCIA usable.
  157          * For now, we just do as if the 4M were RAM and make common memory
  158          * point to attribute memory, which is OK for some I/O cards.
  159          */
  160         sc->mem_space.base = (bus_addr_t) pcmcia_base;
  161         sc->mem_space.absm = &amiga_bus_stride_1;
  162 
  163         sc->devs[0].sc = sc;
  164         sc->devs[0].intr_func = NULL;
  165         sc->devs[0].intr_arg = NULL;
  166         sc->devs[0].flags = 0;
  167 
  168         gayle_pcmcia_status_write(0);
  169         gayle_intr_ack(0);
  170         gayle_pcmcia_config_write(0);
  171         gayle_intr_enable_set(GAYLE_INT_IDE);
  172 
  173         paa.paa_busname = "pcmcia";
  174         paa.pct = &chip_functions;
  175         paa.pch = &sc->devs[0];
  176         sc->devs[0].card = config_found(self, &paa, simple_devprint,
  177             CFARGS_NONE);
  178         if (sc->devs[0].card == NULL) {
  179                 printf("attach failed, config_found() returned NULL\n");
  180                 pmap_remove(kernel_map->pmap, pcmcia_base,
  181                     pcmcia_base + (GAYLE_PCMCIA_END - GAYLE_PCMCIA_START));
  182                 pmap_update(kernel_map->pmap);
  183                 uvm_deallocate(kernel_map, pcmcia_base,
  184                         GAYLE_PCMCIA_END - GAYLE_PCMCIA_START);
  185                 return;
  186         }
  187 
  188         sc->intr6.isr_intr = pccard_intr6;
  189         sc->intr6.isr_arg = sc;
  190         sc->intr6.isr_ipl = 6;
  191         add_isr(&sc->intr6);
  192 
  193         sc->intr2.isr_intr = pccard_intr2;
  194         sc->intr2.isr_arg = sc;
  195         sc->intr2.isr_ipl = 2;
  196         add_isr(&sc->intr2);
  197 
  198         if (kthread_create(PRI_NONE, 0, NULL, pccard_kthread, sc,
  199             NULL, "pccard")) {
  200                 printf("%s: can't create kernel thread\n",
  201                        device_xname(self));
  202                 panic("pccard kthread_create() failed");
  203         }
  204 
  205         gayle_intr_enable_set(GAYLE_INT_DETECT | GAYLE_INT_IREQ);
  206 
  207         /* reset the card if it's already there */
  208         if (gayle_pcmcia_status_read() & GAYLE_CCMEM_DETECT) {
  209                 volatile u_int8_t x;
  210 
  211                 gayle_intr_ack(0xff);
  212                 delay(500);
  213                 gayle_intr_ack(0xfc);
  214 
  215                 delay(100*1000);
  216 
  217                 *reset_card_reg = 0x0;
  218                 delay(1000);
  219                 x = *reset_card_reg;
  220                 __USE(x);
  221                 gayle_pcmcia_status_write(GAYLE_CCMEM_WP | GAYLE_CCIO_SPKR);
  222         }
  223 
  224         pccard_attach_slot(&sc->devs[0]);
  225 }
  226 
  227 static int
  228 pccard_intr6(void *arg)
  229 {
  230         struct pccard_softc *sc = arg;
  231 
  232         if (gayle_intr_status() & GAYLE_INT_DETECT) {
  233                 gayle_intr_ack(GAYLE_INT_IDE | GAYLE_INT_STSCHG |
  234                     GAYLE_INT_SPKR | GAYLE_INT_WP | GAYLE_INT_IREQ);
  235                 sc->devs[0].flags |= SLOT_NEW_CARD_EVENT;
  236                 return 1;
  237         }
  238         return 0;
  239 }
  240 
  241 static int
  242 pccard_intr2(void *arg)
  243 {
  244         struct pccard_softc *sc = arg;
  245         struct pccard_slot *slot = &sc->devs[0];
  246 
  247         if (slot->flags & SLOT_NEW_CARD_EVENT) {
  248                 slot->flags &= ~SLOT_NEW_CARD_EVENT;
  249 
  250                 /* reset the registers */
  251                 gayle_intr_ack(GAYLE_INT_IDE | GAYLE_INT_DETECT);
  252                 gayle_pcmcia_status_write(GAYLE_CCMEM_WP | GAYLE_CCIO_SPKR);
  253                 gayle_pcmcia_config_write(0);
  254                 pccard_attach_slot(&sc->devs[0]);
  255         } else {
  256                 int intreq = gayle_intr_status() &
  257                     (GAYLE_INT_STSCHG | GAYLE_INT_WP | GAYLE_INT_IREQ);
  258                 if (intreq) {
  259                         gayle_intr_ack((intreq ^ 0x2c) | 0xc0);
  260 
  261                         return slot->flags & SLOT_OCCUPIED &&
  262                                 slot->intr_func != NULL &&
  263                                 slot->intr_func(slot->intr_arg);
  264                 }
  265         }
  266         return 0;
  267 }
  268 
  269 static void
  270 pccard_kthread(void *arg)
  271 {
  272         struct pccard_softc *sc = arg;
  273         struct pccard_slot *slot = &sc->devs[0];
  274 
  275         for (;;) {
  276                 int s = spl2();
  277 
  278                 if (slot->flags & SLOT_NEW_CARD_EVENT) {
  279                         slot->flags &= ~SLOT_NEW_CARD_EVENT;
  280                         gayle_intr_ack(0xc0);
  281 
  282                         /* reset the registers */
  283                         gayle_intr_ack(GAYLE_INT_IDE | GAYLE_INT_DETECT);
  284                         gayle_pcmcia_status_write(GAYLE_CCMEM_WP | GAYLE_CCIO_SPKR);
  285                         gayle_pcmcia_config_write(0);
  286                         pccard_attach_slot(&sc->devs[0]);
  287                 }
  288                 splx(s);
  289 
  290                 tsleep(slot, PWAIT, "pccthread", hz);
  291         }
  292 }
  293 
  294 static void
  295 pccard_attach_slot(struct pccard_slot *slot)
  296 {
  297 
  298         if (!(slot->flags & SLOT_OCCUPIED) &&
  299                         gayle_pcmcia_status_read() & GAYLE_CCMEM_DETECT) {
  300                 if (pcmcia_card_attach(slot->card) == 0)
  301                         slot->flags |= SLOT_OCCUPIED;
  302         }
  303 }
  304 
  305 static int
  306 pcf_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t bsz,
  307               struct pcmcia_mem_handle *pcmh)
  308 {
  309         struct pccard_slot *slot = (struct pccard_slot *) pch;
  310 
  311         pcmh->memt = &slot->sc->attr_space;
  312         pcmh->memh = pcmh->memt->base;
  313         return 0;
  314 }
  315 
  316 static void
  317 pcf_mem_free(pcmcia_chipset_handle_t pch, struct pcmcia_mem_handle *memh)
  318 {
  319 }
  320 
  321 static int
  322 pcf_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr,
  323             bus_size_t size, struct pcmcia_mem_handle *pcmh,
  324             bus_addr_t *offsetp, int *windowp)
  325 {
  326         struct pccard_slot *slot = (struct pccard_slot *) pch;
  327 
  328         /* Ignore width requirements */
  329         kind &= ~PCMCIA_WIDTH_MEM_MASK;
  330 
  331         switch (kind) {
  332         case PCMCIA_MEM_ATTR:
  333                 pcmh->memt = &slot->sc->attr_space;
  334                 break;
  335         case PCMCIA_MEM_COMMON:
  336                 pcmh->memt = &slot->sc->mem_space;
  337                 break;
  338         default:
  339                 /* This means that this code needs an update/a bugfix */
  340                 printf(__FILE__ ": unknown kind %d of PCMCIA memory\n", kind);
  341                 return 1;
  342         }
  343 
  344         bus_space_map(pcmh->memt, addr, size, 0, &pcmh->memh);
  345         *offsetp = 0;
  346         *windowp = 0;                   /* unused */
  347 
  348         return 0;
  349 }
  350 
  351 static void
  352 pcf_mem_unmap(pcmcia_chipset_handle_t pch, int win)
  353 {
  354 }
  355 
  356 static int
  357 pcf_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, bus_size_t size,
  358              bus_size_t align, struct pcmcia_io_handle *pcihp)
  359 {
  360         struct pccard_slot *slot = (struct pccard_slot *) pch;
  361 
  362         pcihp->iot = &slot->sc->io_space;
  363         pcihp->ioh = pcihp->iot->base;
  364         return 0;
  365 }
  366 
  367 static void
  368 pcf_io_free(pcmcia_chipset_handle_t pch, struct pcmcia_io_handle *pcihp)
  369 {
  370 }
  371 
  372 static int
  373 pcf_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
  374            bus_size_t size, struct pcmcia_io_handle *pcihp, int *windowp)
  375 {
  376         struct pccard_slot *slot = (struct pccard_slot *) pch;
  377 
  378         pcihp->iot = &slot->sc->io_space;
  379         bus_space_map(pcihp->iot, offset, size, 0, &pcihp->ioh);
  380 
  381         *windowp = 0;           /* unused */
  382         return 0;
  383 }
  384 
  385 static void
  386 pcf_io_unmap(pcmcia_chipset_handle_t pch, int win)
  387 {
  388 }
  389 
  390 static void *
  391 pcf_intr_establish(pcmcia_chipset_handle_t pch, struct pcmcia_function *pf,
  392                    int ipl, int (*func)(void *), void *arg)
  393 {
  394         struct pccard_slot *slot = (struct pccard_slot *) pch;
  395         int s;
  396 
  397         s = splhigh();
  398         if (slot->intr_func == NULL) {
  399                 slot->intr_func = func;
  400                 slot->intr_arg = arg;
  401         } else {
  402                 /* if we are here, we need to put intrs into a list */
  403                 printf("ARGH! see " __FILE__ "\n");
  404                 slot = NULL;
  405         }
  406         splx(s);
  407 
  408         return slot;
  409 }
  410 
  411 static void
  412 pcf_intr_disestablish(pcmcia_chipset_handle_t pch, void *intr_handler)
  413 {
  414         struct pccard_slot *slot = (struct pccard_slot *) intr_handler;
  415 
  416         if (slot != NULL) {
  417                 slot->intr_func = NULL;
  418                 slot->intr_arg = NULL;
  419         }
  420 }
  421 
  422 static void
  423 pcf_socket_enable(pcmcia_chipset_handle_t pch)
  424 {
  425 }
  426 
  427 static void
  428 pcf_socket_disable(pcmcia_chipset_handle_t pch)
  429 {
  430 }
  431 
  432 static void
  433 pcf_socket_settype(pcmcia_chipset_handle_t pch, int type) {
  434 }
  435 
  436 static u_int8_t
  437 pcmio_bsr1(bus_space_handle_t h, bus_size_t o)
  438 {
  439 
  440         return *((volatile u_int8_t *) h + o + (o & 1 ? 0xffff : 0));
  441 }
  442 
  443 static void
  444 pcmio_bsw1(bus_space_handle_t h, bus_size_t o, unsigned v)
  445 {
  446 
  447         *((volatile u_int8_t *) h + o + (o & 1 ? 0xffff : 0)) = v;
  448 }
  449 
  450 static void
  451 pcmio_bsrm1(bus_space_handle_t h, bus_size_t o, u_int8_t *p, bus_size_t c)
  452 {
  453         volatile u_int8_t *src = (volatile u_int8_t *)
  454                 (h + o + (o & 1 ? 0xffff : 0));
  455 
  456 
  457         /* XXX we can (should, must) optimize this if c >= 4 */
  458         for (; c > 0; c--)
  459                 *p++ = *src;
  460 }
  461 
  462 
  463 static void
  464 pcmio_bswm1(bus_space_handle_t h, bus_size_t o, const u_int8_t *p, bus_size_t c)
  465 {
  466         volatile u_int8_t *dst = (volatile u_int8_t *)
  467                 (h + o + (o & 1 ? 0xffff : 0));
  468 
  469 
  470         /* XXX we can (should, must) optimize this if c >= 4 */
  471         for (; c > 0; c--)
  472                 *dst = *p++;
  473 }
  474 
  475 static void
  476 pcmio_bsrr1(bus_space_handle_t h, bus_size_t o, u_int8_t *p, bus_size_t c)
  477 {
  478         volatile u_int8_t *cp1;
  479         volatile u_int8_t *cp2;
  480         volatile u_int8_t *temp;
  481 
  482         if (o & 1) {
  483                 cp1 = (volatile u_int8_t *) h + o + 0x10000;
  484                 cp2 = (volatile u_int8_t *) h + o;
  485         } else {
  486                 cp1 = (volatile u_int8_t *) h + o;
  487                 cp2 = (volatile u_int8_t *) h + o + 0x10000 + 2;
  488         }
  489 
  490         /* XXX we can (should, must) optimize this if c >= 4 */
  491         for (; c > 0; c--) {
  492                 *p++ = *cp1;
  493                 cp1 += 2;
  494 
  495                 /* swap pointers - hope gcc generates exg for this ;) */
  496                 temp = cp1;
  497                 cp1 = cp2;
  498                 cp2 = temp;
  499         }
  500 }
  501 
  502 
  503 static void
  504 pcmio_bswr1(bus_space_handle_t h, bus_size_t o, const u_int8_t *p, bus_size_t c)
  505 {
  506         volatile u_int8_t *cp1;
  507         volatile u_int8_t *cp2;
  508         volatile u_int8_t *temp;
  509 
  510         if (o & 1) {
  511                 cp1 = (volatile u_int8_t *) h + o + 0x10000;
  512                 cp2 = (volatile u_int8_t *) h + o;
  513         } else {
  514                 cp1 = (volatile u_int8_t *) h + o;
  515                 cp2 = (volatile u_int8_t *) h + o + 0x10000 + 2;
  516         }
  517 
  518         /* XXX we can (should, must) optimize this if c >= 4 */
  519         for (; c > 0; c--) {
  520                 *cp1 = *p++;
  521                 cp1 += 2;
  522 
  523                 /* swap pointers - hope gcc generates exg for this ;) */
  524                 temp = cp1;
  525                 cp1 = cp2;
  526                 cp2 = temp;
  527         }
  528 }
  529 
  530 void
  531 pcmio_bssr1(bus_space_handle_t h, bus_size_t o, unsigned v, bus_size_t c)
  532 {
  533 
  534         panic("pcmio_bssr1 is not defined (" __FILE__ ")");
  535 }
  536 
  537 void
  538 pcmio_bscr1(bus_space_handle_t h, bus_size_t o, bus_space_handle_t g,
  539             bus_size_t q, bus_size_t c)
  540 {
  541 
  542         panic("pcmio_bscr1 is not defined (" __FILE__ ")");
  543 }

Cache object: e8509657876b3fd8459ae293e853167a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.