📄 zatm.c
字号:
while (!(zin(GSR) & uPD98401_INT_IND)); zout(uPD98401_GMR_ONE /*uPD98401_BURST4*/,GMR); last = MAX_CRAM_SIZE; for (i = last-RAM_INCREMENT; i >= 0; i -= RAM_INCREMENT) { zpokel(zatm_dev,0x55555555,i); if (zpeekl(zatm_dev,i) != 0x55555555) last = i; else { zpokel(zatm_dev,0xAAAAAAAA,i); if (zpeekl(zatm_dev,i) != 0xAAAAAAAA) last = i; else zpokel(zatm_dev,i,i); } } for (i = 0; i < last; i += RAM_INCREMENT) if (zpeekl(zatm_dev,i) != i) break; zatm_dev->mem = i << 2; while (i) zpokel(zatm_dev,0,--i); /* reset again to rebuild memory pointers */ zout(0,SWR); while (!(zin(GSR) & uPD98401_INT_IND)); zout(uPD98401_GMR_ONE | uPD98401_BURST8 | uPD98401_BURST4 | uPD98401_BURST2 | uPD98401_GMR_PM | uPD98401_GMR_DR,GMR); /* TODO: should shrink allocation now */ printk("mem=%dkB,%s (",zatm_dev->mem >> 10,zatm_dev->copper ? "UTP" : "MMF"); for (i = 0; i < ESI_LEN; i++) printk("%02X%s",dev->esi[i],i == ESI_LEN-1 ? ")\n" : "-"); do { unsigned long flags; save_flags(flags); cli(); t0 = zpeekl(zatm_dev,uPD98401_TSR); udelay(10); t1 = zpeekl(zatm_dev,uPD98401_TSR); udelay(1010); t2 = zpeekl(zatm_dev,uPD98401_TSR); restore_flags(flags); } while (t0 > t1 || t1 > t2); /* loop if wrapping ... */ zatm_dev->khz = t2-2*t1+t0; printk(KERN_NOTICE DEV_LABEL "(itf %d): uPD98401 %d.%d at %d.%03d " "MHz\n",dev->number, (zin(VER) & uPD98401_MAJOR) >> uPD98401_MAJOR_SHIFT, zin(VER) & uPD98401_MINOR,zatm_dev->khz/1000,zatm_dev->khz % 1000);#ifdef CONFIG_ATM_ZATM_EXACT_TS zatm_clock_init(zatm_dev);#endif return uPD98402_init(dev);}static int __init zatm_start(struct atm_dev *dev){ struct zatm_dev *zatm_dev; unsigned long curr; int pools,vccs,rx; int error,i,ld; DPRINTK("zatm_start\n"); zatm_dev = ZATM_DEV(dev); zatm_dev->rx_map = zatm_dev->tx_map = NULL; for (i = 0; i < NR_MBX; i++) zatm_dev->mbx_start[i] = 0; if (request_irq(zatm_dev->irq,&zatm_int,SA_SHIRQ,DEV_LABEL,dev)) { printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n", dev->number,zatm_dev->irq); return -EAGAIN; } request_region(zatm_dev->base,uPD98401_PORTS,DEV_LABEL); /* define memory regions */ pools = NR_POOLS; if (NR_SHAPERS*SHAPER_SIZE > pools*POOL_SIZE) pools = NR_SHAPERS*SHAPER_SIZE/POOL_SIZE; vccs = (zatm_dev->mem-NR_SHAPERS*SHAPER_SIZE-pools*POOL_SIZE)/ (2*VC_SIZE+RX_SIZE); ld = -1; for (rx = 1; rx < vccs; rx <<= 1) ld++; dev->ci_range.vpi_bits = 0; /* @@@ no VPI for now */ dev->ci_range.vci_bits = ld; dev->link_rate = ATM_OC3_PCR; zatm_dev->chans = vccs; /* ??? */ curr = rx*RX_SIZE/4; DPRINTK("RX pool 0x%08lx\n",curr); zpokel(zatm_dev,curr,uPD98401_PMA); /* receive pool */ zatm_dev->pool_base = curr; curr += pools*POOL_SIZE/4; DPRINTK("Shapers 0x%08lx\n",curr); zpokel(zatm_dev,curr,uPD98401_SMA); /* shapers */ curr += NR_SHAPERS*SHAPER_SIZE/4; DPRINTK("Free 0x%08lx\n",curr); zpokel(zatm_dev,curr,uPD98401_TOS); /* free pool */ printk(KERN_INFO DEV_LABEL "(itf %d): %d shapers, %d pools, %d RX, " "%ld VCs\n",dev->number,NR_SHAPERS,pools,rx, (zatm_dev->mem-curr*4)/VC_SIZE); /* create mailboxes */ for (i = 0; i < NR_MBX; i++) if (mbx_entries[i]) { unsigned long here; here = (unsigned long) kmalloc(2*MBX_SIZE(i), GFP_KERNEL); if (!here) { error = -ENOMEM; goto out; } if ((here^(here+MBX_SIZE(i))) & ~0xffffUL)/* paranoia */ here = (here & ~0xffffUL)+0x10000; zatm_dev->mbx_start[i] = here; if ((here^virt_to_bus((void *) here)) & 0xffff) { printk(KERN_ERR DEV_LABEL "(itf %d): system " "bus incompatible with driver\n", dev->number); error = -ENODEV; goto out; } DPRINTK("mbx@0x%08lx-0x%08lx\n",here,here+MBX_SIZE(i)); zatm_dev->mbx_end[i] = (here+MBX_SIZE(i)) & 0xffff; zout(virt_to_bus((void *) here) >> 16,MSH(i)); zout(virt_to_bus((void *) here),MSL(i)); zout((here+MBX_SIZE(i)) & 0xffff,MBA(i)); zout(here & 0xffff,MTA(i)); zout(here & 0xffff,MWA(i)); } error = start_tx(dev); if (error) goto out; error = start_rx(dev); if (error) goto out; error = dev->phy->start(dev); if (error) goto out; zout(0xffffffff,IMR); /* enable interrupts */ /* enable TX & RX */ zout(zin(GMR) | uPD98401_GMR_SE | uPD98401_GMR_RE,GMR); return 0; out: for (i = 0; i < NR_MBX; i++) if (zatm_dev->mbx_start[i] != 0) kfree((void *) zatm_dev->mbx_start[i]); if (zatm_dev->rx_map != NULL) kfree(zatm_dev->rx_map); if (zatm_dev->tx_map != NULL) kfree(zatm_dev->tx_map); free_irq(zatm_dev->irq, dev); return error;}static void zatm_close(struct atm_vcc *vcc){ DPRINTK(">zatm_close\n"); if (!ZATM_VCC(vcc)) return; clear_bit(ATM_VF_READY,&vcc->flags); close_rx(vcc); EVENT("close_tx\n",0,0); close_tx(vcc); DPRINTK("zatm_close: done waiting\n"); /* deallocate memory */ kfree(ZATM_VCC(vcc)); ZATM_VCC(vcc) = NULL; clear_bit(ATM_VF_ADDR,&vcc->flags);}static int zatm_open(struct atm_vcc *vcc,short vpi,int vci){ struct zatm_dev *zatm_dev; struct zatm_vcc *zatm_vcc; int error; DPRINTK(">zatm_open\n"); zatm_dev = ZATM_DEV(vcc->dev); if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ZATM_VCC(vcc) = NULL; error = atm_find_ci(vcc,&vpi,&vci); if (error) return error; vcc->vpi = vpi; vcc->vci = vci; if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) set_bit(ATM_VF_ADDR,&vcc->flags); if (vcc->qos.aal != ATM_AAL5) return -EINVAL; /* @@@ AAL0 */ DPRINTK(DEV_LABEL "(itf %d): open %d.%d\n",vcc->dev->number,vcc->vpi, vcc->vci); if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) { zatm_vcc = kmalloc(sizeof(struct zatm_vcc),GFP_KERNEL); if (!zatm_vcc) { clear_bit(ATM_VF_ADDR,&vcc->flags); return -ENOMEM; } ZATM_VCC(vcc) = zatm_vcc; ZATM_VCC(vcc)->tx_chan = 0; /* for zatm_close after open_rx */ if ((error = open_rx_first(vcc))) { zatm_close(vcc); return error; } if ((error = open_tx_first(vcc))) { zatm_close(vcc); return error; } } if (vci == ATM_VPI_UNSPEC || vpi == ATM_VCI_UNSPEC) return 0; if ((error = open_rx_second(vcc))) { zatm_close(vcc); return error; } if ((error = open_tx_second(vcc))) { zatm_close(vcc); return error; } set_bit(ATM_VF_READY,&vcc->flags); return 0;}static int zatm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flags){ printk("Not yet implemented\n"); return -ENOSYS; /* @@@ */}static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg){ struct zatm_dev *zatm_dev; unsigned long flags; zatm_dev = ZATM_DEV(dev); switch (cmd) { case ZATM_GETPOOLZ: if (!capable(CAP_NET_ADMIN)) return -EPERM; /* fall through */ case ZATM_GETPOOL: { struct zatm_pool_info info; int pool; if (get_user(pool, &((struct zatm_pool_req *) arg)->pool_num)) return -EFAULT; if (pool < 0 || pool > ZATM_LAST_POOL) return -EINVAL; save_flags(flags); cli(); info = zatm_dev->pool_info[pool]; if (cmd == ZATM_GETPOOLZ) { zatm_dev->pool_info[pool].rqa_count = 0; zatm_dev->pool_info[pool].rqu_count = 0; } restore_flags(flags); return copy_to_user( &((struct zatm_pool_req *) arg)->info, &info,sizeof(info)) ? -EFAULT : 0; } case ZATM_SETPOOL: { struct zatm_pool_info info; int pool; if (!capable(CAP_NET_ADMIN)) return -EPERM; if (get_user(pool, &((struct zatm_pool_req *) arg)->pool_num)) return -EFAULT; if (pool < 0 || pool > ZATM_LAST_POOL) return -EINVAL; if (copy_from_user(&info, &((struct zatm_pool_req *) arg)->info, sizeof(info))) return -EFAULT; if (!info.low_water) info.low_water = zatm_dev-> pool_info[pool].low_water; if (!info.high_water) info.high_water = zatm_dev-> pool_info[pool].high_water; if (!info.next_thres) info.next_thres = zatm_dev-> pool_info[pool].next_thres; if (info.low_water >= info.high_water || info.low_water < 0) return -EINVAL; save_flags(flags); cli(); zatm_dev->pool_info[pool].low_water = info.low_water; zatm_dev->pool_info[pool].high_water = info.high_water; zatm_dev->pool_info[pool].next_thres = info.next_thres; restore_flags(flags); return 0; }#ifdef CONFIG_ATM_ZATM_EXACT_TS case ZATM_GETTHIST: { int i; struct zatm_t_hist hs[ZATM_TIMER_HISTORY_SIZE]; save_flags(flags); cli(); for (i = 0; i < ZATM_TIMER_HISTORY_SIZE; i++) hs[i] = zatm_dev->timer_history[ (zatm_dev->th_curr+i) & (ZATM_TIMER_HISTORY_SIZE-1)]; restore_flags(flags); return copy_to_user((struct zatm_t_hist *) arg, hs, sizeof(hs)) ? -EFAULT : 0; }#endif default: if (!dev->phy->ioctl) return -ENOIOCTLCMD; return dev->phy->ioctl(dev,cmd,arg); }}static int zatm_getsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen){ return -EINVAL;}static int zatm_setsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen){ return -EINVAL;}#if 0static int zatm_sg_send(struct atm_vcc *vcc,unsigned long start, unsigned long size){ return vcc->aal == ATM_AAL5; /* @@@ should check size and maybe alignment*/}#endifstatic int zatm_send(struct atm_vcc *vcc,struct sk_buff *skb){ int error; EVENT(">zatm_send 0x%lx\n",(unsigned long) skb,0); if (!ZATM_VCC(vcc)->tx_chan || !test_bit(ATM_VF_READY,&vcc->flags)) { if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); return -EINVAL; } if (!skb) { printk(KERN_CRIT "!skb in zatm_send ?\n"); if (vcc->pop) vcc->pop(vcc,skb); return -EINVAL; } ATM_SKB(skb)->vcc = vcc; error = do_tx(skb); if (error != RING_BUSY) return error; skb_queue_tail(&ZATM_VCC(vcc)->backlog,skb); return 0;}static void zatm_phy_put(struct atm_dev *dev,unsigned char value, unsigned long addr){ struct zatm_dev *zatm_dev; zatm_dev = ZATM_DEV(dev); zwait; zout(value,CER); zout(uPD98401_IND_ACC | uPD98401_IA_B0 | (uPD98401_IA_TGT_PHY << uPD98401_IA_TGT_SHIFT) | addr,CMR);}static unsigned char zatm_phy_get(struct atm_dev *dev,unsigned long addr){ struct zatm_dev *zatm_dev; zatm_dev = ZATM_DEV(dev); zwait; zout(uPD98401_IND_ACC | uPD98401_IA_B0 | uPD98401_IA_RW | (uPD98401_IA_TGT_PHY << uPD98401_IA_TGT_SHIFT) | addr,CMR); zwait; return zin(CER) & 0xff;}static const struct atmdev_ops ops = { open: zatm_open, close: zatm_close, ioctl: zatm_ioctl, getsockopt: zatm_getsockopt, setsockopt: zatm_setsockopt, send: zatm_send, /*zatm_sg_send*/ phy_put: zatm_phy_put, phy_get: zatm_phy_get, feedback: zatm_feedback, change_qos: zatm_change_qos,};int __init zatm_detect(void){ struct atm_dev *dev; struct zatm_dev *zatm_dev; int devs,type; zatm_dev = (struct zatm_dev *) kmalloc(sizeof(struct zatm_dev), GFP_KERNEL); if (!zatm_dev) return -ENOMEM; devs = 0; for (type = 0; type < 2; type++) { struct pci_dev *pci_dev; pci_dev = NULL; while ((pci_dev = pci_find_device(PCI_VENDOR_ID_ZEITNET,type ? PCI_DEVICE_ID_ZEITNET_1225 : PCI_DEVICE_ID_ZEITNET_1221, pci_dev))) { if (pci_enable_device(pci_dev)) break; dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL); if (!dev) break; zatm_dev->pci_dev = pci_dev; ZATM_DEV(dev) = zatm_dev; zatm_dev->copper = type; if (zatm_init(dev) || zatm_start(dev)) { atm_dev_deregister(dev); break; } zatm_dev->more = zatm_boards; zatm_boards = dev; devs++; zatm_dev = (struct zatm_dev *) kmalloc(sizeof(struct zatm_dev),GFP_KERNEL); if (!zatm_dev) { printk(KERN_EMERG "zatm.c: memory shortage\n"); return devs; } } } kfree(zatm_dev); return devs;}#ifdef MODULE MODULE_LICENSE("GPL");int init_module(void){ if (!zatm_detect()) { printk(KERN_ERR DEV_LABEL ": no adapter found\n"); return -ENXIO; } MOD_INC_USE_COUNT; return 0;} void cleanup_module(void){ /* * Well, there's no way to get rid of the driver yet, so we don't * have to clean up, right ? :-) */} #endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -