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

Cache object: 017e9f49de86372b52ce33dd9c558cd3


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