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

Cache object: e91086df4cc11b98066465abd299145f


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