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/snc/dp83932subr.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 /*      $NecBSD: dp83932subr.c,v 1.5.6.2 1999/10/09 05:47:23 kmatsuda Exp $     */
    2 /*      $NetBSD$        */
    3   
    4 /*-
    5  * Copyright (c) 1997, 1998, 1999
    6  *      Kouichi Matsuda.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   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. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Kouichi Matsuda for
   19  *      NetBSD/pc98.
   20  * 4. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/10.3/sys/dev/snc/dp83932subr.c 242871 2012-11-10 14:58:06Z nyan $");
   37 /*
   38  * Routines of NEC PC-9801-83, 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R 
   39  * Ethernet interface for NetBSD/pc98, ported by Kouichi Matsuda.
   40  *
   41  * These cards use National Semiconductor DP83934AVQB as Ethernet Controller
   42  * and National Semiconductor NS46C46 as (64 * 16 bits) Microwire Serial EEPROM.
   43  */
   44 
   45 /*
   46  * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
   47  */
   48 
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/protosw.h>
   52 #include <sys/socket.h>
   53 
   54 #include <net/ethernet.h>
   55 #include <net/if.h>
   56 #include <net/if_arp.h>
   57 #include <net/if_media.h>
   58 
   59 #include <sys/bus.h>
   60 #include <machine/bus.h>
   61 
   62 #include <dev/snc/dp83932reg.h>
   63 #include <dev/snc/dp83932var.h>
   64 #include <dev/snc/if_sncreg.h>
   65 #include <dev/snc/dp83932subr.h>
   66 
   67 static __inline u_int16_t snc_nec16_select_bank
   68         (struct snc_softc *, u_int32_t, u_int32_t);
   69 
   70 /*
   71  * Interface exists: make available by filling in network interface
   72  * record.  System will initialize the interface when it is ready
   73  * to accept packets.
   74  */
   75 int
   76 sncsetup(struct snc_softc *sc, u_int8_t *lladdr)
   77 {
   78         u_int32_t p, pp;
   79         int     i;
   80         int     offset;
   81 
   82         /*
   83          * Put the pup in reset mode (sncinit() will fix it later),
   84          * stop the timer, disable all interrupts and clear any interrupts.
   85          */
   86         NIC_PUT(sc, SNCR_CR, CR_STP);
   87         wbflush();
   88         NIC_PUT(sc, SNCR_CR, CR_RST);
   89         wbflush();
   90         NIC_PUT(sc, SNCR_IMR, 0);
   91         wbflush();
   92         NIC_PUT(sc, SNCR_ISR, ISR_ALL);
   93         wbflush();
   94 
   95         /*
   96          * because the SONIC is basically 16bit device it 'concatenates'
   97          * a higher buffer address to a 16 bit offset--this will cause wrap
   98          * around problems near the end of 64k !!
   99          */
  100         p = pp = 0;
  101 
  102         for (i = 0; i < NRRA; i++) {
  103                 sc->v_rra[i] = SONIC_GETDMA(p);
  104                 p += RXRSRC_SIZE(sc);
  105         }
  106         sc->v_rea = SONIC_GETDMA(p);
  107 
  108         p = SOALIGN(sc, p);
  109 
  110         sc->v_cda = SONIC_GETDMA(p);
  111         p += CDA_SIZE(sc);
  112 
  113         p = SOALIGN(sc, p);
  114 
  115         for (i = 0; i < NTDA; i++) {
  116                 struct mtd *mtdp = &sc->mtda[i];
  117                 mtdp->mtd_vtxp = SONIC_GETDMA(p);
  118                 p += TXP_SIZE(sc);
  119         }
  120 
  121         p = SOALIGN(sc, p);
  122 
  123         if ((p - pp) > PAGE_SIZE) {
  124                 device_printf (sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +"
  125                     "TDA (%ld) > PAGE_SIZE (%d). Punt!\n",
  126                     (u_long)sc->v_cda - (u_long)sc->v_rra[0],
  127                     (u_long)sc->mtda[0].mtd_vtxp - (u_long)sc->v_cda,
  128                     (u_long)p - (u_long)sc->mtda[0].mtd_vtxp,
  129                     PAGE_SIZE);
  130                 return(1);
  131         }
  132 
  133         p = pp + PAGE_SIZE;
  134         pp = p;
  135 
  136         sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc);
  137         sc->v_rda = SONIC_GETDMA(p);
  138 
  139         p = pp + PAGE_SIZE;
  140 
  141         for (i = 0; i < NRBA; i++) {
  142                 sc->rbuf[i] = p;
  143                 p += PAGE_SIZE;
  144         }
  145 
  146         pp = p;
  147         offset = TXBSIZE;
  148         for (i = 0; i < NTDA; i++) {
  149                 struct mtd *mtdp = &sc->mtda[i];
  150 
  151                 mtdp->mtd_vbuf = SONIC_GETDMA(p);
  152                 offset += TXBSIZE;
  153                 if (offset < PAGE_SIZE) {
  154                         p += TXBSIZE;
  155                 } else {
  156                         p = pp + PAGE_SIZE;
  157                         pp = p;
  158                         offset = TXBSIZE;
  159                 }
  160         }
  161 
  162         return (0);
  163 }
  164 
  165 /*
  166  * miscellaneous NEC/SONIC detect functions.
  167  */
  168 
  169 /*
  170  * check if a specified irq is acceptable.
  171  */
  172 u_int8_t
  173 snc_nec16_validate_irq(int irq)
  174 {
  175         const u_int8_t encoded_irq[16] = {
  176             -1, -1, -1, 0, -1, 1, 2, -1, -1, 3, 4, -1, 5, 6, -1, -1
  177         };
  178 
  179         return encoded_irq[irq];
  180 }
  181 
  182 /*
  183  * specify irq to board.
  184  */
  185 int
  186 snc_nec16_register_irq(struct snc_softc *sc, int irq)
  187 {
  188         bus_space_tag_t iot = sc->sc_iot;
  189         bus_space_handle_t ioh = sc->sc_ioh;
  190         u_int8_t encoded_irq;
  191 
  192         encoded_irq = snc_nec16_validate_irq(irq);
  193         if (encoded_irq == (u_int8_t) -1) {
  194                 printf("snc_nec16_register_irq: unsupported irq (%d)\n", irq);
  195                 return 0;
  196         }
  197 
  198         /* select SNECR_IRQSEL register */
  199         bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IRQSEL);
  200         /* write encoded irq value */
  201         bus_space_write_1(iot, ioh, SNEC_CTRLB, encoded_irq);
  202 
  203         return 1;
  204 }
  205 
  206 /*
  207  * check if a specified memory base address is acceptable.
  208  */
  209 int
  210 snc_nec16_validate_mem(int maddr)
  211 {
  212 
  213         /* Check on Normal mode with max range, only */
  214         if ((maddr & ~0x1E000) != 0xC0000) {
  215                 printf("snc_nec16_validate_mem: "
  216                     "unsupported window base (0x%x)\n", maddr);
  217                 return 0;
  218         }
  219 
  220         return 1;
  221 }
  222 
  223 /*
  224  * specify memory base address to board and map to first bank.
  225  */
  226 int
  227 snc_nec16_register_mem(struct snc_softc *sc, int maddr)
  228 {
  229         bus_space_tag_t iot = sc->sc_iot;
  230         bus_space_handle_t ioh = sc->sc_ioh;
  231 
  232         if (snc_nec16_validate_mem(maddr) == 0)
  233                 return 0;
  234 
  235         /* select SNECR_MEMSEL register */
  236         bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMSEL);
  237         /* write encoded memory base select value */
  238         bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_MEMSEL_PHYS2EN(maddr));
  239 
  240         /*
  241          * set current bank to 0 (bottom) and map
  242          */
  243         /* select SNECR_MEMBS register */
  244         bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
  245         /* select new bank */
  246         bus_space_write_1(iot, ioh, SNEC_CTRLB,
  247             SNECR_MEMBS_B2EB(0) | SNECR_MEMBS_BSEN);
  248         /* set current bank to 0 */
  249         sc->curbank = 0;
  250 
  251         return 1;
  252 }
  253 
  254 int
  255 snc_nec16_check_memory(bus_space_tag_t iot, bus_space_handle_t ioh,
  256     bus_space_tag_t memt, bus_space_handle_t memh)
  257 {
  258         u_int16_t val;
  259         int i, j;
  260 
  261         val = 0;
  262         for (i = 0; i < SNEC_NBANK; i++) {
  263                 /* select new bank */
  264                 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
  265                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  266                     SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
  267 
  268                 /* write test pattern */
  269                 for (j = 0; j < SNEC_NMEMS / 2; j++) {
  270                         bus_space_write_2(memt, memh, j * 2, val + j);
  271                 }
  272                 val += 0x1000;
  273         }
  274 
  275         val = 0;
  276         for (i = 0; i < SNEC_NBANK; i++) {
  277                 /* select new bank */
  278                 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
  279                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  280                     SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
  281 
  282                 /* read test pattern */
  283                 for (j = 0; j < SNEC_NMEMS / 2; j++) {
  284                         if (bus_space_read_2(memt, memh, j * 2) != val + j)
  285                                 break;
  286                 }
  287 
  288                 if (j < SNEC_NMEMS / 2) {
  289                         printf("snc_nec16_check_memory: "
  290                             "memory check failed at 0x%04x%04x"
  291                             "val 0x%04x != expected 0x%04x\n", i, j,
  292                             bus_space_read_2(memt, memh, j * 2),
  293                             val + j);
  294                         return 0;
  295                 }
  296                 val += 0x1000;
  297         }
  298 
  299         /* zero clear mem */
  300         for (i = 0; i < SNEC_NBANK; i++) {
  301                 /* select new bank */
  302                 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
  303                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  304                     SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
  305 
  306                 bus_space_set_region_4(memt, memh, 0, 0, SNEC_NMEMS >> 2);
  307         }
  308 
  309         /* again read test if these are 0 */
  310         for (i = 0; i < SNEC_NBANK; i++) {
  311                 /* select new bank */
  312                 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
  313                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  314                     SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
  315 
  316                 /* check if cleared */
  317                 for (j = 0; j < SNEC_NMEMS; j += 2) {
  318                         if (bus_space_read_2(memt, memh, j) != 0)
  319                                 break;
  320                 }
  321 
  322                 if (j != SNEC_NMEMS) {
  323                         printf("snc_nec16_check_memory: "
  324                             "memory zero clear failed at 0x%04x%04x\n", i, j);
  325                         return 0;
  326                 }
  327         }
  328 
  329         return 1;
  330 }
  331 
  332 int
  333 snc_nec16_detectsubr(bus_space_tag_t iot, bus_space_handle_t ioh,
  334     bus_space_tag_t memt, bus_space_handle_t memh, int irq, int maddr,
  335     u_int8_t type)
  336 {
  337         u_int16_t cr;
  338         u_int8_t ident;
  339         int rv = 0;
  340 
  341         if (snc_nec16_validate_irq(irq) == (u_int8_t) -1)
  342                 return 0;
  343         /* XXX: maddr already checked */
  344         if (snc_nec16_validate_mem(maddr) == 0)
  345                 return 0;
  346 
  347         bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IDENT);
  348         ident = bus_space_read_1(iot, ioh, SNEC_CTRLB);
  349         if (ident == 0xff || ident == 0x00) {
  350                 /* not found */
  351                 return 0;
  352         }
  353 
  354         switch (type) {
  355         case SNEC_TYPE_LEGACY:
  356                 rv = (ident == SNECR_IDENT_LEGACY_CBUS);
  357                 break;
  358         case SNEC_TYPE_PNP:
  359                 rv = ((ident == SNECR_IDENT_PNP_CBUS) ||
  360                     (ident == SNECR_IDENT_PNP_PCMCIABUS));
  361                 break;
  362         default:
  363                 break;
  364         }
  365 
  366         if (rv == 0) {
  367                 printf("snc_nec16_detectsubr: parent bus mismatch\n");
  368                 return 0;
  369         }
  370 
  371         /* select SONIC register SNCR_CR */
  372         bus_space_write_1(iot, ioh, SNEC_ADDR, SNCR_CR);
  373         bus_space_write_2(iot, ioh, SNEC_CTRL, CR_RXDIS | CR_STP | CR_RST);
  374         DELAY(400);
  375 
  376         cr = bus_space_read_2(iot, ioh, SNEC_CTRL);
  377         if (cr != (CR_RXDIS | CR_STP | CR_RST)) {
  378 #ifdef DIAGNOSTIC
  379                 printf("snc_nec16_detectsubr: card reset failed, cr = 0x%04x\n",
  380                     cr);
  381 #endif
  382                 return 0;
  383         }
  384 
  385         if (snc_nec16_check_memory(iot, ioh, memt, memh) == 0)
  386                 return 0;
  387 
  388         return 1;
  389 }
  390 
  391 /* XXX */
  392 #define SNC_VENDOR_NEC          0x00004c
  393 #define SNC_NEC_SERIES_LEGACY_CBUS      0xa5
  394 #define SNC_NEC_SERIES_PNP_PCMCIA       0xd5
  395 #define SNC_NEC_SERIES_PNP_PCMCIA2      0x6d    /* XXX */
  396 #define SNC_NEC_SERIES_PNP_CBUS         0x0d
  397 #define SNC_NEC_SERIES_PNP_CBUS2        0x3d
  398 
  399 u_int8_t *
  400 snc_nec16_detect_type(u_int8_t *myea)
  401 {
  402         u_int32_t vendor = (myea[0] << 16) | (myea[1] << 8) | myea[2];
  403         u_int8_t series = myea[3];
  404         u_int8_t type = myea[4] & 0x80;
  405         u_int8_t *typestr;
  406 
  407         switch (vendor) {
  408         case SNC_VENDOR_NEC:
  409                 switch (series) {
  410                 case SNC_NEC_SERIES_LEGACY_CBUS:
  411                         if (type)
  412                                 typestr = "NEC PC-9801-84";
  413                         else
  414                                 typestr = "NEC PC-9801-83";
  415                         break;
  416                 case SNC_NEC_SERIES_PNP_CBUS:
  417                 case SNC_NEC_SERIES_PNP_CBUS2:
  418                         if (type)
  419                                 typestr = "NEC PC-9801-104";
  420                         else
  421                                 typestr = "NEC PC-9801-103";
  422                         break;
  423                 case SNC_NEC_SERIES_PNP_PCMCIA:
  424                 case SNC_NEC_SERIES_PNP_PCMCIA2:
  425                         /* XXX: right ? */
  426                         if (type)
  427                                 typestr = "NEC PC-9801N-J02R";
  428                         else
  429                                 typestr = "NEC PC-9801N-J02";
  430                         break;
  431                 default:
  432                         typestr = "NEC unknown (PC-9801N-25?)";
  433                         break;
  434                 }
  435                 break;
  436         default:
  437                 typestr = "unknown (3rd vendor?)";
  438                 break;
  439         }
  440 
  441         return typestr;
  442 }
  443 
  444 int
  445 snc_nec16_get_enaddr(bus_space_tag_t iot, bus_space_handle_t ioh,
  446     u_int8_t *myea)
  447 {
  448         u_int8_t eeprom[SNEC_EEPROM_SIZE];
  449         u_int8_t rom_sum, sum = 0x00;
  450         int i;
  451 
  452         snc_nec16_read_eeprom(iot, ioh, eeprom);
  453 
  454         for (i = SNEC_EEPROM_KEY0; i < SNEC_EEPROM_CKSUM; i++) {
  455                 sum = sum ^ eeprom[i];
  456         }
  457 
  458         rom_sum = eeprom[SNEC_EEPROM_CKSUM];
  459 
  460         if (sum != rom_sum) {
  461                 printf("snc_nec16_get_enaddr: "
  462                     "checksum mismatch; calculated %02x != read %02x",
  463                     sum, rom_sum);
  464                 return 0;
  465         }
  466 
  467         for (i = 0; i < ETHER_ADDR_LEN; i++)
  468                 myea[i] = eeprom[SNEC_EEPROM_SA0 + i];
  469 
  470         return 1;
  471 }
  472 
  473 /*
  474  * read from NEC/SONIC NIC register.
  475  */
  476 u_int16_t
  477 snc_nec16_nic_get(struct snc_softc *sc, u_int8_t reg)
  478 {
  479         u_int16_t val;
  480 
  481         /* select SONIC register */
  482         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
  483         val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL);
  484 
  485         return val;
  486 }
  487 
  488 /*
  489  * write to NEC/SONIC NIC register.
  490  */
  491 void
  492 snc_nec16_nic_put(struct snc_softc *sc, u_int8_t reg, u_int16_t val)
  493 {
  494 
  495         /* select SONIC register */
  496         bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
  497         bus_space_write_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL, val);
  498 }
  499 
  500 
  501 /*
  502  * select memory bank and map
  503  * where exists specified (internal buffer memory) offset.
  504  */
  505 static __inline u_int16_t
  506 snc_nec16_select_bank(struct snc_softc *sc, u_int32_t base, u_int32_t offset)
  507 {
  508         bus_space_tag_t iot = sc->sc_iot;
  509         bus_space_handle_t ioh = sc->sc_ioh;
  510         u_int8_t bank;
  511         u_int16_t noffset;
  512 
  513         /* bitmode is fixed to 16 bit. */
  514         bank = (base + offset * 2) >> 13;
  515         noffset = (base + offset * 2) & (SNEC_NMEMS - 1);
  516 
  517 #ifdef SNCDEBUG
  518         if (noffset % 2) {
  519                 device_printf(sc->sc_dev, "noffset is odd (0x%04x)\n",
  520                               noffset);
  521         }
  522 #endif  /* SNCDEBUG */
  523 
  524         if (sc->curbank != bank) {
  525                 /* select SNECR_MEMBS register */
  526                 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
  527                 /* select new bank */
  528                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  529                     SNECR_MEMBS_B2EB(bank) | SNECR_MEMBS_BSEN);
  530                 /* update current bank */
  531                 sc->curbank = bank;
  532         }
  533 
  534         return noffset;
  535 }
  536 
  537 /*
  538  * write to SONIC descriptors.
  539  */
  540 void
  541 snc_nec16_writetodesc(struct snc_softc *sc, u_int32_t base, u_int32_t offset,
  542     u_int16_t val)
  543 {
  544         bus_space_tag_t memt = sc->sc_memt;
  545         bus_space_handle_t memh = sc->sc_memh;
  546         u_int16_t noffset;
  547 
  548         noffset = snc_nec16_select_bank(sc, base, offset);
  549 
  550         bus_space_write_2(memt, memh, noffset, val);
  551 }
  552 
  553 /*
  554  * read from SONIC descriptors.
  555  */
  556 u_int16_t
  557 snc_nec16_readfromdesc(struct snc_softc *sc, u_int32_t base, u_int32_t offset)
  558 {
  559         bus_space_tag_t memt = sc->sc_memt;
  560         bus_space_handle_t memh = sc->sc_memh;
  561         u_int16_t noffset;
  562 
  563         noffset = snc_nec16_select_bank(sc, base, offset);
  564 
  565         return bus_space_read_2(memt, memh, noffset);
  566 }
  567 
  568 /*
  569  * read from SONIC data buffer.
  570  */
  571 void
  572 snc_nec16_copyfrombuf(struct snc_softc *sc, void *dst, u_int32_t offset,
  573     size_t size)
  574 {
  575         bus_space_tag_t memt = sc->sc_memt;
  576         bus_space_handle_t memh = sc->sc_memh;
  577         u_int16_t noffset;
  578         u_int8_t* bptr = dst;
  579 
  580         noffset = snc_nec16_select_bank(sc, offset, 0);
  581 
  582         /* XXX: should check if offset + size < 0x2000. */
  583 
  584         bus_space_barrier(memt, memh, noffset, size,
  585                           BUS_SPACE_BARRIER_READ);
  586 
  587         if (size > 3)  {
  588                 if (noffset & 3)  {
  589                         size_t asize = 4 - (noffset & 3);
  590 
  591                         bus_space_read_region_1(memt, memh, noffset,
  592                             bptr, asize);
  593                         bptr += asize;
  594                         noffset += asize;
  595                         size -= asize;
  596                 }
  597                 bus_space_read_region_4(memt, memh, noffset,
  598                     (u_int32_t *) bptr, size >> 2);
  599                 bptr += size & ~3;
  600                 noffset += size & ~3;
  601                 size &= 3;
  602         }
  603         if (size)
  604                 bus_space_read_region_1(memt, memh, noffset, bptr, size);
  605 }
  606 
  607 /*
  608  * write to SONIC data buffer.
  609  */
  610 void
  611 snc_nec16_copytobuf(struct snc_softc *sc, void *src, u_int32_t offset,
  612     size_t size)
  613 {
  614         bus_space_tag_t memt = sc->sc_memt;
  615         bus_space_handle_t memh = sc->sc_memh;
  616         u_int16_t noffset, onoffset;
  617         size_t osize = size;
  618         u_int8_t* bptr = src;
  619 
  620         noffset = snc_nec16_select_bank(sc, offset, 0);
  621         onoffset = noffset;
  622 
  623         /* XXX: should check if offset + size < 0x2000. */
  624 
  625         if (size > 3)  {
  626                 if (noffset & 3)  {
  627                         size_t asize = 4 - (noffset & 3);
  628 
  629                         bus_space_write_region_1(memt, memh, noffset,
  630                             bptr, asize);
  631                         bptr += asize;
  632                         noffset += asize;
  633                         size -= asize;
  634                 }
  635                 bus_space_write_region_4(memt, memh, noffset,
  636                     (u_int32_t *)bptr, size >> 2);
  637                 bptr += size & ~3;
  638                 noffset += size & ~3;
  639                 size -= size & ~3;
  640         }
  641         if (size)
  642                 bus_space_write_region_1(memt, memh, noffset, bptr, size);
  643 
  644         bus_space_barrier(memt, memh, onoffset, osize,
  645                           BUS_SPACE_BARRIER_WRITE);
  646 }
  647 
  648 /*
  649  * write (fill) 0 to SONIC data buffer.
  650  */
  651 void
  652 snc_nec16_zerobuf(struct snc_softc *sc, u_int32_t offset, size_t size)
  653 {
  654         bus_space_tag_t memt = sc->sc_memt;
  655         bus_space_handle_t memh = sc->sc_memh;
  656         u_int16_t noffset, onoffset;
  657         size_t osize = size;
  658 
  659         noffset = snc_nec16_select_bank(sc, offset, 0);
  660         onoffset = noffset;
  661 
  662         /* XXX: should check if offset + size < 0x2000. */
  663 
  664         if (size > 3)  {
  665                 if (noffset & 3)  {
  666                         size_t asize = 4 - (noffset & 3);
  667 
  668                         bus_space_set_region_1(memt, memh, noffset, 0, asize);
  669                         noffset += asize;
  670                         size -= asize;
  671                 }
  672                 bus_space_set_region_4(memt, memh, noffset, 0, size >> 2);
  673                 noffset += size & ~3;
  674                 size -= size & ~3;
  675         }
  676         if (size)
  677                 bus_space_set_region_1(memt, memh, noffset, 0, size);
  678 
  679         bus_space_barrier(memt, memh, onoffset, osize,
  680                           BUS_SPACE_BARRIER_WRITE);
  681 }
  682 
  683 
  684 /* 
  685  * Routines to read bytes sequentially from EEPROM through NEC PC-9801-83,
  686  * 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R for NetBSD/pc98.
  687  * Ported by Kouichi Matsuda.
  688  * 
  689  * This algorism is generic to read data sequentially from 4-Wire
  690  * Microwire Serial EEPROM.
  691  */
  692 
  693 #define SNEC_EEP_DELAY  1000
  694 
  695 void
  696 snc_nec16_read_eeprom(bus_space_tag_t iot, bus_space_handle_t ioh,
  697     u_int8_t *data)
  698 {
  699         u_int8_t n, val, bit;
  700 
  701         /* Read bytes from EEPROM; two bytes per an iteration. */
  702         for (n = 0; n < SNEC_EEPROM_SIZE / 2; n++) {
  703                 /* select SNECR_EEP */
  704                 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_EEP);
  705 
  706                 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
  707                 DELAY(SNEC_EEP_DELAY);
  708 
  709                 /* Start EEPROM access. */
  710                 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
  711                 DELAY(SNEC_EEP_DELAY);
  712 
  713                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  714                     SNECR_EEP_CS | SNECR_EEP_SK);
  715                 DELAY(SNEC_EEP_DELAY);
  716 
  717                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  718                     SNECR_EEP_CS | SNECR_EEP_DI);
  719                 DELAY(SNEC_EEP_DELAY);
  720 
  721                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  722                     SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
  723                 DELAY(SNEC_EEP_DELAY);
  724 
  725                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  726                     SNECR_EEP_CS | SNECR_EEP_DI);
  727                 DELAY(SNEC_EEP_DELAY);
  728 
  729                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  730                     SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
  731                 DELAY(SNEC_EEP_DELAY);
  732 
  733                 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
  734                 DELAY(SNEC_EEP_DELAY);
  735 
  736                 bus_space_write_1(iot, ioh, SNEC_CTRLB,
  737                     SNECR_EEP_CS | SNECR_EEP_SK);
  738                 DELAY(SNEC_EEP_DELAY);
  739 
  740                 /* Pass the iteration count to the chip. */
  741                 for (bit = 0x20; bit != 0x00; bit >>= 1) {
  742                         bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS |
  743                             ((n & bit) ? SNECR_EEP_DI : 0x00));
  744                         DELAY(SNEC_EEP_DELAY);
  745 
  746                         bus_space_write_1(iot, ioh, SNEC_CTRLB,
  747                             SNECR_EEP_CS | SNECR_EEP_SK |
  748                             ((n & bit) ? SNECR_EEP_DI : 0x00));
  749                         DELAY(SNEC_EEP_DELAY);
  750                 }
  751 
  752                 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
  753                 (void) bus_space_read_1(iot, ioh, SNEC_CTRLB);  /* ACK */
  754                 DELAY(SNEC_EEP_DELAY);
  755 
  756                 /* Read a byte. */
  757                 val = 0;
  758                 for (bit = 0x80; bit != 0x00; bit >>= 1) {
  759                         bus_space_write_1(iot, ioh, SNEC_CTRLB,
  760                             SNECR_EEP_CS | SNECR_EEP_SK);
  761                         DELAY(SNEC_EEP_DELAY);
  762 
  763                         bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
  764 
  765                         if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
  766                                 val |= bit;
  767                 }
  768                 *data++ = val;
  769 
  770                 /* Read one more byte. */
  771                 val = 0;
  772                 for (bit = 0x80; bit != 0x00; bit >>= 1) {
  773                         bus_space_write_1(iot, ioh, SNEC_CTRLB,
  774                             SNECR_EEP_CS | SNECR_EEP_SK);
  775                         DELAY(SNEC_EEP_DELAY);
  776 
  777                         bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
  778 
  779                         if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
  780                                 val |= bit;
  781                 }
  782                 *data++ = val;
  783 
  784                 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
  785                 DELAY(SNEC_EEP_DELAY);
  786         }
  787 
  788 #ifdef  SNCDEBUG
  789         /* Report what we got. */
  790         data -= SNEC_EEPROM_SIZE;
  791         log(LOG_INFO, "%s: EEPROM:"
  792             " %02x%02x%02x%02x %02x%02x%02x%02x -"
  793             " %02x%02x%02x%02x %02x%02x%02x%02x -"
  794             " %02x%02x%02x%02x %02x%02x%02x%02x -"
  795             " %02x%02x%02x%02x %02x%02x%02x%02x\n",
  796             "snc_nec16_read_eeprom",
  797             data[ 0], data[ 1], data[ 2], data[ 3],
  798             data[ 4], data[ 5], data[ 6], data[ 7],
  799             data[ 8], data[ 9], data[10], data[11],
  800             data[12], data[13], data[14], data[15],
  801             data[16], data[17], data[18], data[19],
  802             data[20], data[21], data[22], data[23],
  803             data[24], data[25], data[26], data[27],
  804             data[28], data[29], data[30], data[31]);
  805 #endif
  806 }
  807 
  808 #ifdef  SNCDEBUG
  809 void
  810 snc_nec16_dump_reg(bus_space_tag_t iot, bus_space_handle_t ioh)
  811 {
  812         u_int8_t n;
  813         u_int16_t val;
  814 
  815         printf("SONIC registers (word):");
  816         for (n = 0; n < SNC_NREGS; n++) {
  817                 /* select required SONIC register */
  818                 bus_space_write_1(iot, ioh, SNEC_ADDR, n);
  819                 DELAY(10);
  820                 val = bus_space_read_2(iot, ioh, SNEC_CTRL);
  821                 if ((n % 0x10) == 0)
  822                         printf("\n%04x ", val);
  823                 else
  824                         printf("%04x ", val);
  825         }
  826         printf("\n");
  827 
  828         printf("NEC/SONIC registers (byte):\n");
  829         for (n = SNECR_MEMBS; n <= SNECR_IDENT; n += 2) {
  830                 /* select required SONIC register */
  831                 bus_space_write_1(iot, ioh, SNEC_ADDR, n);
  832                 DELAY(10);
  833                 val = (u_int16_t) bus_space_read_1(iot, ioh, SNEC_CTRLB);
  834                 printf("%04x ", val);
  835         }
  836         printf("\n");
  837 }
  838 
  839 #endif  /* SNCDEBUG */

Cache object: 8e3169f5a26c35a484d87811916a80be


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