gonzui


Format: Advanced Search

t2ex/t2ex_source/driver/tef_em1d/netdrv/src/misc.cbare sourcepermlink (0.02 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T2EX Software Package
    4:  *
    5:  *    Copyright 2012 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2012/12/12.
   10:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/04.
   11:  *
   12:  *----------------------------------------------------------------------
   13:  */
   14: /*
   15:  * This software package is available for use, modification, 
   16:  * and redistribution in accordance with the terms of the attached 
   17:  * T-License 2.x.
   18:  * If you want to redistribute the source code, you need to attach 
   19:  * the T-License 2.x document.
   20:  * There's no obligation to publish the content, and no obligation 
   21:  * to disclose it to the TRON Forum if you have modified the 
   22:  * software package.
   23:  * You can also distribute the modified source code. In this case, 
   24:  * please register the modification to T-Kernel traceability service.
   25:  * People can know the history of modifications by the service, 
   26:  * and can be sure that the version you have inherited some 
   27:  * modification of a particular version or not.
   28:  *
   29:  *    http://trace.tron.org/tk/?lang=en
   30:  *    http://trace.tron.org/tk/?lang=ja
   31:  *
   32:  * As per the provisions of the T-License 2.x, TRON Forum ensures that 
   33:  * the portion of the software that is copyrighted by Ken Sakamura or 
   34:  * the TRON Forum does not infringe the copyrights of a third party.
   35:  * However, it does not make any warranty other than this.
   36:  * DISCLAIMER: TRON Forum and Ken Sakamura shall not be held
   37:  * responsible for any consequences or damages caused directly or
   38:  * indirectly by the use of this software package.
   39:  *
   40:  * The source codes in bsd_source.tar.gz in this software package are 
   41:  * derived from NetBSD or OpenBSD and not covered under T-License 2.x.
   42:  * They need to be changed or redistributed according to the 
   43:  * representation of each source header.
   44:  */
   45: 
   46: /*
   47:  *      @(#)misc.c
   48:  *
   49:  */
   50: 
   51: #include        "netdrv.h"
   52: 
   53: /*----------------------------------------------------------------------
   54:         Functions related to memory
   55:                 (do not use malloc in order to reduce code size.)
   56: ----------------------------------------------------------------------*/
   57: /*
   58:  *      allocate memory area
   59:  */
   60: EXPORT  ER       AllocMem(W sz, VP *p)
   61: {
   62:         T_RSMB msts;
   63: 
   64:         if (tk_ref_smb(&msts) >= E_OK) {
   65:                 sz = (sz + msts.blksz - 1) / msts.blksz;
   66:                 return tk_get_smb(p, sz, TA_RNG0);
   67:         }
   68:         return E_NOMEM;
   69: }
   70: 
   71: /*
   72:  *      free memory area
   73:  */
   74: EXPORT  void     FreeMem(VP p)
   75: {
   76:         if (p != NULL) tk_rel_smb(p);
   77: }
   78: /*----------------------------------------------------------------------
   79:         Functions related to receive buffer
   80: ----------------------------------------------------------------------*/
   81: /*
   82:  *      Setting of receive buffer  (bp = NULL : Initialize)
   83:  */
   84: EXPORT  ER       SetRxBuf(NetInf *inf, VP bp)
   85: {
   86:         UW     imsk;
   87: 
   88:         if (bp == NULL) {      /* Initialize */
   89:                 DI(imsk);
   90:                 inf->ip_rxbuf = inf->op_rxbuf = 0;
   91:                 EI(imsk);
   92:         } else {               /* Setting */
   93:                 if (inf->ip_rxbuf - inf->op_rxbuf >= N_RXBUF) return E_BUSY;
   94:                 inf->rxbuf[inf->ip_rxbuf % N_RXBUF] = bp;
   95:                 inf->ip_rxbuf++;
   96:         }
   97:         return E_OK;
   98: }
   99: 
  100: /*
  101:  *      get a receive buffer (called in interrupt handler)
  102:  */
  103: EXPORT  VP       GetRxBuf(NetInf *inf)
  104: {
  105:         if (inf->ip_rxbuf == inf->op_rxbuf) return NULL;
  106:         return inf->rxbuf[(inf->op_rxbuf++) % N_RXBUF];
  107: }
  108: /*----------------------------------------------------------------------
  109:         Functions related to message
  110: ----------------------------------------------------------------------*/
  111: /*
  112:  *      Send a message
  113:  */
  114: EXPORT  ER       SendMsg(NetInf *inf, VP bp, W len)
  115: {
  116:         ER             er;
  117:         NetEvent       evt;
  118: 
  119:         evt.buf = bp;          /* Receive buffer       */
  120:         evt.len = len;         /* Receive Data length */
  121: 
  122:         /* Send message */
  123:         er = tk_snd_mbf(inf->mbfid, &evt, sizeof(evt), TMO_POL);
  124:         if (bp != NULL) {
  125:                 if (er >= E_OK) inf->stinf.rxpkt++;   /* Packets received. */
  126:                 else {
  127:                         inf->stinf.misspkt++;        /* Packets abandoned */
  128:                         SetRxBuf(inf, bp);   /* Set receive buffer     */
  129:                 }
  130:         }
  131:         return er;
  132: }
  133: /*----------------------------------------------------------------------
  134:         Functions related to MII
  135: ----------------------------------------------------------------------*/
  136: /*
  137:  *      MII related registers
  138:  */
  139: #define BMCR_RESET      (1 << 15)    /* 0x8000 */
  140: #define BMCR_SPEED0     (1 << 13)   /* 0x2000 */
  141: #define BMCR_ANEG       (1 << 12)     /* 0x1000 */
  142: #define BMCR_PDN        (1 << 11)      /* 0x0800 */
  143: #define BMCR_ISOLATE    (1 << 10)  /* 0x0400 */
  144: #define BMCR_RANEG      (1 << 9)     /* 0x0200 */
  145: #define BMCR_FDX        (1 << 8)       /* 0x0100 */
  146: #define BMCR_SPEED1     (1 << 6)    /* 0x0040 */
  147: 
  148: #define BMSR_GB         (1 << 8)       /* 0x0100 */
  149: 
  150: #define ANAR_TX_FD      (1 << 8)     /* 0x0100 */
  151: #define ANAR_TX_HD      (1 << 7)     /* 0x0080 */
  152: #define ANAR_10_FD      (1 << 6)     /* 0x0040 */
  153: #define ANAR_10_HD      (1 << 5)     /* 0x0020 */
  154: 
  155: #define GBCR_1000T_FD   (1 << 9)  /* 0x0200 */
  156: #define GBCR_1000T_HD   (1 << 8)  /* 0x0100 */
  157: 
  158: #define peek_mii(inf, adr, reg) (*inf->mii_read) ((inf), (adr), (reg))
  159: #define poke_mii(inf, adr, reg, dat)    \
  160:                                 (*inf->mii_write)((inf), (adr), (reg), (dat))
  161: /*
  162:  *      Search MII address
  163:  */
  164: EXPORT  INT      MIIfind(NetInf *inf, W target)
  165: {
  166:         W      i, adr, reg, val, prev;
  167: 
  168:         if (inf->mii_read == NULL || inf->mii_write == NULL) return E_NOMDA;
  169: 
  170:         for (i = 0; i < 32; i++) {
  171:                 /* Criteria: when value of all registers are the same,
  172:                         assume not exist */
  173:                 adr = (i + target) & 31;
  174:                 prev = peek_mii(inf, adr, 0);
  175:                 for (reg = 1; reg < 32; reg++) {
  176:                         val = peek_mii(inf, adr, reg);
  177:                         if (val != prev) goto fin;
  178:                         prev = val;
  179:                 }
  180:         }
  181:         adr = E_NOMDA;
  182:  fin:
  183:     return adr;
  184: }
  185: 
  186: /*
  187:  *      Initialize MII
  188:  */
  189: EXPORT  INT      MIIinit(NetInf *inf, W target)
  190: {
  191:         W      adr, mii_reg0, mii_reg4, mii_reg9;
  192:         W      i, bmcr, gbe;
  193: 
  194:         if (inf->mii_read == NULL || inf->mii_write == NULL) return E_NOMDA;
  195: 
  196:         /* Search MII address */
  197:         adr = MIIfind(inf, target);
  198:         if (adr < 0) {
  199:                 DP(("MIIinit(): MII not found\n"));
  200:                 goto fin;
  201:         }
  202: 
  203:         DP(("MIIinit(): MII found, address #%d\n", adr));
  204: 
  205:         /* Reset MII, then sets depending on the mode */
  206:         poke_mii(inf, adr, 0, BMCR_RESET);
  207:         for (i = 0; i < 2000; i++) {   /* max 1sec */
  208:                 WaitUsec(500);
  209:                 bmcr = peek_mii(inf, adr, 0);
  210:                 if (!(bmcr & BMCR_RESET)) break;
  211:         }
  212:         DP(("MIIinit(): MII reset: wait: %d count(s)\n", i + 1));
  213: 
  214:         /* Confirm support of Giga-bit mode */
  215:         gbe = peek_mii(inf, adr, 1) & BMSR_GB;
  216:         DP(("MIIinit(): GbE %supported\n", gbe ? "" : "not "));
  217: 
  218:         /* Setting of auto-negotiation advertisement.
  219:            Copy capability bits regardless to the initial value of
  220:            advertisement register. does not support 1000BASE-T(Half-Duplex) */
  221:         mii_reg0  = 0;
  222:         mii_reg4  = peek_mii(inf, adr, 4) &
  223:                 ~(ANAR_TX_FD | ANAR_TX_HD | ANAR_10_FD | ANAR_10_HD);
  224:         mii_reg4 |= (peek_mii(inf, adr, 1) & 0x7800) >> 6;
  225:         if (gbe) {
  226:                 mii_reg9  = peek_mii(inf, adr, 9) &
  227:                         ~(GBCR_1000T_FD | GBCR_1000T_HD);
  228:                 mii_reg9 |= (peek_mii(inf, adr, 15) & 0x2000) >> 4;
  229:         } else {
  230:                 mii_reg9  = 0;
  231:         }
  232: 
  233:         switch (inf->di.ifconn = IFC_TYPE(inf)) {
  234:         case   IFC_AUI:
  235:         case   IFC_TPE:
  236:         case   IFC_BNC:
  237:                 if (isFDX(inf)) mii_reg0 |= BMCR_FDX;
  238:                 break;
  239:         case   IFC_100TX:
  240:         case   IFC_100FX:
  241:                 mii_reg0 |= BMCR_SPEED0;
  242:                 if (isFDX(inf)) mii_reg0 |= BMCR_FDX;
  243:                 break;
  244:         case   IFC_1000T:
  245:                 // Auto negotiation is mandatory for 1000BASE-T,
  246:                 // regard as same to IFC_AUTO.
  247:                 /* fall-through */
  248:         default:
  249:                 inf->di.ifconn = IFC_AUTO;
  250:                 mii_reg0 |= BMCR_ANEG | BMCR_RANEG;
  251:                 if (!isFDX(inf)) {
  252:                         mii_reg4 &= ~(ANAR_TX_FD | ANAR_10_FD);
  253:                         mii_reg9 &= ~(GBCR_1000T_FD);
  254:                 }
  255:                 break;
  256:         }
  257: 
  258:         if (gbe) poke_mii(inf, adr, 9, mii_reg9);
  259:         poke_mii(inf, adr, 4, mii_reg4);
  260:         poke_mii(inf, adr, 0, mii_reg0);
  261: 
  262: #ifdef  DEBUG
  263:         for (i = 0; i < 32; i++) printf("%04x%c", peek_mii(inf, adr, i),
  264:                                         ((i + 1) % 16) ? ' ' : '\n');
  265: #endif
  266: 
  267:         /* Clear PHY status register */
  268:         peek_mii(inf, adr, 1);
  269: 
  270:  fin:
  271:         return adr;
  272: }
  273: /*----------------------------------------------------------------------
  274:         Other common functions
  275: ----------------------------------------------------------------------*/
  276: /*
  277:  *      Setting of product name
  278:  */
  279: EXPORT  void     SetProdName(NetInf *inf, UB **nm1, UB **nm2)
  280: {
  281:         W      n;
  282: 
  283:         if (nm1 == NULL) n = 0;
  284:         else {
  285:                 nm1 += (inf->devix >> 8) & 0x0f;      /* Series name*/
  286:                 strncpy(inf->di.name, *nm1, L_NETPNAME);
  287:                 n = strlen(*nm1);
  288:         }
  289:         if (n < L_NETPNAME) {
  290:                 nm2 += inf->devix & 0xff;             /* individual name */
  291:                 strncpy(&inf->di.name[n], *nm2, L_NETPNAME - n);
  292:         }
  293: 
  294: DP(("Net%c: '%.40s'\n", NetUnit(inf), inf->di.name));
  295: 
  296: }
  297: 
  298: /*
  299:  *      Calculation of CRC
  300:  *      * when the MAC address is 00:11:22:33:44:55, the order in memory is
  301:  *        00, 11, 22, 33, 44, 55. (i.e. bigendian)
  302:  *      * Bit inversion may be required, in order to make the calculated
  303:  *        results to bigendian.
  304:  */
  305: EXPORT  UW       CalcCRC32(UB *data, W len)
  306: {
  307: #define CRC_POLY        0x04c11db6
  308: 
  309:         UW     crc, byteindex, addrbyte, bitindex, carry;
  310: 
  311:         crc = 0xffffffff;
  312: 
  313:         for (byteindex = 0; byteindex < len; byteindex++) {
  314:                 addrbyte = data[byteindex];
  315: 
  316:                 for (bitindex = 0; bitindex < 8; bitindex++) {
  317:                         carry = (crc >> 31) ^ (addrbyte & 1);
  318:                         crc <<= 1;
  319: 
  320:                         if (carry) crc = (crc ^ CRC_POLY) | carry;
  321: 
  322:                         addrbyte >>= 1;
  323:                 }
  324:         }
  325: 
  326:         return crc;
  327: }
  328: