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/dev/pci/if_ntwoc_pci.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: if_ntwoc_pci.c,v 1.13 2003/11/02 10:31:06 wiz Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1998 Vixie Enterprises
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  *
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of Vixie Enterprises nor the names
   17  *    of its contributors may be used to endorse or promote products derived
   18  *    from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY VIXIE ENTERPRISES AND
   21  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   22  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   23  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   24  * DISCLAIMED.  IN NO EVENT SHALL VIXIE ENTERPRISES OR
   25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * This software has been written for Vixie Enterprises by Michael Graff
   35  * <explorer@flame.org>.  To learn more about Vixie Enterprises, see
   36  * ``http://www.vix.com''.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: if_ntwoc_pci.c,v 1.13 2003/11/02 10:31:06 wiz Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/device.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/socket.h>
   47 
   48 #include <net/if.h>
   49 
   50 #include <machine/cpu.h>
   51 #include <machine/bus.h>
   52 #include <machine/intr.h>
   53 
   54 #include <dev/pci/pcivar.h>
   55 #include <dev/pci/pcireg.h>
   56 #include <dev/pci/pcidevs.h>
   57 
   58 #include <dev/ic/hd64570reg.h>
   59 #include <dev/ic/hd64570var.h>
   60 
   61 #include <dev/pci/if_ntwoc_pcireg.h>
   62 
   63 #if 0
   64 #define NTWO_DEBUG
   65 #endif
   66 
   67 #ifdef NTWO_DEBUG
   68 #define NTWO_DPRINTF(x) printf x
   69 #else
   70 #define NTWO_DPRINTF(x)
   71 #endif
   72 
   73 /*
   74  * buffers per tx and rx channels, per port, and the size of each.
   75  * Don't use these constants directly, as they are really only hints.
   76  * Use the calculated values stored in struct sca_softc instead.
   77  *
   78  * Each must be at least 2, receive would be better at around 20 or so.
   79  *
   80  * XXX Due to a damned near impossible to track down bug, transmit buffers
   81  * MUST be 2, no more, no less.
   82  */
   83 #ifndef NTWOC_NtxBUFS
   84 #define NTWOC_NtxBUFS     40
   85 #endif
   86 #ifndef NTWOC_NrxBUFS
   87 #define NTWOC_NrxBUFS     20
   88 #endif
   89 
   90 #if __NetBSD_Version__ >= 104160000
   91 static  void ntwoc_pci_config_interrupts __P((struct device *));
   92 #else
   93 #define SCA_BASECLOCK   16000000
   94 #endif
   95 
   96 /*
   97  * Card specific config register location
   98  */
   99 #define PCI_CBMA_ASIC   0x10    /* Configuration Base Memory Address */
  100 #define PCI_CBMA_SCA    0x18
  101 
  102 struct ntwoc_pci_softc {
  103         /* Generic device stuff */
  104         struct device sc_dev;           /* Common to all devices */
  105 
  106         /* PCI chipset glue */
  107         pci_intr_handle_t *sc_ih;       /* Interrupt handler */
  108         pci_chipset_tag_t sc_sr;        /* PCI chipset handle */
  109 
  110         bus_space_tag_t sc_asic_iot;    /* space cookie (for ASIC) */
  111         bus_space_handle_t sc_asic_ioh; /* bus space handle (for ASIC) */
  112 
  113         struct sca_softc sc_sca;        /* the SCA itself */
  114 };
  115 
  116 static  int ntwoc_pci_match __P((struct device *, struct cfdata *, void *));
  117 static  void ntwoc_pci_attach __P((struct device *, struct device *, void *));
  118 
  119 static  int ntwoc_pci_alloc_dma __P((struct sca_softc *));
  120 static  void ntwoc_pci_clock_callback __P((void *, int, int));
  121 static  void ntwoc_pci_dtr_callback __P((void *, int, int));
  122 static  void ntwoc_pci_get_clock __P((struct sca_port *, u_int8_t, u_int8_t,
  123     u_int8_t, u_int8_t));
  124 static  int ntwoc_pci_intr __P((void *));
  125 static  void ntwoc_pci_setup_dma __P((struct sca_softc *));
  126 static  void ntwoc_pci_shutdown __P((void *sc));
  127 
  128 CFATTACH_DECL(ntwoc_pci, sizeof(struct ntwoc_pci_softc),
  129     ntwoc_pci_match, ntwoc_pci_attach, NULL, NULL);
  130 
  131 /*
  132  * Names for daughter card types.  These match the NTWOC_DB_* defines.
  133  */
  134 char *ntwoc_pci_db_names[] = {
  135         "V.35", "Unknown 0x01", "Test", "Unknown 0x03",
  136         "RS232", "Unknown 0x05", "RS422", "None"
  137 };
  138 
  139 /*
  140  * At least one implementation uses a somewhat strange register address
  141  * mapping.  If a card doesn't, define this to be a pass-through
  142  * macro.  (The ntwo driver needs this...)
  143  */
  144 #define SCA_REG(y)  (((y) & 0x0002) ? (((y) & 0x00fd) + 0x100) : (y))
  145 
  146 /*
  147  * functions that read and write to the sca registers
  148  */
  149 static void
  150 ntwoc_pci_sca_write_1(struct sca_softc *sc, u_int reg, u_int8_t val)
  151 {
  152         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SCA_REG(reg), val);
  153 }
  154 
  155 static void
  156 ntwoc_pci_sca_write_2(struct sca_softc *sc, u_int reg, u_int16_t val)
  157 {
  158         bus_space_write_2(sc->sc_iot, sc->sc_ioh, SCA_REG(reg), val);
  159 }
  160 
  161 static u_int8_t
  162 ntwoc_pci_sca_read_1(struct sca_softc *sc, u_int reg)
  163 {
  164         return
  165             bus_space_read_1(sc->sc_iot, sc->sc_ioh, SCA_REG(reg));
  166 }
  167 
  168 static u_int16_t
  169 ntwoc_pci_sca_read_2(struct sca_softc *sc, u_int reg)
  170 {
  171         return
  172             bus_space_read_2(sc->sc_iot, sc->sc_ioh, SCA_REG(reg));
  173 }
  174 
  175 
  176 
  177 static int
  178 ntwoc_pci_match(struct device *parent, struct cfdata *match, void *aux)
  179 {
  180         struct pci_attach_args *pa = (struct pci_attach_args *)aux;
  181 
  182         if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RISCOM)
  183             && (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RISCOM_N2))
  184                 return 1;
  185 
  186         return 0;
  187 }
  188 
  189 static void
  190 ntwoc_pci_attach(struct device *parent, struct device *self, void *aux)
  191 {
  192         struct ntwoc_pci_softc *sc = (void *)self;
  193         struct pci_attach_args *pa = aux;
  194         struct sca_softc *sca = &sc->sc_sca;
  195         pci_intr_handle_t ih;
  196         const char *intrstr;
  197         pcireg_t csr;
  198         u_int8_t tmc, rdiv, tdiv;
  199         u_int16_t frontend_cr;
  200         u_int16_t db0, db1;
  201         u_int32_t flags;
  202         u_int numports;
  203 
  204         printf(": N2 Serial Interface\n");
  205         flags = sc->sc_dev.dv_cfdata->cf_flags;
  206 
  207         /*
  208          * Map in the ASIC configuration space
  209          */
  210         if (pci_mapreg_map(pa, PCI_CBMA_ASIC, PCI_MAPREG_TYPE_MEM, 0,
  211                            &sc->sc_asic_iot, &sc->sc_asic_ioh, NULL, NULL)) {
  212                 printf("%s: Can't map register space (ASIC)\n",
  213                        sc->sc_dev.dv_xname);
  214                 return;
  215         }
  216         /*
  217          * Map in the serial controller configuration space
  218          */
  219         if (pci_mapreg_map(pa, PCI_CBMA_SCA, PCI_MAPREG_TYPE_MEM, 0,
  220                            &sca->sc_iot, &sca->sc_ioh, NULL, NULL)) {
  221                 printf("%s: Can't map register space (SCA)\n",
  222                        sc->sc_dev.dv_xname);
  223                 return;
  224         }
  225 
  226         /*
  227          * Enable the card
  228          */
  229         csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
  230         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr);
  231 
  232         /*
  233          * Map and establish the interrupt
  234          */
  235         if (pci_intr_map(pa, &ih)) {
  236                 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
  237                 return;
  238         }
  239         intrstr = pci_intr_string(pa->pa_pc, ih);
  240         sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, ntwoc_pci_intr,
  241             sc);
  242         if (sc->sc_ih == NULL) {
  243                 printf("%s: couldn't establish interrupt",
  244                        sc->sc_dev.dv_xname);
  245                 if (intrstr != NULL)
  246                         printf(" at %s", intrstr);
  247                 printf("\n");
  248                 return;
  249         }
  250         printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
  251 
  252         /*
  253          * Perform total black magic.  This is not only extremely
  254          * disgusting, but it should be explained a lot more in the
  255          * card's documentation.
  256          *
  257          * From what I gather, this does nothing more than configure the
  258          * PCI to ISA translator ASIC the N2pci card uses.
  259          *
  260          * From the FreeBSD driver:
  261          * offset
  262          *  0x00 - Map Range    - Mem-mapped to locate anywhere
  263          *  0x04 - Re-Map       - PCI address decode enable
  264          *  0x18 - Bus Region   - 32-bit bus, ready enable
  265          *  0x1c - Master Range - include all 16 MB
  266          *  0x20 - Master RAM   - Map SCA Base at 0
  267          *  0x28 - Master Remap - direct master memory enable
  268          *  0x68 - Interrupt    - Enable interrupt (0 to disable)
  269          */
  270         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  271                           0x00, 0xfffff000);
  272         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  273                           0x04, 1);
  274         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  275                           0x18, 0x40030043);
  276         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  277                           0x1c, 0xff000000);
  278         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  279                           0x20, 0);
  280         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  281                           0x28, 0xe9);
  282         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  283                           0x68, 0x10900);
  284 
  285         /*
  286          * pass the DMA tag to the SCA
  287          */
  288         sca->sc_usedma = 1;
  289         sca->scu_dmat = pa->pa_dmat;
  290 
  291         /*
  292          * Read the configuration information off the daughter card.
  293          */
  294         frontend_cr = bus_space_read_2(sca->sc_iot, sca->sc_ioh, NTWOC_FECR);
  295         NTWO_DPRINTF(("%s: frontend_cr = 0x%04x\n",
  296                       sc->sc_dev.dv_xname, frontend_cr));
  297 
  298         db0 = (frontend_cr & NTWOC_FECR_ID0) >> NTWOC_FECR_ID0_SHIFT;
  299         db1 = (frontend_cr & NTWOC_FECR_ID1) >> NTWOC_FECR_ID1_SHIFT;
  300 
  301         /*
  302          * Port 1 HAS to be present.  If it isn't, don't attach anything.
  303          */
  304         if (db0 == NTWOC_FE_ID_NONE) {
  305                 printf("%s: no ports available\n", sc->sc_dev.dv_xname);
  306                 return;
  307         }
  308 
  309         /*
  310          * Port 1 is present.  Now, check to see if port 2 is also
  311          * present.
  312          */
  313         numports = 1;
  314         if (db1 != NTWOC_FE_ID_NONE)
  315                 numports++;
  316 
  317         printf("%s: %d port%s\n", sc->sc_dev.dv_xname, numports,
  318                (numports > 1 ? "s" : ""));
  319         printf("%s: port 0 interface card: %s\n", sc->sc_dev.dv_xname,
  320                ntwoc_pci_db_names[db0]);
  321         if (numports > 1)
  322                 printf("%s: port 1 interface card: %s\n", sc->sc_dev.dv_xname,
  323                        ntwoc_pci_db_names[db1]);
  324 
  325         /*
  326          * enable the RS422 tristate transmit
  327          * diable clock output (use receiver clock for both)
  328          */
  329         frontend_cr |= (NTWOC_FECR_TE0 | NTWOC_FECR_TE1);
  330         frontend_cr &= ~(NTWOC_FECR_ETC0 | NTWOC_FECR_ETC1);
  331         bus_space_write_2(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh,
  332                           NTWOC_FECR, frontend_cr);
  333 
  334         /*
  335          * initialize the SCA.  This will allocate DMAable memory based
  336          * on the number of ports we passed in, the size of each
  337          * buffer, and the number of buffers per port.
  338          */
  339         sca->sc_parent = &sc->sc_dev;
  340         sca->sc_read_1 = ntwoc_pci_sca_read_1;
  341         sca->sc_read_2 = ntwoc_pci_sca_read_2;
  342         sca->sc_write_1 = ntwoc_pci_sca_write_1;
  343         sca->sc_write_2 = ntwoc_pci_sca_write_2;
  344         sca->sc_dtr_callback = ntwoc_pci_dtr_callback;
  345         sca->sc_clock_callback = ntwoc_pci_clock_callback;
  346         sca->sc_aux = sc;
  347         sca->sc_numports = numports;
  348 
  349         /*
  350          * get clock information from user
  351          */
  352         rdiv = (flags & NTWOC_FLAGS_RXDIV_MASK) >> NTWOC_FLAGS_RXDIV_SHIFT;
  353         if (rdiv > 9)
  354                 panic("bad rx divisor in flags");
  355 
  356         tdiv = (flags & NTWOC_FLAGS_TXDIV_MASK) >> NTWOC_FLAGS_TXDIV_SHIFT;
  357         if (tdiv > 9)
  358                 panic("bad tx divisor in flags");
  359         tmc = (flags & NTWOC_FLAGS_TMC_MASK) >> NTWOC_FLAGS_TMC_SHIFT;
  360 
  361         ntwoc_pci_get_clock(&sca->sc_ports[0], flags & NTWOC_FLAGS_CLK0_MASK,
  362             tmc, rdiv, tdiv);
  363         if (sca->sc_numports > 1)
  364                 ntwoc_pci_get_clock(&sca->sc_ports[1],
  365                     (flags & NTWOC_FLAGS_CLK1_MASK) >> NTWOC_FLAGS_CLK1_SHIFT,
  366                     tmc, rdiv, tdiv);
  367 
  368         /* allocate DMA'able memory for card to use */
  369         ntwoc_pci_alloc_dma(sca);
  370         ntwoc_pci_setup_dma(sca);
  371 
  372         sca_init(sca);
  373 
  374         /*
  375          * always initialize port 0, since we have to have found it to
  376          * get this far.  If we have two ports, attach the second
  377          * as well.
  378          */
  379         sca_port_attach(sca, 0);
  380         if (numports == 2)
  381                 sca_port_attach(sca, 1);
  382 
  383         /*
  384          * Add shutdown hook so that DMA is disabled prior to reboot. Not
  385          * doing do could allow DMA to corrupt kernel memory during the
  386          * reboot before the driver initializes.
  387          */
  388         shutdownhook_establish(ntwoc_pci_shutdown, sc);
  389 
  390 #if __NetBSD_Version__ >= 104160000
  391         /*
  392          * defer getting the base clock until interrupts are enabled
  393          * (and thus we have microtime())
  394          */
  395         config_interrupts(self, ntwoc_pci_config_interrupts);
  396 #else
  397         sca->sc_baseclock = SCA_BASECLOCK;
  398         sca_print_clock_info(&sc->sc_sca);
  399 #endif
  400 }
  401 
  402 /*
  403  * extract the clock information for a port from the flags field
  404  */
  405 static void
  406 ntwoc_pci_get_clock(struct sca_port *scp, u_int8_t flags, u_int8_t tmc,
  407     u_int8_t rdiv, u_int8_t tdiv)
  408 {
  409         scp->sp_eclock =
  410             (flags & NTWOC_FLAGS_ECLOCK_MASK) >> NTWOC_FLAGS_ECLOCK_SHIFT;
  411         scp->sp_rxs = rdiv;
  412         scp->sp_txs = tdiv;
  413         scp->sp_tmc = tmc;
  414 
  415         /* get rx source */
  416         switch ((flags & NTWOC_FLAGS_RXS_MASK) >> NTWOC_FLAGS_RXS_SHIFT) {
  417         case NTWOC_FLAGS_RXS_LINE:
  418                 scp->sp_rxs = 0;
  419                 break;
  420         case NTWOC_FLAGS_RXS_LINE_SN:
  421                 scp->sp_rxs |= SCA_RXS_CLK_LINE_SN;
  422                 break;
  423         case NTWOC_FLAGS_RXS_INTERNAL:
  424                 scp->sp_rxs |= SCA_RXS_CLK_INTERNAL;
  425                 break;
  426         case NTWOC_FLAGS_RXS_ADPLL_OUT:
  427                 scp->sp_rxs |= SCA_RXS_CLK_ADPLL_OUT;
  428                 break;
  429         case NTWOC_FLAGS_RXS_ADPLL_IN:
  430                 scp->sp_rxs |= SCA_RXS_CLK_ADPLL_IN;
  431                 break;
  432         default:
  433                 panic("bad rx source in flags");
  434         }
  435 
  436         /* get tx source */
  437         switch ((flags & NTWOC_FLAGS_TXS_MASK) >> NTWOC_FLAGS_TXS_SHIFT) {
  438         case NTWOC_FLAGS_TXS_LINE:
  439                 scp->sp_txs = 0;
  440                 break;
  441         case NTWOC_FLAGS_TXS_INTERNAL:
  442                 scp->sp_txs |= SCA_TXS_CLK_INTERNAL;
  443                 break;
  444         case NTWOC_FLAGS_TXS_RXCLOCK:
  445                 scp->sp_txs |= SCA_TXS_CLK_RXCLK;
  446                 break;
  447         default:
  448                 panic("bad rx source in flags");
  449         }
  450 }
  451 
  452 
  453 static int
  454 ntwoc_pci_intr(void *arg)
  455 {
  456         struct ntwoc_pci_softc *sc = (struct ntwoc_pci_softc *)arg;
  457 
  458         return sca_hardintr(&sc->sc_sca);
  459 }
  460 
  461 /*
  462  * shut down interrupts and DMA, so we don't trash the kernel on warm
  463  * boot.  Also, lower DTR on each port and disable card interrupts.
  464  */
  465 static void
  466 ntwoc_pci_shutdown(void *aux)
  467 {
  468         struct ntwoc_pci_softc *sc = aux;
  469         u_int16_t fecr;
  470 
  471         /*
  472          * shut down the SCA ports
  473          */
  474         sca_shutdown(&sc->sc_sca);
  475 
  476         /*
  477          * disable interrupts for the whole card.  Black magic, see comment
  478          * above.
  479          */
  480         bus_space_write_4(sc->sc_asic_iot, sc->sc_asic_ioh,
  481                           0x68, 0x10900);
  482 
  483         /*
  484          * lower DTR on both ports
  485          */
  486         fecr = bus_space_read_2(sc->sc_sca.sc_iot,
  487                                 sc->sc_sca.sc_ioh, NTWOC_FECR);
  488         fecr |= (NTWOC_FECR_DTR0 | NTWOC_FECR_DTR1);
  489         bus_space_write_2(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh,
  490                           NTWOC_FECR, fecr);
  491 }
  492 
  493 static void
  494 ntwoc_pci_dtr_callback(void *aux, int port, int state)
  495 {
  496         struct ntwoc_pci_softc *sc = aux;
  497         u_int16_t fecr;
  498 
  499         fecr = bus_space_read_2(sc->sc_sca.sc_iot,
  500                                 sc->sc_sca.sc_ioh, NTWOC_FECR);
  501 
  502         NTWO_DPRINTF(("dtr: port == %d, state == %d, old fecr:  0x%04x\n",
  503                        port, state, fecr));
  504 
  505         if (port == 0) {
  506                 if (state == 0)
  507                         fecr |= NTWOC_FECR_DTR0;
  508                 else
  509                         fecr &= ~NTWOC_FECR_DTR0;
  510         } else {
  511                 if (state == 0)
  512                         fecr |= NTWOC_FECR_DTR1;
  513                 else
  514                         fecr &= ~NTWOC_FECR_DTR1;
  515         }
  516 
  517         NTWO_DPRINTF(("new fecr:  0x%04x\n", fecr));
  518 
  519         bus_space_write_2(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh,
  520                           NTWOC_FECR, fecr);
  521 }
  522 
  523 static void
  524 ntwoc_pci_clock_callback(void *aux, int port, int enable)
  525 {
  526         struct ntwoc_pci_softc *sc = aux;
  527         u_int16_t fecr;
  528 
  529         fecr = bus_space_read_2(sc->sc_sca.sc_iot,
  530                                 sc->sc_sca.sc_ioh, NTWOC_FECR);
  531 
  532         NTWO_DPRINTF(("clk: port == %d, enable == %d, old fecr:  0x%04x\n",
  533                        port, enable, fecr));
  534 
  535         if (port == 0) {
  536                 if (enable)
  537                         fecr |= NTWOC_FECR_ETC0;
  538                 else
  539                         fecr &= ~NTWOC_FECR_ETC0;
  540         } else {
  541                 if (enable)
  542                         fecr |= NTWOC_FECR_ETC1;
  543                 else
  544                         fecr &= ~NTWOC_FECR_ETC1;
  545         }
  546 
  547         NTWO_DPRINTF(("new fecr:  0x%04x\n", fecr));
  548 
  549         bus_space_write_2(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh,
  550                           NTWOC_FECR, fecr);
  551 }
  552 
  553 static int
  554 ntwoc_pci_alloc_dma(struct sca_softc *sc)
  555 {
  556         u_int   allocsize;
  557         int     err;
  558         int     rsegs;
  559         u_int   bpp;
  560 
  561         /* first initialize the number of descriptors */
  562         sc->sc_ports[0].sp_nrxdesc = NTWOC_NrxBUFS;
  563         sc->sc_ports[0].sp_ntxdesc = NTWOC_NtxBUFS;
  564         if (sc->sc_numports == 2) {
  565                 sc->sc_ports[1].sp_nrxdesc = NTWOC_NrxBUFS;
  566                 sc->sc_ports[1].sp_ntxdesc = NTWOC_NtxBUFS;
  567         }
  568 
  569         NTWO_DPRINTF(("sizeof sca_desc_t: %d bytes\n", sizeof (sca_desc_t)));
  570 
  571         bpp = sc->sc_numports * (NTWOC_NtxBUFS + NTWOC_NrxBUFS);
  572 
  573         allocsize = bpp * (SCA_BSIZE + sizeof (sca_desc_t));
  574 
  575         /*
  576          * sanity checks:
  577          *
  578          * Check the total size of the data buffers, and so on.  The total
  579          * DMAable space needs to fit within a single 16M region, and the
  580          * descriptors need to fit within a 64K region.
  581          */
  582         if (allocsize > 16 * 1024 * 1024)
  583                 return 1;
  584         if (bpp * sizeof (sca_desc_t) > 64 * 1024)
  585                 return 1;
  586 
  587         sc->scu_allocsize = allocsize;
  588 
  589         /*
  590          * Allocate one huge chunk of memory.
  591          */
  592         if (bus_dmamem_alloc(sc->scu_dmat,
  593                              allocsize,
  594                              SCA_DMA_ALIGNMENT,
  595                              SCA_DMA_BOUNDARY,
  596                              &sc->scu_seg, 1, &rsegs, BUS_DMA_NOWAIT) != 0) {
  597                 printf("Could not allocate DMA memory\n");
  598                 return 1;
  599         }
  600         NTWO_DPRINTF(("DMA memory allocated:  %d bytes\n", allocsize));
  601 
  602         if (bus_dmamem_map(sc->scu_dmat, &sc->scu_seg, 1, allocsize,
  603                            &sc->scu_dma_addr, BUS_DMA_NOWAIT) != 0) {
  604                 printf("Could not map DMA memory into kernel space\n");
  605                 return 1;
  606         }
  607         NTWO_DPRINTF(("DMA memory mapped\n"));
  608 
  609         if (bus_dmamap_create(sc->scu_dmat, allocsize, 2,
  610                               allocsize, SCA_DMA_BOUNDARY,
  611                               BUS_DMA_NOWAIT, &sc->scu_dmam) != 0) {
  612                 printf("Could not create DMA map\n");
  613                 return 1;
  614         }
  615         NTWO_DPRINTF(("DMA map created\n"));
  616 
  617         err = bus_dmamap_load(sc->scu_dmat, sc->scu_dmam, sc->scu_dma_addr,
  618                               allocsize, NULL, BUS_DMA_NOWAIT);
  619         if (err != 0) {
  620                 printf("Could not load DMA segment:  %d\n", err);
  621                 return 1;
  622         }
  623         NTWO_DPRINTF(("DMA map loaded\n"));
  624 
  625         return 0;
  626 }
  627 
  628 /*
  629  * Take the memory allocated with sca_alloc_dma() and divide it among the
  630  * two ports.
  631  */
  632 static void
  633 ntwoc_pci_setup_dma(struct sca_softc *sc)
  634 {
  635         sca_port_t *scp0, *scp1;
  636         u_int8_t  *vaddr0;
  637         u_int32_t paddr0;
  638         u_long addroff;
  639 
  640         /*
  641          * remember the physical address to 24 bits only, since the upper
  642          * 8 bits is programed into the device at a different layer.
  643          */
  644         paddr0 = (sc->scu_dmam->dm_segs[0].ds_addr & 0x00ffffff);
  645         vaddr0 = sc->scu_dma_addr;
  646 
  647         /*
  648          * if we have only one port it gets the full range.  If we have
  649          * two we need to do a little magic to divide things up.
  650          *
  651          * The descriptors will all end up in the front of the area, while
  652          * the remainder of the buffer is used for transmit and receive
  653          * data.
  654          *
  655          * -------------------- start of memory
  656          *    tx desc port 0
  657          *    rx desc port 0
  658          *    tx desc port 1
  659          *    rx desc port 1
  660          *    tx buffer port 0
  661          *    rx buffer port 0
  662          *    tx buffer port 1
  663          *    rx buffer port 1
  664          * -------------------- end of memory
  665          */
  666         scp0 = &sc->sc_ports[0];
  667         scp1 = &sc->sc_ports[1];
  668 
  669         scp0->sp_txdesc_p = paddr0;
  670         scp0->sp_txdesc = (sca_desc_t *)vaddr0;
  671         addroff = sizeof(sca_desc_t) * scp0->sp_ntxdesc;
  672 
  673         /*
  674          * point to the range following the tx descriptors, and
  675          * set the rx descriptors there.
  676          */
  677         scp0->sp_rxdesc_p = paddr0 + addroff;
  678         scp0->sp_rxdesc = (sca_desc_t *)(vaddr0 + addroff);
  679         addroff += sizeof(sca_desc_t) * scp0->sp_nrxdesc;
  680 
  681         if (sc->sc_numports == 2) {
  682                 scp1->sp_txdesc_p = paddr0 + addroff;
  683                 scp1->sp_txdesc = (sca_desc_t *)(vaddr0 + addroff);
  684                 addroff += sizeof(sca_desc_t) * scp1->sp_ntxdesc;
  685 
  686                 scp1->sp_rxdesc_p = paddr0 + addroff;
  687                 scp1->sp_rxdesc = (sca_desc_t *)(vaddr0 + addroff);
  688                 addroff += sizeof(sca_desc_t) * scp1->sp_nrxdesc;
  689         }
  690 
  691         /*
  692          * point to the memory following the descriptors, and set the
  693          * transmit buffer there.
  694          */
  695         scp0->sp_txbuf_p = paddr0 + addroff;
  696         scp0->sp_txbuf = vaddr0 + addroff;
  697         addroff += SCA_BSIZE * scp0->sp_ntxdesc;
  698 
  699         /*
  700          * lastly, skip over the transmit buffer and set up pointers into
  701          * the receive buffer.
  702          */
  703         scp0->sp_rxbuf_p = paddr0 + addroff;
  704         scp0->sp_rxbuf = vaddr0 + addroff;
  705         addroff += SCA_BSIZE * scp0->sp_nrxdesc;
  706 
  707         if (sc->sc_numports == 2) {
  708                 scp1->sp_txbuf_p = paddr0 + addroff;
  709                 scp1->sp_txbuf = vaddr0 + addroff;
  710                 addroff += SCA_BSIZE * scp1->sp_ntxdesc;
  711 
  712                 scp1->sp_rxbuf_p = paddr0 + addroff;
  713                 scp1->sp_rxbuf = vaddr0 + addroff;
  714                 addroff += SCA_BSIZE * scp1->sp_nrxdesc;
  715         }
  716 
  717         /*
  718          * as a consistancy check, addroff should be equal to the allocation
  719          * size.
  720          */
  721         if (sc->scu_allocsize != addroff)
  722                 printf("ERROR:  scu_allocsize != addroff: %lu != %lu\n",
  723                        (u_long)sc->scu_allocsize, addroff);
  724 }
  725 
  726 #if __NetBSD_Version__ >= 104160000
  727 static void
  728 ntwoc_pci_config_interrupts(self)
  729         struct device *self;
  730 {
  731         struct ntwoc_pci_softc *sc;
  732 
  733         sc = (void *)self;
  734         sca_get_base_clock(&sc->sc_sca);
  735         sca_print_clock_info(&sc->sc_sca);
  736 }
  737 #endif

Cache object: e01374d9b003212b06fa3807fb6401c4


[ 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.