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

Cache object: 313dfc8d77321d233d68518f49ea34c2


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