⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 depca.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
** card initialized itself correctly.** ** Search the Ethernet address ROM for the signature. Since the ROM address** counter can start at an arbitrary point, the search must include the entire** probe sequence length plus the (length_of_the_signature - 1).** Stop the search IMMEDIATELY after the signature is found so that the** PROM address counter is correctly positioned at the start of the** ethernet address for later read out.*/__initfunc(static intDevicePresent(u_long ioaddr)){  union {    struct {      u32 a;      u32 b;    } llsig;    char Sig[sizeof(u32) << 1];  } dev;  short sigLength=0;  s8 data;  s16 nicsr;  int i, j, status = 0;  data = inb(DEPCA_PROM);                /* clear counter on DEPCA */  data = inb(DEPCA_PROM);                /* read data */  if (data == 0x08) {                    /* Enable counter on DEPCA */    nicsr = inb(DEPCA_NICSR);    nicsr |= AAC;    outb(nicsr, DEPCA_NICSR);  }    dev.llsig.a = ETH_PROM_SIG;  dev.llsig.b = ETH_PROM_SIG;  sigLength = sizeof(u32) << 1;  for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {    data = inb(DEPCA_PROM);    if (dev.Sig[j] == data) {    /* track signature */      j++;    } else {                     /* lost signature; begin search again */      if (data == dev.Sig[0]) {  /* rare case.... */	j=1;      } else {	j=0;      }    }  }  if (j!=sigLength) {    status = -ENODEV;           /* search failed */  }  return status;}/*** The DE100 and DE101 PROM accesses were made non-standard for some bizarre** reason: access the upper half of the PROM with x=0; access the lower half** with x=1.*/__initfunc(static intget_hw_addr(struct device *dev)){  u_long ioaddr = dev->base_addr;  int i, k, tmp, status = 0;  u_short j, x, chksum;  x = (((adapter == de100) || (adapter == de101)) ? 1 : 0);  for (i=0,k=0,j=0;j<3;j++) {    k <<= 1 ;    if (k > 0xffff) k-=0xffff;    k += (u_char) (tmp = inb(DEPCA_PROM + x));    dev->dev_addr[i++] = (u_char) tmp;    k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8);    dev->dev_addr[i++] = (u_char) tmp;    if (k > 0xffff) k-=0xffff;  }  if (k == 0xffff) k=0;  chksum = (u_char) inb(DEPCA_PROM + x);  chksum |= (u_short) (inb(DEPCA_PROM + x) << 8);  if (k != chksum) status = -1;  return status;}/*** Load a packet into the shared memory*/static int load_packet(struct device *dev, struct sk_buff *skb){  struct depca_private *lp = (struct depca_private *)dev->priv;  int i, entry, end, len, status = 0;  entry = lp->tx_new;  		               /* Ring around buffer number. */  end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask;  if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {/* Enough room? */    /*     ** Caution: the write order is important here... don't set up the    ** ownership rights until all the other information is in place.    */    if (end < entry) {                         /* wrapped buffer */      len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ;      memcpy_toio(lp->tx_memcpy[entry], skb->data, len);      memcpy_toio(lp->tx_memcpy[0], skb->data + len, skb->len - len);    } else {                                   /* linear buffer */      memcpy_toio(lp->tx_memcpy[entry], skb->data, skb->len);    }    /* set up the buffer descriptors */    len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;    for (i = entry; i != end; i = (++i) & lp->txRingMask) {                                               /* clean out flags */      writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);      writew(0x0000, &lp->tx_ring[i].misc);    /* clears other error flags */      writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */      len -= TX_BUFF_SZ;    }                                               /* clean out flags */    writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base);    writew(0x0000, &lp->tx_ring[end].misc);    /* clears other error flags */    writew(-len, &lp->tx_ring[end].length);    /* packet length in last buff */                                               /* start of packet */    writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base);                                               /* end of packet */    writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base);    for (i=end; i!=entry; --i) {                                               /* ownership of packet */      writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base);      if (i == 0) i=lp->txRingMask+1;    }       writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base);     lp->tx_new = (++end) & lp->txRingMask;     /* update current pointers */  } else {    status = -1;  }  return status;}/*** Look for a particular board name in the EISA configuration space*/__initfunc(static intEISA_signature(char *name, s32 eisa_id)){  u_int i;  const char *signatures[] = DEPCA_SIGNATURE;  char ManCode[DEPCA_STRLEN];  union {    s32 ID;    char Id[4];  } Eisa;  int status = 0;  *name = '\0';  Eisa.ID = inl(eisa_id);  ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40);  ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40);  ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30);  ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30);  ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30);  ManCode[5]='\0';  for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) {    if (strstr(ManCode, signatures[i]) != NULL) {      strcpy(name,ManCode);      status = 1;    }  }  return status;}static void depca_dbg_open(struct device *dev){  struct depca_private *lp = (struct depca_private *)dev->priv;  u_long ioaddr = dev->base_addr;  struct depca_init *p = (struct depca_init *)lp->sh_mem;  int i;   if (depca_debug > 1){    /* Copy the shadow init_block to shared memory */    memcpy_toio((char *)lp->sh_mem,&lp->init_block,sizeof(struct depca_init));    printk("%s: depca open with irq %d\n",dev->name,dev->irq);    printk("Descriptor head addresses:\n");    printk("\t0x%lx  0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring);    printk("Descriptor addresses:\nRX: ");    for (i=0;i<lp->rxRingMask;i++){      if (i < 3) {	printk("0x%8.8lx ", (long) &lp->rx_ring[i].base);      }    }    printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base);    printk("TX: ");    for (i=0;i<lp->txRingMask;i++){      if (i < 3) {	printk("0x%8.8lx ", (long) &lp->tx_ring[i].base);      }    }    printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base);    printk("\nDescriptor buffers:\nRX: ");    for (i=0;i<lp->rxRingMask;i++){      if (i < 3) {	printk("0x%8.8x  ", readl(&lp->rx_ring[i].base));      }    }    printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base));    printk("TX: ");    for (i=0;i<lp->txRingMask;i++){      if (i < 3) {	printk("0x%8.8x  ", readl(&lp->tx_ring[i].base));      }    }    printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));    printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem);    printk("\tmode: 0x%4.4x\n",readw(&p->mode));    printk("\tphysical address: ");    for (i=0;i<ETH_ALEN-1;i++){      printk("%2.2x:",(u_char)readb(&p->phys_addr[i]));    }    printk("%2.2x\n",(u_char)readb(&p->phys_addr[i]));    printk("\tmulticast hash table: ");    for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){      printk("%2.2x:",(u_char)readb(&p->mcast_table[i]));    }    printk("%2.2x\n",(u_char)readb(&p->mcast_table[i]));    printk("\trx_ring at: 0x%8.8x\n",readl(&p->rx_ring));    printk("\ttx_ring at: 0x%8.8x\n",readl(&p->tx_ring));    printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs);    printk("Ring size:\nRX: %d  Log2(rxRingMask): 0x%8.8x\n", 	   (int)lp->rxRingMask + 1, 	   lp->rx_rlen);    printk("TX: %d  Log2(txRingMask): 0x%8.8x\n", 	   (int)lp->txRingMask + 1, 	   lp->tx_rlen);    outw(CSR2,DEPCA_ADDR);    printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA));    outw(CSR1,DEPCA_ADDR);    printk("%4.4x\n",inw(DEPCA_DATA));    outw(CSR3,DEPCA_ADDR);    printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA));  }  return;}/*** Perform IOCTL call functions here. Some are privileged operations and the** effective uid is checked in those cases.** All multicast IOCTLs will not work here and are for testing purposes only.*/static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd){  struct depca_private *lp = (struct depca_private *)dev->priv;  struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data;  int i, status = 0;  u_long ioaddr = dev->base_addr;  union {    u8  addr[(HASH_TABLE_LEN * ETH_ALEN)];    u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1];    u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2];  } tmp;  switch(ioc->cmd) {  case DEPCA_GET_HWADDR:             /* Get the hardware address */    for (i=0; i<ETH_ALEN; i++) {      tmp.addr[i] = dev->dev_addr[i];    }    ioc->len = ETH_ALEN;    if (verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len)) return -EFAULT;    copy_to_user(ioc->data, tmp.addr, ioc->len);    break;  case DEPCA_SET_HWADDR:             /* Set the hardware address */    if (!capable(CAP_NET_ADMIN)) return -EPERM;    if (verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN)) return -EFAULT;    copy_from_user(tmp.addr,ioc->data,ETH_ALEN);    for (i=0; i<ETH_ALEN; i++) {      dev->dev_addr[i] = tmp.addr[i];    }    while(dev->tbusy) barrier();        /* Stop ring access */    test_and_set_bit(0, (void*)&dev->tbusy);    while(lp->tx_old != lp->tx_new);    /* Wait for the ring to empty */    STOP_DEPCA;                         /* Temporarily stop the depca.  */    depca_init_ring(dev);               /* Initialize the descriptor rings */    LoadCSRs(dev);                      /* Reload CSR3 */    InitRestartDepca(dev);              /* Resume normal operation. */    dev->tbusy = 0;                     /* Unlock the TX ring */    break;  case DEPCA_SET_PROM:               /* Set Promiscuous Mode */    if (!capable(CAP_NET_ADMIN)) return -EPERM;    while(dev->tbusy) barrier();        /* Stop ring access */    test_and_set_bit(0, (void*)&dev->tbusy);    while(lp->tx_old != lp->tx_new);    /* Wait for the ring to empty */    STOP_DEPCA;                         /* Temporarily stop the depca.  */    depca_init_ring(dev);               /* Initialize the descriptor rings */    lp->init_block.mode |= PROM;        /* Set promiscuous mode */    LoadCSRs(dev);                      /* Reload CSR3 */    InitRestartDepca(dev);              /* Resume normal operation. */    dev->tbusy = 0;                     /* Unlock the TX ring */    break;  case DEPCA_CLR_PROM:               /* Clear Promiscuous Mode */    if (!capable(CAP_NET_ADMIN)) return -EPERM;    while(dev->tbusy) barrier();        /* Stop ring access */    test_and_set_bit(0, (void*)&dev->tbusy);    while(lp->tx_old != lp->tx_new);    /* Wait for the ring to empty */    STOP_DEPCA;                         /* Temporarily stop the depca.  */    depca_init_ring(dev);               /* Initialize the descriptor rings */    lp->init_block.mode &= ~PROM;       /* Clear promiscuous mode */    LoadCSRs(dev);                      /* Reload CSR3 */    InitRestartDepca(dev);              /* Resume normal operation. */    dev->tbusy = 0;                     /* Unlock the TX ring */    break;  case DEPCA_SAY_BOO:                /* Say "Boo!" to the kernel log file */    printk("%s: Boo!\n", dev->name);    break;  case DEPCA_GET_MCA:                /* Get the multicast address table */    ioc->len = (HASH_TABLE_LEN >> 3);    if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;    copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len);     break;  case DEPCA_SET_MCA:                /* Set a multicast address */    if (!capable(CAP_NET_ADMIN)) return -EPERM;    if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len)) return -EFAULT;    copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);    set_multicast_list(dev);    break;  case DEPCA_CLR_MCA:                /* Clear all multicast addresses */    if (!capable(CAP_NET_ADMIN)) return -EPERM;    set_multicast_list(dev);    break;  case DEPCA_MCA_EN:                 /* Enable pass all multicast addressing */    if (!capable(CAP_NET_ADMIN)) return -EPERM;      set_multicast_list(dev);    break;  case DEPCA_GET_STATS:              /* Get the driver statistics */    cli();    ioc->len = sizeof(lp->pktStats);    if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) {	status = -EFAULT;    } else {	copy_to_user(ioc->data, &lp->pktStats, ioc->len);     }    sti();    break;  case DEPCA_CLR_STATS:              /* Zero out the driver statistics */    if (!capable(CAP_NET_ADMIN)) return -EPERM;    cli();    memset(&lp->pktStats, 0, sizeof(lp->pktStats));    sti();    break;  case DEPCA_GET_REG:                /* Get the DEPCA Registers */    i=0;    tmp.sval[i++] = inw(DEPCA_NICSR);    outw(CSR0, DEPCA_ADDR);              /* status register */    tmp.sval[i++] = inw(DEPCA_DATA);    memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init));    ioc->len = i+sizeof(struct depca_init);    if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;    copy_to_user(ioc->data, tmp.addr, ioc->len);    break;  default:    return -EOPNOTSUPP;  }  return status;}#ifdef MODULEstatic char devicename[9] = {0,};static struct device thisDepca = {  devicename,  /* device name is inserted by /linux/drivers/net/net_init.c */  0, 0, 0, 0,  0x200, 7,    /* I/O address, IRQ */  0, 0, 0, NULL, depca_pro

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -