root/dev/pcmcia/esp_pcmcia.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. esp_pcmcia_match
  2. esp_pcmcia_attach
  3. esp_pcmcia_init
  4. esp_pcmcia_detach
  5. esp_pcmcia_enable
  6. esp_pcmcia_poll
  7. esp_pcmcia_read_reg
  8. esp_pcmcia_write_reg
  9. esp_pcmcia_dma_isintr
  10. esp_pcmcia_dma_reset
  11. esp_pcmcia_dma_intr
  12. esp_pcmcia_dma_setup
  13. esp_pcmcia_dma_go
  14. esp_pcmcia_dma_stop
  15. esp_pcmcia_dma_isactive

    1 /*      $OpenBSD: esp_pcmcia.c,v 1.6 2006/04/20 20:30:28 miod Exp $     */
    2 /*      $NetBSD: esp_pcmcia.c,v 1.8 2000/06/05 15:36:45 tsutsui Exp $   */
    3 
    4 /*-
    5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Charles M. Hannum.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/device.h>
   43 #include <sys/buf.h>
   44 
   45 #include <machine/bus.h>
   46 #include <machine/intr.h>
   47 
   48 #include <scsi/scsi_all.h>
   49 #include <scsi/scsiconf.h>
   50 
   51 #include <dev/pcmcia/pcmciareg.h>
   52 #include <dev/pcmcia/pcmciavar.h>
   53 #include <dev/pcmcia/pcmciadevs.h>
   54 
   55 #include <dev/ic/ncr53c9xreg.h>
   56 #include <dev/ic/ncr53c9xvar.h>
   57 
   58 struct esp_pcmcia_softc {
   59         struct ncr53c9x_softc   sc_ncr53c9x;    /* glue to MI code */
   60 
   61         int             sc_active;              /* Pseudo-DMA state vars */
   62         int             sc_tc;
   63         int             sc_datain;
   64         size_t          sc_dmasize;
   65         size_t          sc_dmatrans;
   66         char            **sc_dmaaddr;
   67         size_t          *sc_pdmalen;
   68 
   69         /* PCMCIA-specific goo. */
   70         struct pcmcia_io_handle sc_pcioh;       /* PCMCIA i/o space info */
   71         int sc_io_window;                       /* our i/o window */
   72         struct pcmcia_function *sc_pf;          /* our PCMCIA function */
   73         void *sc_ih;                            /* interrupt handler */
   74 #ifdef ESP_PCMCIA_POLL
   75         struct callout sc_poll_ch;
   76 #endif
   77         int sc_flags;
   78 #define ESP_PCMCIA_ATTACHED     1               /* attach completed */
   79 #define ESP_PCMCIA_ATTACHING    2               /* attach in progress */
   80 };
   81 
   82 int     esp_pcmcia_match(struct device *, void *, void *); 
   83 void    esp_pcmcia_attach(struct device *, struct device *, void *);  
   84 void    esp_pcmcia_init(struct esp_pcmcia_softc *);
   85 int     esp_pcmcia_detach(struct device *, int);
   86 int     esp_pcmcia_enable(void *, int);
   87 
   88 struct scsi_adapter esp_pcmcia_adapter = {
   89         ncr53c9x_scsi_cmd,      /* cmd */
   90         minphys,                /* minphys */
   91         0,                      /* open */
   92         0,                      /* close */
   93 };
   94 
   95 struct cfattach esp_pcmcia_ca = {
   96         sizeof(struct esp_pcmcia_softc), esp_pcmcia_match, esp_pcmcia_attach
   97 };
   98 
   99 /*
  100  * Functions and the switch for the MI code.
  101  */
  102 #ifdef ESP_PCMCIA_POLL
  103 void    esp_pcmcia_poll(void *);
  104 #endif
  105 u_char  esp_pcmcia_read_reg(struct ncr53c9x_softc *, int);
  106 void    esp_pcmcia_write_reg(struct ncr53c9x_softc *, int, u_char);
  107 int     esp_pcmcia_dma_isintr(struct ncr53c9x_softc *);
  108 void    esp_pcmcia_dma_reset(struct ncr53c9x_softc *);
  109 int     esp_pcmcia_dma_intr(struct ncr53c9x_softc *);
  110 int     esp_pcmcia_dma_setup(struct ncr53c9x_softc *, caddr_t *,
  111             size_t *, int, size_t *);
  112 void    esp_pcmcia_dma_go(struct ncr53c9x_softc *);
  113 void    esp_pcmcia_dma_stop(struct ncr53c9x_softc *);
  114 int     esp_pcmcia_dma_isactive(struct ncr53c9x_softc *);
  115 
  116 struct ncr53c9x_glue esp_pcmcia_glue = {
  117         esp_pcmcia_read_reg,
  118         esp_pcmcia_write_reg,
  119         esp_pcmcia_dma_isintr,
  120         esp_pcmcia_dma_reset,
  121         esp_pcmcia_dma_intr,
  122         esp_pcmcia_dma_setup,
  123         esp_pcmcia_dma_go,
  124         esp_pcmcia_dma_stop,
  125         esp_pcmcia_dma_isactive,
  126         NULL,                   /* gl_clear_latched_intr */
  127 };
  128 
  129 struct esp_pcmcia_product {
  130         u_int16_t       app_vendor;             /* PCMCIA vendor ID */
  131         u_int16_t       app_product;            /* PCMCIA product ID */
  132         int             app_expfunc;            /* expected function number */
  133 } esp_pcmcia_prod[] = {
  134         { PCMCIA_VENDOR_PANASONIC, PCMCIA_PRODUCT_PANASONIC_KXLC002, 0 },
  135         { PCMCIA_VENDOR_PANASONIC, PCMCIA_PRODUCT_PANASONIC_KME, 0 },
  136         { PCMCIA_VENDOR_NEWMEDIA2, PCMCIA_PRODUCT_NEWMEDIA2_BUSTOASTER, 0 }
  137 };
  138 
  139 int
  140 esp_pcmcia_match(parent, match, aux)
  141         struct device *parent;
  142         void *match, *aux;
  143 {
  144         struct pcmcia_attach_args *pa = aux;
  145         int i;
  146 
  147         for (i = 0; i < sizeof(esp_pcmcia_prod)/sizeof(esp_pcmcia_prod[0]); i++)
  148                 if (pa->manufacturer == esp_pcmcia_prod[i].app_vendor &&
  149                     pa->product == esp_pcmcia_prod[i].app_product &&
  150                     pa->pf->number == esp_pcmcia_prod[i].app_expfunc)
  151                         return (1);
  152         return (0);
  153 }
  154 
  155 void
  156 esp_pcmcia_attach(parent, self, aux)
  157         struct device *parent, *self;
  158         void *aux;
  159 {
  160         struct esp_pcmcia_softc *esc = (void *)self;
  161         struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
  162         struct pcmcia_attach_args *pa = aux;
  163         struct pcmcia_config_entry *cfe;
  164         struct pcmcia_function *pf = pa->pf;
  165         const char *intrstr;
  166 
  167         esc->sc_pf = pf;
  168 
  169         for (cfe = SIMPLEQ_FIRST(&pf->cfe_head); cfe != NULL;
  170             cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
  171                 if (cfe->num_memspace != 0 ||
  172                     cfe->num_iospace != 1)
  173                         continue;
  174 
  175                 if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
  176                     cfe->iospace[0].length, 0, &esc->sc_pcioh) == 0)
  177                         break;
  178         }
  179 
  180         if (cfe == 0) {
  181                 printf(": can't alloc i/o space\n");
  182                 goto no_config_entry;
  183         }
  184 
  185         /* Enable the card. */
  186         pcmcia_function_init(pf, cfe);
  187         if (pcmcia_function_enable(pf)) {
  188                 printf(": function enable failed\n");
  189                 goto enable_failed;
  190         }
  191 
  192         /* Map in the I/O space */
  193         if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_AUTO, 0, esc->sc_pcioh.size,
  194             &esc->sc_pcioh, &esc->sc_io_window)) {
  195                 printf(": can't map i/o space\n");
  196                 goto iomap_failed;
  197         }
  198 
  199         printf(" port 0x%lx/%lu", esc->sc_pcioh.addr,
  200             (u_long)esc->sc_pcioh.size);
  201 
  202         esp_pcmcia_init(esc);
  203 
  204         esc->sc_ih = pcmcia_intr_establish(esc->sc_pf, IPL_BIO,
  205             ncr53c9x_intr, &esc->sc_ncr53c9x, sc->sc_dev.dv_xname);
  206         intrstr = pcmcia_intr_string(esc->sc_pf, esc->sc_ih);
  207         if (esc->sc_ih == NULL) {
  208                 printf(", %s\n", intrstr);
  209                 goto iomap_failed;
  210         }
  211         if (*intrstr)
  212                 printf(", %s", intrstr);
  213 
  214         /*
  215          *  Initialize nca board itself.
  216          */
  217         esc->sc_flags |= ESP_PCMCIA_ATTACHING;
  218         ncr53c9x_attach(sc, &esp_pcmcia_adapter, NULL);
  219         esc->sc_flags &= ~ESP_PCMCIA_ATTACHING;
  220         esc->sc_flags |= ESP_PCMCIA_ATTACHED;
  221         return;
  222 
  223 iomap_failed:
  224         /* Disable the device. */
  225         pcmcia_function_disable(esc->sc_pf);
  226 
  227 enable_failed:
  228         /* Unmap our I/O space. */
  229         pcmcia_io_free(esc->sc_pf, &esc->sc_pcioh);
  230 
  231 no_config_entry:
  232         return;
  233 }
  234 
  235 void
  236 esp_pcmcia_init(esc)
  237         struct esp_pcmcia_softc *esc;
  238 {
  239         struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
  240         bus_space_tag_t iot = esc->sc_pcioh.iot;
  241         bus_space_handle_t ioh = esc->sc_pcioh.ioh;
  242 
  243         /* id 7, clock 40M, parity ON, sync OFF, fast ON, slow ON */
  244 
  245         sc->sc_glue = &esp_pcmcia_glue;
  246 
  247 #ifdef ESP_PCMCIA_POLL
  248         callout_init(&esc->sc_poll_ch);
  249 #endif
  250 
  251         sc->sc_rev = NCR_VARIANT_ESP406;
  252         sc->sc_id = 7;
  253         sc->sc_freq = 40;
  254         /* try -PARENB -SLOW */
  255         sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB | NCRCFG1_SLOW;
  256         /* try +FE */
  257         sc->sc_cfg2 = NCRCFG2_SCSI2;
  258         /* try -IDM -FSCSI -FCLK */
  259         sc->sc_cfg3 = NCRESPCFG3_CDB | NCRESPCFG3_FCLK | NCRESPCFG3_IDM |
  260             NCRESPCFG3_FSCSI;
  261         sc->sc_cfg4 = NCRCFG4_ACTNEG;
  262         /* try +INTP */
  263         sc->sc_cfg5 = NCRCFG5_CRS1 | NCRCFG5_AADDR | NCRCFG5_PTRINC;
  264         sc->sc_minsync = 0;
  265         sc->sc_maxxfer = 64 * 1024;
  266 
  267         bus_space_write_1(iot, ioh, NCR_CFG5, sc->sc_cfg5);
  268 
  269         bus_space_write_1(iot, ioh, NCR_PIOI, 0);
  270         bus_space_write_1(iot, ioh, NCR_PSTAT, 0);
  271         bus_space_write_1(iot, ioh, 0x09, 0x24);
  272 
  273         bus_space_write_1(iot, ioh, NCR_CFG4, sc->sc_cfg4);
  274 }
  275 
  276 #ifdef notyet
  277 int
  278 esp_pcmcia_detach(self, flags)
  279         struct device *self;
  280         int flags;
  281 {
  282         struct esp_pcmcia_softc *esc = (void *)self;
  283         int error;
  284 
  285         if ((esc->sc_flags & ESP_PCMCIA_ATTACHED) == 0) {
  286                 /* Nothing to detach. */
  287                 return (0);
  288         }
  289 
  290         error = ncr53c9x_detach(&esc->sc_ncr53c9x, flags);
  291         if (error)
  292                 return (error);
  293 
  294         /* Unmap our i/o window and i/o space. */
  295         pcmcia_io_unmap(esc->sc_pf, esc->sc_io_window);
  296         pcmcia_io_free(esc->sc_pf, &esc->sc_pcioh);
  297 
  298         return (0);
  299 }
  300 #endif
  301 
  302 int
  303 esp_pcmcia_enable(arg, onoff)
  304         void *arg;
  305         int onoff;
  306 {
  307         struct esp_pcmcia_softc *esc = arg;
  308 
  309         if (onoff) {
  310 #ifdef ESP_PCMCIA_POLL
  311                 callout_reset(&esc->sc_poll_ch, 1, esp_pcmcia_poll, esc);
  312 #else
  313                 /* Establish the interrupt handler. */
  314                 esc->sc_ih = pcmcia_intr_establish(esc->sc_pf, IPL_BIO,
  315                     ncr53c9x_intr, &esc->sc_ncr53c9x,
  316                     esc->sc_ncr53c9x.sc_dev.dv_xname);
  317                 if (esc->sc_ih == NULL) {
  318                         printf("%s: couldn't establish interrupt handler\n",
  319                             esc->sc_ncr53c9x.sc_dev.dv_xname);
  320                         return (EIO);
  321                 }
  322 #endif
  323 
  324                 /*
  325                  * If attach is in progress, we know that card power is
  326                  * enabled and chip will be initialized later.
  327                  * Otherwise, enable and reset now.
  328                  */
  329                 if ((esc->sc_flags & ESP_PCMCIA_ATTACHING) == 0) {
  330                         if (pcmcia_function_enable(esc->sc_pf)) {
  331                                 printf("%s: couldn't enable PCMCIA function\n",
  332                                     esc->sc_ncr53c9x.sc_dev.dv_xname);
  333                                 pcmcia_intr_disestablish(esc->sc_pf,
  334                                     esc->sc_ih);
  335                                 return (EIO);
  336                         }
  337 
  338                         /* Initialize only chip.  */
  339                         ncr53c9x_init(&esc->sc_ncr53c9x, 0);
  340                 }
  341         } else {
  342                 pcmcia_function_disable(esc->sc_pf);
  343 #ifdef ESP_PCMCIA_POLL
  344                 callout_stop(&esc->sc_poll_ch);
  345 #else
  346                 pcmcia_intr_disestablish(esc->sc_pf, esc->sc_ih);
  347 #endif
  348         }
  349 
  350         return (0);
  351 }
  352 
  353 #ifdef ESP_PCMCIA_POLL
  354 void
  355 esp_pcmcia_poll(arg)
  356         void *arg;
  357 {
  358         struct esp_pcmcia_softc *esc = arg;
  359 
  360         (void) ncr53c9x_intr(&esc->sc_ncr53c9x);
  361         callout_reset(&esc->sc_poll_ch, 1, esp_pcmcia_poll, esc);
  362 }
  363 #endif
  364 
  365 /*
  366  * Glue functions.
  367  */
  368 u_char
  369 esp_pcmcia_read_reg(sc, reg)
  370         struct ncr53c9x_softc *sc;
  371         int reg;
  372 {
  373         struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
  374         u_char v;
  375 
  376         v = bus_space_read_1(esc->sc_pcioh.iot, esc->sc_pcioh.ioh, reg);
  377         return v;
  378 }
  379 
  380 void
  381 esp_pcmcia_write_reg(sc, reg, val)
  382         struct ncr53c9x_softc *sc;
  383         int reg;
  384         u_char val;
  385 {
  386         struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
  387         u_char v = val;
  388 
  389         if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA))
  390                 v = NCRCMD_TRANS;
  391         bus_space_write_1(esc->sc_pcioh.iot, esc->sc_pcioh.ioh, reg, v);
  392 }
  393 
  394 int
  395 esp_pcmcia_dma_isintr(sc)
  396         struct ncr53c9x_softc *sc;
  397 {
  398 
  399         return NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT;
  400 }
  401 
  402 void
  403 esp_pcmcia_dma_reset(sc)
  404         struct ncr53c9x_softc *sc;
  405 {
  406         struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
  407 
  408         esc->sc_active = 0;
  409         esc->sc_tc = 0;
  410 }
  411 
  412 int
  413 esp_pcmcia_dma_intr(sc)
  414         struct ncr53c9x_softc *sc;
  415 {
  416         struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
  417         u_char  *p;
  418         u_int   espphase, espstat, espintr;
  419         int     cnt;
  420 
  421         if (esc->sc_active == 0) {
  422                 printf("%s: dma_intr--inactive DMA\n", sc->sc_dev.dv_xname);
  423                 return -1;
  424         }
  425 
  426         if ((sc->sc_espintr & NCRINTR_BS) == 0) {
  427                 esc->sc_active = 0;
  428                 return 0;
  429         }
  430 
  431         cnt = *esc->sc_pdmalen;
  432         if (*esc->sc_pdmalen == 0) {
  433                 printf("%s: data interrupt, but no count left\n",
  434                     sc->sc_dev.dv_xname);
  435         }
  436 
  437         p = *esc->sc_dmaaddr;
  438         espphase = sc->sc_phase;
  439         espstat = (u_int) sc->sc_espstat;
  440         espintr = (u_int) sc->sc_espintr;
  441         do {
  442                 if (esc->sc_datain) {
  443                         *p++ = NCR_READ_REG(sc, NCR_FIFO);
  444                         cnt--;
  445                         if (espphase == DATA_IN_PHASE)
  446                                 NCR_WRITE_REG(sc, NCR_CMD, NCRCMD_TRANS);
  447                         else
  448                                 esc->sc_active = 0;
  449                 } else {
  450                         if (espphase == DATA_OUT_PHASE ||
  451                             espphase == MESSAGE_OUT_PHASE) {
  452                                 NCR_WRITE_REG(sc, NCR_FIFO, *p++);
  453                                 cnt--;
  454                                 NCR_WRITE_REG(sc, NCR_CMD, NCRCMD_TRANS);
  455                         } else
  456                                 esc->sc_active = 0;
  457                 }
  458 
  459                 if (esc->sc_active) {
  460                         while (!(NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT));
  461                         espstat = NCR_READ_REG(sc, NCR_STAT);
  462                         espintr = NCR_READ_REG(sc, NCR_INTR);
  463                         espphase = (espintr & NCRINTR_DIS)
  464                                     ? /* Disconnected */ BUSFREE_PHASE
  465                                     : espstat & PHASE_MASK;
  466                 }
  467         } while (esc->sc_active && espintr);
  468         sc->sc_phase = espphase;
  469         sc->sc_espstat = (u_char) espstat;
  470         sc->sc_espintr = (u_char) espintr;
  471         *esc->sc_dmaaddr = p;
  472         *esc->sc_pdmalen = cnt;
  473 
  474         if (*esc->sc_pdmalen == 0)
  475                 esc->sc_tc = NCRSTAT_TC;
  476         sc->sc_espstat |= esc->sc_tc;
  477         return 0;
  478 }
  479 
  480 int
  481 esp_pcmcia_dma_setup(sc, addr, len, datain, dmasize)
  482         struct ncr53c9x_softc *sc;
  483         caddr_t *addr;
  484         size_t *len;
  485         int datain;
  486         size_t *dmasize;
  487 {
  488         struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
  489 
  490         esc->sc_dmaaddr = addr;
  491         esc->sc_pdmalen = len;
  492         esc->sc_datain = datain;
  493         esc->sc_dmasize = *dmasize;
  494         esc->sc_tc = 0;
  495 
  496         return 0;
  497 }
  498 
  499 void
  500 esp_pcmcia_dma_go(sc)
  501         struct ncr53c9x_softc *sc;
  502 {
  503         struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
  504 
  505         esc->sc_active = 1;
  506 }
  507 
  508 void
  509 esp_pcmcia_dma_stop(sc)
  510         struct ncr53c9x_softc *sc;
  511 {
  512 }
  513 
  514 int
  515 esp_pcmcia_dma_isactive(sc)
  516         struct ncr53c9x_softc *sc;
  517 {
  518         struct esp_pcmcia_softc *esc = (struct esp_pcmcia_softc *)sc;
  519 
  520         return (esc->sc_active);
  521 }

/* [<][>][^][v][top][bottom][index][help] */