/* ia_lnxatm.c */ /* This module provides the glue that binds the device independent */ /* atm code to the IA 5515 device driver. */ /* Copyright (c) 2000 James M. Westall, Dept of Computer Science, * Clemson University, Clemson SC 29634 USA * * Copyright (c) 1996 Robert Geist and James Westall * Clemson University Dept. of Computer Science * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ia_defs.h" #if LINUX_VERSION_CODE < 0x20182 #define schedule_timeout(a) { current->timeout = (a); schedule(); } #endif /* Here is where we remember vcc locations... */ /* Index is vci........ */ #define LC_COUNT 128 #define LC_BITS 7 static struct atm_vcc *vcctab[LC_COUNT]; static int initflag = 1; /**/ /* Fetch routine */ long ia5515_fetch( struct atm_vcc *vcc, int offset) { } static int pushes; void ia5515_getvcc( int lcndx, /* LC index into vcc table. */ struct atm_vcc **vccad) /* Return vcc address here. */ { #ifdef DBG_ATM printk("IA5515: lookup request for LC %d gives vcc %x \n", lcndx, vcctab[lcndx]); #endif *vccad = vcctab[lcndx]; #if 0 if (vccad != 0) pushes += 1; if (pushes % 1000 == 0) printk("pushes = %d \n", pushes); #endif } /**/ /* Open routine */ int ia5515_open( struct atm_vcc *vcc, /* vcc structure from driver */ short vpi, /* vpi... better be 0! */ int vci) /* vci... better be < LC_COUNT */ { ia_softc_t *softc; int rc; int lcnum; int lcndx; long flags; #ifdef DBG_ATM printk("ia5515_open: Got an open for vpi %d and vci %d \n", vpi, vci); printk("ia5515_open: VCC->VCI is %d \n", vcc->vci); printk("ia5515_open: VCC address is %08x \n", vcc); printk("ia5515_open: push address is %08x \n", vcc->push); printk("ia5515_open: pop address is %08x \n", vcc->pop); #endif softc = vcc->dev->dev_data; spin_lock_irqsave(&softc->xramlock, flags); #if LINUX_VERSION_CODE >= 0x20312 clear_bit(ATM_VF_READY,&vcc->flags); #else vcc->flags &= ~ATM_VF_SCRX; #endif rc = atm_find_ci(vcc, &vpi, &vci); #ifdef DBG_ATM printk("ia5515_open: find ci returned %d \n", rc); #endif if (rc) { spin_unlock_irqrestore(&softc->xramlock, flags); return(rc); } vcc->vpi = vpi; vcc->vci = vci; #if LINUX_VERSION_CODE >= 0x20312 if ((vci != ATM_VPI_UNSPEC) && (vpi != ATM_VCI_UNSPEC)) set_bit(ATM_VF_ADDR, &vcc->flags); #else if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC) vcc->flags |= ATM_VF_ADDR; #endif lcndx = vci; /* If lc was obtained... bind vcc to lc in vcc table */ vcctab[lcndx] = vcc; vcc->vci = vci; vcc->vpi = vpi; #if LINUX_VERSION_CODE >= 0x20312 set_bit(ATM_VF_ADDR, &vcc->flags); set_bit(ATM_VF_READY, &vcc->flags); atomic_set(&vcc->rx_inuse, 0); atomic_set(&vcc->tx_inuse, 0); #else vcc->flags |= ATM_VF_READY; vcc->flags |= ATM_VF_ADDR; vcc->rx_quota = 1024 * 1024; atomic_set(&vcc->rx_inuse, 0); atomic_set(&vcc->tx_inuse, 0); #endif spin_unlock_irqrestore(&softc->xramlock, flags); MOD_INC_USE_COUNT; return(0); } void ia5515_close( struct atm_vcc *vcc) /* vcc structure of conn being closed */ { ia_softc_t *softc; int rc; unsigned int flags; int tx, rx, c; #ifdef DBG_ATM printk("ia5515_close: Got a close for vpi %d and vci %d \n", vcc->vpi, vcc->vci); #endif softc = vcc->dev->dev_data; c = 25; while( (tx = atomic_read(&vcc->tx_inuse)) != 0) { printk("IA5515: Trying to close but tx inuse is %d \n", tx); if( --c <= 0) { printk("ia5515_close: Warning: 5 sec. timeout !\n"); break; } current->state = TASK_INTERRUPTIBLE; schedule_timeout(20); } spin_lock_irqsave(&softc->xramlock, flags); vcctab[vcc->vci] = 0; #if LINUX_VERSION_CODE >= 0x20312 clear_bit(ATM_VF_READY, &vcc->flags); clear_bit(ATM_VF_ADDR, &vcc->flags); #else vcc->flags &= ~ATM_VF_READY; vcc->flags &= ~ATM_VF_ADDR; #endif MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&softc->xramlock, flags); } int ia5515_ioctl( struct atm_dev *dev, /* ATM dev structure registered */ unsigned int cmd, /* Command word. */ void *arg) /* Actually a parm pointer. */ { return(0); } int ia5515_getsockopt( struct atm_vcc *vcc, /* Vcc structure identifying LC */ int level, /* Usual get/set sockopt parms */ int optname, void *optval, int optlen) { return -EINVAL; } int ia5515_setsockopt( struct atm_vcc *vcc, /* Vcc structure identifying LC */ int level, /* Usual get/set sockopt parms */ int optname, void *optval, int optlen) { printk("Setsockopt wuz called \n"); return(0); } int ia5515_send( struct atm_vcc *vcc, struct sk_buff *skb) { ia_softc_t *softc; int rc; int len; #if 0 int *loc; loc = &vcc; rc = atomic_read(&vcc->rx_inuse); printk("ia5515_send: rx_inuse at entry %d \n", rc); printk("ia5515_send: VCC address is %08x \n", vcc); printk("ia5515_send: SKB address is %08x \n", skb); printk("ia5515_send: Requested send of %d bytes \n", skb->len); /*printk("ia5515_send: Data was %s: \n", skb->data); */ printk("ia5515_send: tx_inuse %d: \n", vcc->tx_inuse.counter); printk("ia5515_send: rx_inuse %d: \n", vcc->rx_inuse.counter); printk("ia5515_send: Location was %08x \n", skb->data); printk("ia5515_send: VCI is %d \n", vcc->vci); printk("ia5515_send: Calling send5skb... my caller was %x \n", *(loc - 1)); #endif softc = vcc->dev->dev_data; #ifdef DBG_ATM printk("ia5515_send: softc is at %x \n", softc); #endif rc = ia_send5skb(softc, vcc, skb); return(0); #ifdef DBG_ATM len = atomic_read(&vcc->tx_inuse); printk("ia5515_send: tx_inuse at exit %d \n", rc); #endif /*printk("Send exiting with xram lock %x \n", softc->xramlock); */ return(0); } static struct atmdev_ops atm_ops = { NULL, /* dev_close */ ia5515_open, /* open */ ia5515_close, /* close */ ia5515_ioctl, /* ioctl */ ia5515_getsockopt, /* getsockopt */ ia5515_setsockopt, /* setsockopt */ ia5515_send, /* send */ NULL, /* sg_send */ NULL, /* poll */ NULL, /* send_oam */ NULL, /* phy_put */ NULL, /* phy_get */ NULL, /* feedback */ NULL, /* change_qos */ NULL, /* free_rx_skb */ }; /**/ /* Attempt to register the IA 5515 device */ int ia5515_register( ia_softc_t *softc, /* Pointer to device dependent descriptor */ int intf) { int i; int flags = 0; softc->atmdev = atm_dev_register("ia5515", &atm_ops, intf, flags); if (softc->atmdev == NULL) { printk("ia5515: Can't register device \n"); return -EIO; } printk("ia5515_register: Free callback at %x \n", atm_ops.free_rx_skb); printk("ia5515_register: ESI is: "); for (i = 0; i < ESI_LEN; i++) { softc->atmdev->esi[i] = softc->mac_addr[i]; printk("%02x.", softc->atmdev->esi[i]); } printk("\n"); softc->atmdev->dev_data = softc; softc->atmdev->ci_range.vpi_bits = 0; softc->atmdev->ci_range.vci_bits = LC_BITS; printk("ATM dev block at %8x \n", softc->atmdev); return(0); } void ia5515_deregister( ia_softc_t *softc) /* Pointer to device dependent descriptor */ { atm_dev_deregister(softc->atmdev); }