xref: /OK3568_Linux_fs/kernel/drivers/atm/idt77252.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*******************************************************************
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * Copyright (c) 2000 ATecoM GmbH
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * The author may be reached at ecd@atecom.com.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * This program is free software; you can redistribute  it and/or modify it
8*4882a593Smuzhiyun  * under  the terms of  the GNU General  Public License as published by the
9*4882a593Smuzhiyun  * Free Software Foundation;  either version 2 of the  License, or (at your
10*4882a593Smuzhiyun  * option) any later version.
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
13*4882a593Smuzhiyun  * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
14*4882a593Smuzhiyun  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
15*4882a593Smuzhiyun  * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
16*4882a593Smuzhiyun  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17*4882a593Smuzhiyun  * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
18*4882a593Smuzhiyun  * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19*4882a593Smuzhiyun  * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
20*4882a593Smuzhiyun  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21*4882a593Smuzhiyun  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * You should have received a copy of the  GNU General Public License along
24*4882a593Smuzhiyun  * with this program; if not, write  to the Free Software Foundation, Inc.,
25*4882a593Smuzhiyun  * 675 Mass Ave, Cambridge, MA 02139, USA.
26*4882a593Smuzhiyun  *
27*4882a593Smuzhiyun  *******************************************************************/
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <linux/module.h>
30*4882a593Smuzhiyun #include <linux/pci.h>
31*4882a593Smuzhiyun #include <linux/poison.h>
32*4882a593Smuzhiyun #include <linux/skbuff.h>
33*4882a593Smuzhiyun #include <linux/kernel.h>
34*4882a593Smuzhiyun #include <linux/vmalloc.h>
35*4882a593Smuzhiyun #include <linux/netdevice.h>
36*4882a593Smuzhiyun #include <linux/atmdev.h>
37*4882a593Smuzhiyun #include <linux/atm.h>
38*4882a593Smuzhiyun #include <linux/delay.h>
39*4882a593Smuzhiyun #include <linux/init.h>
40*4882a593Smuzhiyun #include <linux/interrupt.h>
41*4882a593Smuzhiyun #include <linux/bitops.h>
42*4882a593Smuzhiyun #include <linux/wait.h>
43*4882a593Smuzhiyun #include <linux/jiffies.h>
44*4882a593Smuzhiyun #include <linux/mutex.h>
45*4882a593Smuzhiyun #include <linux/slab.h>
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #include <asm/io.h>
48*4882a593Smuzhiyun #include <linux/uaccess.h>
49*4882a593Smuzhiyun #include <linux/atomic.h>
50*4882a593Smuzhiyun #include <asm/byteorder.h>
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_USE_SUNI
53*4882a593Smuzhiyun #include "suni.h"
54*4882a593Smuzhiyun #endif /* CONFIG_ATM_IDT77252_USE_SUNI */
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #include "idt77252.h"
58*4882a593Smuzhiyun #include "idt77252_tables.h"
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static unsigned int vpibits = 1;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #define ATM_IDT77252_SEND_IDLE 1
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun  * Debug HACKs.
68*4882a593Smuzhiyun  */
69*4882a593Smuzhiyun #define DEBUG_MODULE 1
70*4882a593Smuzhiyun #undef HAVE_EEPROM	/* does not work, yet. */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_DEBUG
73*4882a593Smuzhiyun static unsigned long debug = DBG_GENERAL;
74*4882a593Smuzhiyun #endif
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define SAR_RX_DELAY	(SAR_CFG_RXINT_NODELAY)
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun /*
81*4882a593Smuzhiyun  * SCQ Handling.
82*4882a593Smuzhiyun  */
83*4882a593Smuzhiyun static struct scq_info *alloc_scq(struct idt77252_dev *, int);
84*4882a593Smuzhiyun static void free_scq(struct idt77252_dev *, struct scq_info *);
85*4882a593Smuzhiyun static int queue_skb(struct idt77252_dev *, struct vc_map *,
86*4882a593Smuzhiyun 		     struct sk_buff *, int oam);
87*4882a593Smuzhiyun static void drain_scq(struct idt77252_dev *, struct vc_map *);
88*4882a593Smuzhiyun static unsigned long get_free_scd(struct idt77252_dev *, struct vc_map *);
89*4882a593Smuzhiyun static void fill_scd(struct idt77252_dev *, struct scq_info *, int);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun /*
92*4882a593Smuzhiyun  * FBQ Handling.
93*4882a593Smuzhiyun  */
94*4882a593Smuzhiyun static int push_rx_skb(struct idt77252_dev *,
95*4882a593Smuzhiyun 		       struct sk_buff *, int queue);
96*4882a593Smuzhiyun static void recycle_rx_skb(struct idt77252_dev *, struct sk_buff *);
97*4882a593Smuzhiyun static void flush_rx_pool(struct idt77252_dev *, struct rx_pool *);
98*4882a593Smuzhiyun static void recycle_rx_pool_skb(struct idt77252_dev *,
99*4882a593Smuzhiyun 				struct rx_pool *);
100*4882a593Smuzhiyun static void add_rx_skb(struct idt77252_dev *, int queue,
101*4882a593Smuzhiyun 		       unsigned int size, unsigned int count);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /*
104*4882a593Smuzhiyun  * RSQ Handling.
105*4882a593Smuzhiyun  */
106*4882a593Smuzhiyun static int init_rsq(struct idt77252_dev *);
107*4882a593Smuzhiyun static void deinit_rsq(struct idt77252_dev *);
108*4882a593Smuzhiyun static void idt77252_rx(struct idt77252_dev *);
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /*
111*4882a593Smuzhiyun  * TSQ handling.
112*4882a593Smuzhiyun  */
113*4882a593Smuzhiyun static int init_tsq(struct idt77252_dev *);
114*4882a593Smuzhiyun static void deinit_tsq(struct idt77252_dev *);
115*4882a593Smuzhiyun static void idt77252_tx(struct idt77252_dev *);
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun /*
119*4882a593Smuzhiyun  * ATM Interface.
120*4882a593Smuzhiyun  */
121*4882a593Smuzhiyun static void idt77252_dev_close(struct atm_dev *dev);
122*4882a593Smuzhiyun static int idt77252_open(struct atm_vcc *vcc);
123*4882a593Smuzhiyun static void idt77252_close(struct atm_vcc *vcc);
124*4882a593Smuzhiyun static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb);
125*4882a593Smuzhiyun static int idt77252_send_oam(struct atm_vcc *vcc, void *cell,
126*4882a593Smuzhiyun 			     int flags);
127*4882a593Smuzhiyun static void idt77252_phy_put(struct atm_dev *dev, unsigned char value,
128*4882a593Smuzhiyun 			     unsigned long addr);
129*4882a593Smuzhiyun static unsigned char idt77252_phy_get(struct atm_dev *dev, unsigned long addr);
130*4882a593Smuzhiyun static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos,
131*4882a593Smuzhiyun 			       int flags);
132*4882a593Smuzhiyun static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos,
133*4882a593Smuzhiyun 			      char *page);
134*4882a593Smuzhiyun static void idt77252_softint(struct work_struct *work);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun static const struct atmdev_ops idt77252_ops =
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	.dev_close	= idt77252_dev_close,
140*4882a593Smuzhiyun 	.open		= idt77252_open,
141*4882a593Smuzhiyun 	.close		= idt77252_close,
142*4882a593Smuzhiyun 	.send		= idt77252_send,
143*4882a593Smuzhiyun 	.send_oam	= idt77252_send_oam,
144*4882a593Smuzhiyun 	.phy_put	= idt77252_phy_put,
145*4882a593Smuzhiyun 	.phy_get	= idt77252_phy_get,
146*4882a593Smuzhiyun 	.change_qos	= idt77252_change_qos,
147*4882a593Smuzhiyun 	.proc_read	= idt77252_proc_read,
148*4882a593Smuzhiyun 	.owner		= THIS_MODULE
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun static struct idt77252_dev *idt77252_chain = NULL;
152*4882a593Smuzhiyun static unsigned int idt77252_sram_write_errors = 0;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun /*****************************************************************************/
155*4882a593Smuzhiyun /*                                                                           */
156*4882a593Smuzhiyun /* I/O and Utility Bus                                                       */
157*4882a593Smuzhiyun /*                                                                           */
158*4882a593Smuzhiyun /*****************************************************************************/
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun static void
waitfor_idle(struct idt77252_dev * card)161*4882a593Smuzhiyun waitfor_idle(struct idt77252_dev *card)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	u32 stat;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	stat = readl(SAR_REG_STAT);
166*4882a593Smuzhiyun 	while (stat & SAR_STAT_CMDBZ)
167*4882a593Smuzhiyun 		stat = readl(SAR_REG_STAT);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun static u32
read_sram(struct idt77252_dev * card,unsigned long addr)171*4882a593Smuzhiyun read_sram(struct idt77252_dev *card, unsigned long addr)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	unsigned long flags;
174*4882a593Smuzhiyun 	u32 value;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	spin_lock_irqsave(&card->cmd_lock, flags);
177*4882a593Smuzhiyun 	writel(SAR_CMD_READ_SRAM | (addr << 2), SAR_REG_CMD);
178*4882a593Smuzhiyun 	waitfor_idle(card);
179*4882a593Smuzhiyun 	value = readl(SAR_REG_DR0);
180*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->cmd_lock, flags);
181*4882a593Smuzhiyun 	return value;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static void
write_sram(struct idt77252_dev * card,unsigned long addr,u32 value)185*4882a593Smuzhiyun write_sram(struct idt77252_dev *card, unsigned long addr, u32 value)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	unsigned long flags;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	if ((idt77252_sram_write_errors == 0) &&
190*4882a593Smuzhiyun 	    (((addr > card->tst[0] + card->tst_size - 2) &&
191*4882a593Smuzhiyun 	      (addr < card->tst[0] + card->tst_size)) ||
192*4882a593Smuzhiyun 	     ((addr > card->tst[1] + card->tst_size - 2) &&
193*4882a593Smuzhiyun 	      (addr < card->tst[1] + card->tst_size)))) {
194*4882a593Smuzhiyun 		printk("%s: ERROR: TST JMP section at %08lx written: %08x\n",
195*4882a593Smuzhiyun 		       card->name, addr, value);
196*4882a593Smuzhiyun 	}
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	spin_lock_irqsave(&card->cmd_lock, flags);
199*4882a593Smuzhiyun 	writel(value, SAR_REG_DR0);
200*4882a593Smuzhiyun 	writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD);
201*4882a593Smuzhiyun 	waitfor_idle(card);
202*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->cmd_lock, flags);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun static u8
read_utility(void * dev,unsigned long ubus_addr)206*4882a593Smuzhiyun read_utility(void *dev, unsigned long ubus_addr)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	struct idt77252_dev *card = dev;
209*4882a593Smuzhiyun 	unsigned long flags;
210*4882a593Smuzhiyun 	u8 value;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	if (!card) {
213*4882a593Smuzhiyun 		printk("Error: No such device.\n");
214*4882a593Smuzhiyun 		return -1;
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	spin_lock_irqsave(&card->cmd_lock, flags);
218*4882a593Smuzhiyun 	writel(SAR_CMD_READ_UTILITY + ubus_addr, SAR_REG_CMD);
219*4882a593Smuzhiyun 	waitfor_idle(card);
220*4882a593Smuzhiyun 	value = readl(SAR_REG_DR0);
221*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->cmd_lock, flags);
222*4882a593Smuzhiyun 	return value;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun static void
write_utility(void * dev,unsigned long ubus_addr,u8 value)226*4882a593Smuzhiyun write_utility(void *dev, unsigned long ubus_addr, u8 value)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun 	struct idt77252_dev *card = dev;
229*4882a593Smuzhiyun 	unsigned long flags;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	if (!card) {
232*4882a593Smuzhiyun 		printk("Error: No such device.\n");
233*4882a593Smuzhiyun 		return;
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	spin_lock_irqsave(&card->cmd_lock, flags);
237*4882a593Smuzhiyun 	writel((u32) value, SAR_REG_DR0);
238*4882a593Smuzhiyun 	writel(SAR_CMD_WRITE_UTILITY + ubus_addr, SAR_REG_CMD);
239*4882a593Smuzhiyun 	waitfor_idle(card);
240*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->cmd_lock, flags);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun #ifdef HAVE_EEPROM
244*4882a593Smuzhiyun static u32 rdsrtab[] =
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	SAR_GP_EECS | SAR_GP_EESCLK,
247*4882a593Smuzhiyun 	0,
248*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
249*4882a593Smuzhiyun 	0,
250*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
251*4882a593Smuzhiyun 	0,
252*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
253*4882a593Smuzhiyun 	0,
254*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
255*4882a593Smuzhiyun 	0,
256*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
257*4882a593Smuzhiyun 	SAR_GP_EEDO,
258*4882a593Smuzhiyun 	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
259*4882a593Smuzhiyun 	0,
260*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
261*4882a593Smuzhiyun 	SAR_GP_EEDO,
262*4882a593Smuzhiyun 	SAR_GP_EESCLK | SAR_GP_EEDO	/* 1 */
263*4882a593Smuzhiyun };
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun static u32 wrentab[] =
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	SAR_GP_EECS | SAR_GP_EESCLK,
268*4882a593Smuzhiyun 	0,
269*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
270*4882a593Smuzhiyun 	0,
271*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
272*4882a593Smuzhiyun 	0,
273*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
274*4882a593Smuzhiyun 	0,
275*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
276*4882a593Smuzhiyun 	SAR_GP_EEDO,
277*4882a593Smuzhiyun 	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
278*4882a593Smuzhiyun 	SAR_GP_EEDO,
279*4882a593Smuzhiyun 	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
280*4882a593Smuzhiyun 	0,
281*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
282*4882a593Smuzhiyun 	0,
283*4882a593Smuzhiyun 	SAR_GP_EESCLK			/* 0 */
284*4882a593Smuzhiyun };
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun static u32 rdtab[] =
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	SAR_GP_EECS | SAR_GP_EESCLK,
289*4882a593Smuzhiyun 	0,
290*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
291*4882a593Smuzhiyun 	0,
292*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
293*4882a593Smuzhiyun 	0,
294*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
295*4882a593Smuzhiyun 	0,
296*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
297*4882a593Smuzhiyun 	0,
298*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
299*4882a593Smuzhiyun 	0,
300*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
301*4882a593Smuzhiyun 	SAR_GP_EEDO,
302*4882a593Smuzhiyun 	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
303*4882a593Smuzhiyun 	SAR_GP_EEDO,
304*4882a593Smuzhiyun 	SAR_GP_EESCLK | SAR_GP_EEDO	/* 1 */
305*4882a593Smuzhiyun };
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun static u32 wrtab[] =
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	SAR_GP_EECS | SAR_GP_EESCLK,
310*4882a593Smuzhiyun 	0,
311*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
312*4882a593Smuzhiyun 	0,
313*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
314*4882a593Smuzhiyun 	0,
315*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
316*4882a593Smuzhiyun 	0,
317*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
318*4882a593Smuzhiyun 	0,
319*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
320*4882a593Smuzhiyun 	0,
321*4882a593Smuzhiyun 	SAR_GP_EESCLK,			/* 0 */
322*4882a593Smuzhiyun 	SAR_GP_EEDO,
323*4882a593Smuzhiyun 	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
324*4882a593Smuzhiyun 	0,
325*4882a593Smuzhiyun 	SAR_GP_EESCLK			/* 0 */
326*4882a593Smuzhiyun };
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun static u32 clktab[] =
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun 	0,
331*4882a593Smuzhiyun 	SAR_GP_EESCLK,
332*4882a593Smuzhiyun 	0,
333*4882a593Smuzhiyun 	SAR_GP_EESCLK,
334*4882a593Smuzhiyun 	0,
335*4882a593Smuzhiyun 	SAR_GP_EESCLK,
336*4882a593Smuzhiyun 	0,
337*4882a593Smuzhiyun 	SAR_GP_EESCLK,
338*4882a593Smuzhiyun 	0,
339*4882a593Smuzhiyun 	SAR_GP_EESCLK,
340*4882a593Smuzhiyun 	0,
341*4882a593Smuzhiyun 	SAR_GP_EESCLK,
342*4882a593Smuzhiyun 	0,
343*4882a593Smuzhiyun 	SAR_GP_EESCLK,
344*4882a593Smuzhiyun 	0,
345*4882a593Smuzhiyun 	SAR_GP_EESCLK,
346*4882a593Smuzhiyun 	0
347*4882a593Smuzhiyun };
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun static u32
idt77252_read_gp(struct idt77252_dev * card)350*4882a593Smuzhiyun idt77252_read_gp(struct idt77252_dev *card)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun 	u32 gp;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	gp = readl(SAR_REG_GP);
355*4882a593Smuzhiyun #if 0
356*4882a593Smuzhiyun 	printk("RD: %s\n", gp & SAR_GP_EEDI ? "1" : "0");
357*4882a593Smuzhiyun #endif
358*4882a593Smuzhiyun 	return gp;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun static void
idt77252_write_gp(struct idt77252_dev * card,u32 value)362*4882a593Smuzhiyun idt77252_write_gp(struct idt77252_dev *card, u32 value)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun 	unsigned long flags;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun #if 0
367*4882a593Smuzhiyun 	printk("WR: %s %s %s\n", value & SAR_GP_EECS ? "   " : "/CS",
368*4882a593Smuzhiyun 	       value & SAR_GP_EESCLK ? "HIGH" : "LOW ",
369*4882a593Smuzhiyun 	       value & SAR_GP_EEDO   ? "1" : "0");
370*4882a593Smuzhiyun #endif
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	spin_lock_irqsave(&card->cmd_lock, flags);
373*4882a593Smuzhiyun 	waitfor_idle(card);
374*4882a593Smuzhiyun 	writel(value, SAR_REG_GP);
375*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->cmd_lock, flags);
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun static u8
idt77252_eeprom_read_status(struct idt77252_dev * card)379*4882a593Smuzhiyun idt77252_eeprom_read_status(struct idt77252_dev *card)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	u8 byte;
382*4882a593Smuzhiyun 	u32 gp;
383*4882a593Smuzhiyun 	int i, j;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
388*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | rdsrtab[i]);
389*4882a593Smuzhiyun 		udelay(5);
390*4882a593Smuzhiyun 	}
391*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
392*4882a593Smuzhiyun 	udelay(5);
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	byte = 0;
395*4882a593Smuzhiyun 	for (i = 0, j = 0; i < 8; i++) {
396*4882a593Smuzhiyun 		byte <<= 1;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++]);
399*4882a593Smuzhiyun 		udelay(5);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 		byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++]);
404*4882a593Smuzhiyun 		udelay(5);
405*4882a593Smuzhiyun 	}
406*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
407*4882a593Smuzhiyun 	udelay(5);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	return byte;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun static u8
idt77252_eeprom_read_byte(struct idt77252_dev * card,u8 offset)413*4882a593Smuzhiyun idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun 	u8 byte;
416*4882a593Smuzhiyun 	u32 gp;
417*4882a593Smuzhiyun 	int i, j;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rdtab); i++) {
422*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | rdtab[i]);
423*4882a593Smuzhiyun 		udelay(5);
424*4882a593Smuzhiyun 	}
425*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
426*4882a593Smuzhiyun 	udelay(5);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	for (i = 0, j = 0; i < 8; i++) {
429*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++] |
430*4882a593Smuzhiyun 					(offset & 1 ? SAR_GP_EEDO : 0));
431*4882a593Smuzhiyun 		udelay(5);
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++] |
434*4882a593Smuzhiyun 					(offset & 1 ? SAR_GP_EEDO : 0));
435*4882a593Smuzhiyun 		udelay(5);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 		offset >>= 1;
438*4882a593Smuzhiyun 	}
439*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
440*4882a593Smuzhiyun 	udelay(5);
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	byte = 0;
443*4882a593Smuzhiyun 	for (i = 0, j = 0; i < 8; i++) {
444*4882a593Smuzhiyun 		byte <<= 1;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++]);
447*4882a593Smuzhiyun 		udelay(5);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 		byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++]);
452*4882a593Smuzhiyun 		udelay(5);
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
455*4882a593Smuzhiyun 	udelay(5);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	return byte;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun static void
idt77252_eeprom_write_byte(struct idt77252_dev * card,u8 offset,u8 data)461*4882a593Smuzhiyun idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun 	u32 gp;
464*4882a593Smuzhiyun 	int i, j;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(wrentab); i++) {
469*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | wrentab[i]);
470*4882a593Smuzhiyun 		udelay(5);
471*4882a593Smuzhiyun 	}
472*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
473*4882a593Smuzhiyun 	udelay(5);
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(wrtab); i++) {
476*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | wrtab[i]);
477*4882a593Smuzhiyun 		udelay(5);
478*4882a593Smuzhiyun 	}
479*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
480*4882a593Smuzhiyun 	udelay(5);
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	for (i = 0, j = 0; i < 8; i++) {
483*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++] |
484*4882a593Smuzhiyun 					(offset & 1 ? SAR_GP_EEDO : 0));
485*4882a593Smuzhiyun 		udelay(5);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++] |
488*4882a593Smuzhiyun 					(offset & 1 ? SAR_GP_EEDO : 0));
489*4882a593Smuzhiyun 		udelay(5);
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 		offset >>= 1;
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
494*4882a593Smuzhiyun 	udelay(5);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	for (i = 0, j = 0; i < 8; i++) {
497*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++] |
498*4882a593Smuzhiyun 					(data & 1 ? SAR_GP_EEDO : 0));
499*4882a593Smuzhiyun 		udelay(5);
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 		idt77252_write_gp(card, gp | clktab[j++] |
502*4882a593Smuzhiyun 					(data & 1 ? SAR_GP_EEDO : 0));
503*4882a593Smuzhiyun 		udelay(5);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 		data >>= 1;
506*4882a593Smuzhiyun 	}
507*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
508*4882a593Smuzhiyun 	udelay(5);
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun static void
idt77252_eeprom_init(struct idt77252_dev * card)512*4882a593Smuzhiyun idt77252_eeprom_init(struct idt77252_dev *card)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	u32 gp;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
519*4882a593Smuzhiyun 	udelay(5);
520*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
521*4882a593Smuzhiyun 	udelay(5);
522*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
523*4882a593Smuzhiyun 	udelay(5);
524*4882a593Smuzhiyun 	idt77252_write_gp(card, gp | SAR_GP_EECS);
525*4882a593Smuzhiyun 	udelay(5);
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun #endif /* HAVE_EEPROM */
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_DEBUG
531*4882a593Smuzhiyun static void
dump_tct(struct idt77252_dev * card,int index)532*4882a593Smuzhiyun dump_tct(struct idt77252_dev *card, int index)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	unsigned long tct;
535*4882a593Smuzhiyun 	int i;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	tct = (unsigned long) (card->tct_base + index * SAR_SRAM_TCT_SIZE);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	printk("%s: TCT %x:", card->name, index);
540*4882a593Smuzhiyun 	for (i = 0; i < 8; i++) {
541*4882a593Smuzhiyun 		printk(" %08x", read_sram(card, tct + i));
542*4882a593Smuzhiyun 	}
543*4882a593Smuzhiyun 	printk("\n");
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun static void
idt77252_tx_dump(struct idt77252_dev * card)547*4882a593Smuzhiyun idt77252_tx_dump(struct idt77252_dev *card)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct atm_vcc *vcc;
550*4882a593Smuzhiyun 	struct vc_map *vc;
551*4882a593Smuzhiyun 	int i;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	printk("%s\n", __func__);
554*4882a593Smuzhiyun 	for (i = 0; i < card->tct_size; i++) {
555*4882a593Smuzhiyun 		vc = card->vcs[i];
556*4882a593Smuzhiyun 		if (!vc)
557*4882a593Smuzhiyun 			continue;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 		vcc = NULL;
560*4882a593Smuzhiyun 		if (vc->rx_vcc)
561*4882a593Smuzhiyun 			vcc = vc->rx_vcc;
562*4882a593Smuzhiyun 		else if (vc->tx_vcc)
563*4882a593Smuzhiyun 			vcc = vc->tx_vcc;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 		if (!vcc)
566*4882a593Smuzhiyun 			continue;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 		printk("%s: Connection %d:\n", card->name, vc->index);
569*4882a593Smuzhiyun 		dump_tct(card, vc->index);
570*4882a593Smuzhiyun 	}
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun #endif
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun /*****************************************************************************/
576*4882a593Smuzhiyun /*                                                                           */
577*4882a593Smuzhiyun /* SCQ Handling                                                              */
578*4882a593Smuzhiyun /*                                                                           */
579*4882a593Smuzhiyun /*****************************************************************************/
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun static int
sb_pool_add(struct idt77252_dev * card,struct sk_buff * skb,int queue)582*4882a593Smuzhiyun sb_pool_add(struct idt77252_dev *card, struct sk_buff *skb, int queue)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct sb_pool *pool = &card->sbpool[queue];
585*4882a593Smuzhiyun 	int index;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	index = pool->index;
588*4882a593Smuzhiyun 	while (pool->skb[index]) {
589*4882a593Smuzhiyun 		index = (index + 1) & FBQ_MASK;
590*4882a593Smuzhiyun 		if (index == pool->index)
591*4882a593Smuzhiyun 			return -ENOBUFS;
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	pool->skb[index] = skb;
595*4882a593Smuzhiyun 	IDT77252_PRV_POOL(skb) = POOL_HANDLE(queue, index);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	pool->index = (index + 1) & FBQ_MASK;
598*4882a593Smuzhiyun 	return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun static void
sb_pool_remove(struct idt77252_dev * card,struct sk_buff * skb)602*4882a593Smuzhiyun sb_pool_remove(struct idt77252_dev *card, struct sk_buff *skb)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun 	unsigned int queue, index;
605*4882a593Smuzhiyun 	u32 handle;
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	handle = IDT77252_PRV_POOL(skb);
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	queue = POOL_QUEUE(handle);
610*4882a593Smuzhiyun 	if (queue > 3)
611*4882a593Smuzhiyun 		return;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	index = POOL_INDEX(handle);
614*4882a593Smuzhiyun 	if (index > FBQ_SIZE - 1)
615*4882a593Smuzhiyun 		return;
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun 	card->sbpool[queue].skb[index] = NULL;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun static struct sk_buff *
sb_pool_skb(struct idt77252_dev * card,u32 handle)621*4882a593Smuzhiyun sb_pool_skb(struct idt77252_dev *card, u32 handle)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	unsigned int queue, index;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	queue = POOL_QUEUE(handle);
626*4882a593Smuzhiyun 	if (queue > 3)
627*4882a593Smuzhiyun 		return NULL;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	index = POOL_INDEX(handle);
630*4882a593Smuzhiyun 	if (index > FBQ_SIZE - 1)
631*4882a593Smuzhiyun 		return NULL;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	return card->sbpool[queue].skb[index];
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun static struct scq_info *
alloc_scq(struct idt77252_dev * card,int class)637*4882a593Smuzhiyun alloc_scq(struct idt77252_dev *card, int class)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 	struct scq_info *scq;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL);
642*4882a593Smuzhiyun 	if (!scq)
643*4882a593Smuzhiyun 		return NULL;
644*4882a593Smuzhiyun 	scq->base = dma_alloc_coherent(&card->pcidev->dev, SCQ_SIZE,
645*4882a593Smuzhiyun 				       &scq->paddr, GFP_KERNEL);
646*4882a593Smuzhiyun 	if (scq->base == NULL) {
647*4882a593Smuzhiyun 		kfree(scq);
648*4882a593Smuzhiyun 		return NULL;
649*4882a593Smuzhiyun 	}
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	scq->next = scq->base;
652*4882a593Smuzhiyun 	scq->last = scq->base + (SCQ_ENTRIES - 1);
653*4882a593Smuzhiyun 	atomic_set(&scq->used, 0);
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	spin_lock_init(&scq->lock);
656*4882a593Smuzhiyun 	spin_lock_init(&scq->skblock);
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	skb_queue_head_init(&scq->transmit);
659*4882a593Smuzhiyun 	skb_queue_head_init(&scq->pending);
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	TXPRINTK("idt77252: SCQ: base 0x%p, next 0x%p, last 0x%p, paddr %08llx\n",
662*4882a593Smuzhiyun 		 scq->base, scq->next, scq->last, (unsigned long long)scq->paddr);
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	return scq;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun static void
free_scq(struct idt77252_dev * card,struct scq_info * scq)668*4882a593Smuzhiyun free_scq(struct idt77252_dev *card, struct scq_info *scq)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	struct sk_buff *skb;
671*4882a593Smuzhiyun 	struct atm_vcc *vcc;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	dma_free_coherent(&card->pcidev->dev, SCQ_SIZE,
674*4882a593Smuzhiyun 			  scq->base, scq->paddr);
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	while ((skb = skb_dequeue(&scq->transmit))) {
677*4882a593Smuzhiyun 		dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
678*4882a593Smuzhiyun 				 skb->len, DMA_TO_DEVICE);
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 		vcc = ATM_SKB(skb)->vcc;
681*4882a593Smuzhiyun 		if (vcc->pop)
682*4882a593Smuzhiyun 			vcc->pop(vcc, skb);
683*4882a593Smuzhiyun 		else
684*4882a593Smuzhiyun 			dev_kfree_skb(skb);
685*4882a593Smuzhiyun 	}
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	while ((skb = skb_dequeue(&scq->pending))) {
688*4882a593Smuzhiyun 		dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
689*4882a593Smuzhiyun 				 skb->len, DMA_TO_DEVICE);
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 		vcc = ATM_SKB(skb)->vcc;
692*4882a593Smuzhiyun 		if (vcc->pop)
693*4882a593Smuzhiyun 			vcc->pop(vcc, skb);
694*4882a593Smuzhiyun 		else
695*4882a593Smuzhiyun 			dev_kfree_skb(skb);
696*4882a593Smuzhiyun 	}
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	kfree(scq);
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun static int
push_on_scq(struct idt77252_dev * card,struct vc_map * vc,struct sk_buff * skb)703*4882a593Smuzhiyun push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun 	struct scq_info *scq = vc->scq;
706*4882a593Smuzhiyun 	unsigned long flags;
707*4882a593Smuzhiyun 	struct scqe *tbd;
708*4882a593Smuzhiyun 	int entries;
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	TXPRINTK("%s: SCQ: next 0x%p\n", card->name, scq->next);
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	atomic_inc(&scq->used);
713*4882a593Smuzhiyun 	entries = atomic_read(&scq->used);
714*4882a593Smuzhiyun 	if (entries > (SCQ_ENTRIES - 1)) {
715*4882a593Smuzhiyun 		atomic_dec(&scq->used);
716*4882a593Smuzhiyun 		goto out;
717*4882a593Smuzhiyun 	}
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	skb_queue_tail(&scq->transmit, skb);
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	spin_lock_irqsave(&vc->lock, flags);
722*4882a593Smuzhiyun 	if (vc->estimator) {
723*4882a593Smuzhiyun 		struct atm_vcc *vcc = vc->tx_vcc;
724*4882a593Smuzhiyun 		struct sock *sk = sk_atm(vcc);
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 		vc->estimator->cells += (skb->len + 47) / 48;
727*4882a593Smuzhiyun 		if (refcount_read(&sk->sk_wmem_alloc) >
728*4882a593Smuzhiyun 		    (sk->sk_sndbuf >> 1)) {
729*4882a593Smuzhiyun 			u32 cps = vc->estimator->maxcps;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 			vc->estimator->cps = cps;
732*4882a593Smuzhiyun 			vc->estimator->avcps = cps << 5;
733*4882a593Smuzhiyun 			if (vc->lacr < vc->init_er) {
734*4882a593Smuzhiyun 				vc->lacr = vc->init_er;
735*4882a593Smuzhiyun 				writel(TCMDQ_LACR | (vc->lacr << 16) |
736*4882a593Smuzhiyun 				       vc->index, SAR_REG_TCMDQ);
737*4882a593Smuzhiyun 			}
738*4882a593Smuzhiyun 		}
739*4882a593Smuzhiyun 	}
740*4882a593Smuzhiyun 	spin_unlock_irqrestore(&vc->lock, flags);
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	tbd = &IDT77252_PRV_TBD(skb);
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	spin_lock_irqsave(&scq->lock, flags);
745*4882a593Smuzhiyun 	scq->next->word_1 = cpu_to_le32(tbd->word_1 |
746*4882a593Smuzhiyun 					SAR_TBD_TSIF | SAR_TBD_GTSI);
747*4882a593Smuzhiyun 	scq->next->word_2 = cpu_to_le32(tbd->word_2);
748*4882a593Smuzhiyun 	scq->next->word_3 = cpu_to_le32(tbd->word_3);
749*4882a593Smuzhiyun 	scq->next->word_4 = cpu_to_le32(tbd->word_4);
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	if (scq->next == scq->last)
752*4882a593Smuzhiyun 		scq->next = scq->base;
753*4882a593Smuzhiyun 	else
754*4882a593Smuzhiyun 		scq->next++;
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	write_sram(card, scq->scd,
757*4882a593Smuzhiyun 		   scq->paddr +
758*4882a593Smuzhiyun 		   (u32)((unsigned long)scq->next - (unsigned long)scq->base));
759*4882a593Smuzhiyun 	spin_unlock_irqrestore(&scq->lock, flags);
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	scq->trans_start = jiffies;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	if (test_and_clear_bit(VCF_IDLE, &vc->flags)) {
764*4882a593Smuzhiyun 		writel(TCMDQ_START_LACR | (vc->lacr << 16) | vc->index,
765*4882a593Smuzhiyun 		       SAR_REG_TCMDQ);
766*4882a593Smuzhiyun 	}
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	TXPRINTK("%d entries in SCQ used (push).\n", atomic_read(&scq->used));
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	XPRINTK("%s: SCQ (after push %2d) head = 0x%x, next = 0x%p.\n",
771*4882a593Smuzhiyun 		card->name, atomic_read(&scq->used),
772*4882a593Smuzhiyun 		read_sram(card, scq->scd + 1), scq->next);
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	return 0;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun out:
777*4882a593Smuzhiyun 	if (time_after(jiffies, scq->trans_start + HZ)) {
778*4882a593Smuzhiyun 		printk("%s: Error pushing TBD for %d.%d\n",
779*4882a593Smuzhiyun 		       card->name, vc->tx_vcc->vpi, vc->tx_vcc->vci);
780*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_DEBUG
781*4882a593Smuzhiyun 		idt77252_tx_dump(card);
782*4882a593Smuzhiyun #endif
783*4882a593Smuzhiyun 		scq->trans_start = jiffies;
784*4882a593Smuzhiyun 	}
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	return -ENOBUFS;
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun static void
drain_scq(struct idt77252_dev * card,struct vc_map * vc)791*4882a593Smuzhiyun drain_scq(struct idt77252_dev *card, struct vc_map *vc)
792*4882a593Smuzhiyun {
793*4882a593Smuzhiyun 	struct scq_info *scq = vc->scq;
794*4882a593Smuzhiyun 	struct sk_buff *skb;
795*4882a593Smuzhiyun 	struct atm_vcc *vcc;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	TXPRINTK("%s: SCQ (before drain %2d) next = 0x%p.\n",
798*4882a593Smuzhiyun 		 card->name, atomic_read(&scq->used), scq->next);
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	skb = skb_dequeue(&scq->transmit);
801*4882a593Smuzhiyun 	if (skb) {
802*4882a593Smuzhiyun 		TXPRINTK("%s: freeing skb at %p.\n", card->name, skb);
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 		dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
805*4882a593Smuzhiyun 				 skb->len, DMA_TO_DEVICE);
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 		vcc = ATM_SKB(skb)->vcc;
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun 		if (vcc->pop)
810*4882a593Smuzhiyun 			vcc->pop(vcc, skb);
811*4882a593Smuzhiyun 		else
812*4882a593Smuzhiyun 			dev_kfree_skb(skb);
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->tx);
815*4882a593Smuzhiyun 	}
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	atomic_dec(&scq->used);
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	spin_lock(&scq->skblock);
820*4882a593Smuzhiyun 	while ((skb = skb_dequeue(&scq->pending))) {
821*4882a593Smuzhiyun 		if (push_on_scq(card, vc, skb)) {
822*4882a593Smuzhiyun 			skb_queue_head(&vc->scq->pending, skb);
823*4882a593Smuzhiyun 			break;
824*4882a593Smuzhiyun 		}
825*4882a593Smuzhiyun 	}
826*4882a593Smuzhiyun 	spin_unlock(&scq->skblock);
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun static int
queue_skb(struct idt77252_dev * card,struct vc_map * vc,struct sk_buff * skb,int oam)830*4882a593Smuzhiyun queue_skb(struct idt77252_dev *card, struct vc_map *vc,
831*4882a593Smuzhiyun 	  struct sk_buff *skb, int oam)
832*4882a593Smuzhiyun {
833*4882a593Smuzhiyun 	struct atm_vcc *vcc;
834*4882a593Smuzhiyun 	struct scqe *tbd;
835*4882a593Smuzhiyun 	unsigned long flags;
836*4882a593Smuzhiyun 	int error;
837*4882a593Smuzhiyun 	int aal;
838*4882a593Smuzhiyun 	u32 word4;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	if (skb->len == 0) {
841*4882a593Smuzhiyun 		printk("%s: invalid skb->len (%d)\n", card->name, skb->len);
842*4882a593Smuzhiyun 		return -EINVAL;
843*4882a593Smuzhiyun 	}
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun 	TXPRINTK("%s: Sending %d bytes of data.\n",
846*4882a593Smuzhiyun 		 card->name, skb->len);
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	tbd = &IDT77252_PRV_TBD(skb);
849*4882a593Smuzhiyun 	vcc = ATM_SKB(skb)->vcc;
850*4882a593Smuzhiyun 	word4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
851*4882a593Smuzhiyun 			(skb->data[2] <<  8) | (skb->data[3] <<  0);
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	IDT77252_PRV_PADDR(skb) = dma_map_single(&card->pcidev->dev, skb->data,
854*4882a593Smuzhiyun 						 skb->len, DMA_TO_DEVICE);
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun 	error = -EINVAL;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	if (oam) {
859*4882a593Smuzhiyun 		if (skb->len != 52)
860*4882a593Smuzhiyun 			goto errout;
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 		tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU;
863*4882a593Smuzhiyun 		tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
864*4882a593Smuzhiyun 		tbd->word_3 = 0x00000000;
865*4882a593Smuzhiyun 		tbd->word_4 = word4;
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 		if (test_bit(VCF_RSV, &vc->flags))
868*4882a593Smuzhiyun 			vc = card->vcs[0];
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 		goto done;
871*4882a593Smuzhiyun 	}
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	if (test_bit(VCF_RSV, &vc->flags)) {
874*4882a593Smuzhiyun 		printk("%s: Trying to transmit on reserved VC\n", card->name);
875*4882a593Smuzhiyun 		goto errout;
876*4882a593Smuzhiyun 	}
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	aal = vcc->qos.aal;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	switch (aal) {
881*4882a593Smuzhiyun 	case ATM_AAL0:
882*4882a593Smuzhiyun 	case ATM_AAL34:
883*4882a593Smuzhiyun 		if (skb->len > 52)
884*4882a593Smuzhiyun 			goto errout;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 		if (aal == ATM_AAL0)
887*4882a593Smuzhiyun 			tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL0 |
888*4882a593Smuzhiyun 				      ATM_CELL_PAYLOAD;
889*4882a593Smuzhiyun 		else
890*4882a593Smuzhiyun 			tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL34 |
891*4882a593Smuzhiyun 				      ATM_CELL_PAYLOAD;
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun 		tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
894*4882a593Smuzhiyun 		tbd->word_3 = 0x00000000;
895*4882a593Smuzhiyun 		tbd->word_4 = word4;
896*4882a593Smuzhiyun 		break;
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun 	case ATM_AAL5:
899*4882a593Smuzhiyun 		tbd->word_1 = SAR_TBD_EPDU | SAR_TBD_AAL5 | skb->len;
900*4882a593Smuzhiyun 		tbd->word_2 = IDT77252_PRV_PADDR(skb);
901*4882a593Smuzhiyun 		tbd->word_3 = skb->len;
902*4882a593Smuzhiyun 		tbd->word_4 = (vcc->vpi << SAR_TBD_VPI_SHIFT) |
903*4882a593Smuzhiyun 			      (vcc->vci << SAR_TBD_VCI_SHIFT);
904*4882a593Smuzhiyun 		break;
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	case ATM_AAL1:
907*4882a593Smuzhiyun 	case ATM_AAL2:
908*4882a593Smuzhiyun 	default:
909*4882a593Smuzhiyun 		printk("%s: Traffic type not supported.\n", card->name);
910*4882a593Smuzhiyun 		error = -EPROTONOSUPPORT;
911*4882a593Smuzhiyun 		goto errout;
912*4882a593Smuzhiyun 	}
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun done:
915*4882a593Smuzhiyun 	spin_lock_irqsave(&vc->scq->skblock, flags);
916*4882a593Smuzhiyun 	skb_queue_tail(&vc->scq->pending, skb);
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	while ((skb = skb_dequeue(&vc->scq->pending))) {
919*4882a593Smuzhiyun 		if (push_on_scq(card, vc, skb)) {
920*4882a593Smuzhiyun 			skb_queue_head(&vc->scq->pending, skb);
921*4882a593Smuzhiyun 			break;
922*4882a593Smuzhiyun 		}
923*4882a593Smuzhiyun 	}
924*4882a593Smuzhiyun 	spin_unlock_irqrestore(&vc->scq->skblock, flags);
925*4882a593Smuzhiyun 
926*4882a593Smuzhiyun 	return 0;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun errout:
929*4882a593Smuzhiyun 	dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
930*4882a593Smuzhiyun 			 skb->len, DMA_TO_DEVICE);
931*4882a593Smuzhiyun 	return error;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun static unsigned long
get_free_scd(struct idt77252_dev * card,struct vc_map * vc)935*4882a593Smuzhiyun get_free_scd(struct idt77252_dev *card, struct vc_map *vc)
936*4882a593Smuzhiyun {
937*4882a593Smuzhiyun 	int i;
938*4882a593Smuzhiyun 
939*4882a593Smuzhiyun 	for (i = 0; i < card->scd_size; i++) {
940*4882a593Smuzhiyun 		if (!card->scd2vc[i]) {
941*4882a593Smuzhiyun 			card->scd2vc[i] = vc;
942*4882a593Smuzhiyun 			vc->scd_index = i;
943*4882a593Smuzhiyun 			return card->scd_base + i * SAR_SRAM_SCD_SIZE;
944*4882a593Smuzhiyun 		}
945*4882a593Smuzhiyun 	}
946*4882a593Smuzhiyun 	return 0;
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun static void
fill_scd(struct idt77252_dev * card,struct scq_info * scq,int class)950*4882a593Smuzhiyun fill_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
951*4882a593Smuzhiyun {
952*4882a593Smuzhiyun 	write_sram(card, scq->scd, scq->paddr);
953*4882a593Smuzhiyun 	write_sram(card, scq->scd + 1, 0x00000000);
954*4882a593Smuzhiyun 	write_sram(card, scq->scd + 2, 0xffffffff);
955*4882a593Smuzhiyun 	write_sram(card, scq->scd + 3, 0x00000000);
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun static void
clear_scd(struct idt77252_dev * card,struct scq_info * scq,int class)959*4882a593Smuzhiyun clear_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
960*4882a593Smuzhiyun {
961*4882a593Smuzhiyun 	return;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun /*****************************************************************************/
965*4882a593Smuzhiyun /*                                                                           */
966*4882a593Smuzhiyun /* RSQ Handling                                                              */
967*4882a593Smuzhiyun /*                                                                           */
968*4882a593Smuzhiyun /*****************************************************************************/
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun static int
init_rsq(struct idt77252_dev * card)971*4882a593Smuzhiyun init_rsq(struct idt77252_dev *card)
972*4882a593Smuzhiyun {
973*4882a593Smuzhiyun 	struct rsq_entry *rsqe;
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun 	card->rsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE,
976*4882a593Smuzhiyun 					    &card->rsq.paddr, GFP_KERNEL);
977*4882a593Smuzhiyun 	if (card->rsq.base == NULL) {
978*4882a593Smuzhiyun 		printk("%s: can't allocate RSQ.\n", card->name);
979*4882a593Smuzhiyun 		return -1;
980*4882a593Smuzhiyun 	}
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun 	card->rsq.last = card->rsq.base + RSQ_NUM_ENTRIES - 1;
983*4882a593Smuzhiyun 	card->rsq.next = card->rsq.last;
984*4882a593Smuzhiyun 	for (rsqe = card->rsq.base; rsqe <= card->rsq.last; rsqe++)
985*4882a593Smuzhiyun 		rsqe->word_4 = 0;
986*4882a593Smuzhiyun 
987*4882a593Smuzhiyun 	writel((unsigned long) card->rsq.last - (unsigned long) card->rsq.base,
988*4882a593Smuzhiyun 	       SAR_REG_RSQH);
989*4882a593Smuzhiyun 	writel(card->rsq.paddr, SAR_REG_RSQB);
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	IPRINTK("%s: RSQ base at 0x%lx (0x%x).\n", card->name,
992*4882a593Smuzhiyun 		(unsigned long) card->rsq.base,
993*4882a593Smuzhiyun 		readl(SAR_REG_RSQB));
994*4882a593Smuzhiyun 	IPRINTK("%s: RSQ head = 0x%x, base = 0x%x, tail = 0x%x.\n",
995*4882a593Smuzhiyun 		card->name,
996*4882a593Smuzhiyun 		readl(SAR_REG_RSQH),
997*4882a593Smuzhiyun 		readl(SAR_REG_RSQB),
998*4882a593Smuzhiyun 		readl(SAR_REG_RSQT));
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun 	return 0;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun static void
deinit_rsq(struct idt77252_dev * card)1004*4882a593Smuzhiyun deinit_rsq(struct idt77252_dev *card)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun 	dma_free_coherent(&card->pcidev->dev, RSQSIZE,
1007*4882a593Smuzhiyun 			  card->rsq.base, card->rsq.paddr);
1008*4882a593Smuzhiyun }
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun static void
dequeue_rx(struct idt77252_dev * card,struct rsq_entry * rsqe)1011*4882a593Smuzhiyun dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
1012*4882a593Smuzhiyun {
1013*4882a593Smuzhiyun 	struct atm_vcc *vcc;
1014*4882a593Smuzhiyun 	struct sk_buff *skb;
1015*4882a593Smuzhiyun 	struct rx_pool *rpp;
1016*4882a593Smuzhiyun 	struct vc_map *vc;
1017*4882a593Smuzhiyun 	u32 header, vpi, vci;
1018*4882a593Smuzhiyun 	u32 stat;
1019*4882a593Smuzhiyun 	int i;
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 	stat = le32_to_cpu(rsqe->word_4);
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun 	if (stat & SAR_RSQE_IDLE) {
1024*4882a593Smuzhiyun 		RXPRINTK("%s: message about inactive connection.\n",
1025*4882a593Smuzhiyun 			 card->name);
1026*4882a593Smuzhiyun 		return;
1027*4882a593Smuzhiyun 	}
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	skb = sb_pool_skb(card, le32_to_cpu(rsqe->word_2));
1030*4882a593Smuzhiyun 	if (skb == NULL) {
1031*4882a593Smuzhiyun 		printk("%s: NULL skb in %s, rsqe: %08x %08x %08x %08x\n",
1032*4882a593Smuzhiyun 		       card->name, __func__,
1033*4882a593Smuzhiyun 		       le32_to_cpu(rsqe->word_1), le32_to_cpu(rsqe->word_2),
1034*4882a593Smuzhiyun 		       le32_to_cpu(rsqe->word_3), le32_to_cpu(rsqe->word_4));
1035*4882a593Smuzhiyun 		return;
1036*4882a593Smuzhiyun 	}
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun 	header = le32_to_cpu(rsqe->word_1);
1039*4882a593Smuzhiyun 	vpi = (header >> 16) & 0x00ff;
1040*4882a593Smuzhiyun 	vci = (header >>  0) & 0xffff;
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 	RXPRINTK("%s: SDU for %d.%d received in buffer 0x%p (data 0x%p).\n",
1043*4882a593Smuzhiyun 		 card->name, vpi, vci, skb, skb->data);
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun 	if ((vpi >= (1 << card->vpibits)) || (vci != (vci & card->vcimask))) {
1046*4882a593Smuzhiyun 		printk("%s: SDU received for out-of-range vc %u.%u\n",
1047*4882a593Smuzhiyun 		       card->name, vpi, vci);
1048*4882a593Smuzhiyun 		recycle_rx_skb(card, skb);
1049*4882a593Smuzhiyun 		return;
1050*4882a593Smuzhiyun 	}
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 	vc = card->vcs[VPCI2VC(card, vpi, vci)];
1053*4882a593Smuzhiyun 	if (!vc || !test_bit(VCF_RX, &vc->flags)) {
1054*4882a593Smuzhiyun 		printk("%s: SDU received on non RX vc %u.%u\n",
1055*4882a593Smuzhiyun 		       card->name, vpi, vci);
1056*4882a593Smuzhiyun 		recycle_rx_skb(card, skb);
1057*4882a593Smuzhiyun 		return;
1058*4882a593Smuzhiyun 	}
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 	vcc = vc->rx_vcc;
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 	dma_sync_single_for_cpu(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
1063*4882a593Smuzhiyun 				skb_end_pointer(skb) - skb->data,
1064*4882a593Smuzhiyun 				DMA_FROM_DEVICE);
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun 	if ((vcc->qos.aal == ATM_AAL0) ||
1067*4882a593Smuzhiyun 	    (vcc->qos.aal == ATM_AAL34)) {
1068*4882a593Smuzhiyun 		struct sk_buff *sb;
1069*4882a593Smuzhiyun 		unsigned char *cell;
1070*4882a593Smuzhiyun 		u32 aal0;
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 		cell = skb->data;
1073*4882a593Smuzhiyun 		for (i = (stat & SAR_RSQE_CELLCNT); i; i--) {
1074*4882a593Smuzhiyun 			if ((sb = dev_alloc_skb(64)) == NULL) {
1075*4882a593Smuzhiyun 				printk("%s: Can't allocate buffers for aal0.\n",
1076*4882a593Smuzhiyun 				       card->name);
1077*4882a593Smuzhiyun 				atomic_add(i, &vcc->stats->rx_drop);
1078*4882a593Smuzhiyun 				break;
1079*4882a593Smuzhiyun 			}
1080*4882a593Smuzhiyun 			if (!atm_charge(vcc, sb->truesize)) {
1081*4882a593Smuzhiyun 				RXPRINTK("%s: atm_charge() dropped aal0 packets.\n",
1082*4882a593Smuzhiyun 					 card->name);
1083*4882a593Smuzhiyun 				atomic_add(i - 1, &vcc->stats->rx_drop);
1084*4882a593Smuzhiyun 				dev_kfree_skb(sb);
1085*4882a593Smuzhiyun 				break;
1086*4882a593Smuzhiyun 			}
1087*4882a593Smuzhiyun 			aal0 = (vpi << ATM_HDR_VPI_SHIFT) |
1088*4882a593Smuzhiyun 			       (vci << ATM_HDR_VCI_SHIFT);
1089*4882a593Smuzhiyun 			aal0 |= (stat & SAR_RSQE_EPDU) ? 0x00000002 : 0;
1090*4882a593Smuzhiyun 			aal0 |= (stat & SAR_RSQE_CLP)  ? 0x00000001 : 0;
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 			*((u32 *) sb->data) = aal0;
1093*4882a593Smuzhiyun 			skb_put(sb, sizeof(u32));
1094*4882a593Smuzhiyun 			skb_put_data(sb, cell, ATM_CELL_PAYLOAD);
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun 			ATM_SKB(sb)->vcc = vcc;
1097*4882a593Smuzhiyun 			__net_timestamp(sb);
1098*4882a593Smuzhiyun 			vcc->push(vcc, sb);
1099*4882a593Smuzhiyun 			atomic_inc(&vcc->stats->rx);
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun 			cell += ATM_CELL_PAYLOAD;
1102*4882a593Smuzhiyun 		}
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 		recycle_rx_skb(card, skb);
1105*4882a593Smuzhiyun 		return;
1106*4882a593Smuzhiyun 	}
1107*4882a593Smuzhiyun 	if (vcc->qos.aal != ATM_AAL5) {
1108*4882a593Smuzhiyun 		printk("%s: Unexpected AAL type in dequeue_rx(): %d.\n",
1109*4882a593Smuzhiyun 		       card->name, vcc->qos.aal);
1110*4882a593Smuzhiyun 		recycle_rx_skb(card, skb);
1111*4882a593Smuzhiyun 		return;
1112*4882a593Smuzhiyun 	}
1113*4882a593Smuzhiyun 	skb->len = (stat & SAR_RSQE_CELLCNT) * ATM_CELL_PAYLOAD;
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 	rpp = &vc->rcv.rx_pool;
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 	__skb_queue_tail(&rpp->queue, skb);
1118*4882a593Smuzhiyun 	rpp->len += skb->len;
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun 	if (stat & SAR_RSQE_EPDU) {
1121*4882a593Smuzhiyun 		unsigned char *l1l2;
1122*4882a593Smuzhiyun 		unsigned int len;
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun 		l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 		len = (l1l2[0] << 8) | l1l2[1];
1127*4882a593Smuzhiyun 		len = len ? len : 0x10000;
1128*4882a593Smuzhiyun 
1129*4882a593Smuzhiyun 		RXPRINTK("%s: PDU has %d bytes.\n", card->name, len);
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 		if ((len + 8 > rpp->len) || (len + (47 + 8) < rpp->len)) {
1132*4882a593Smuzhiyun 			RXPRINTK("%s: AAL5 PDU size mismatch: %d != %d. "
1133*4882a593Smuzhiyun 			         "(CDC: %08x)\n",
1134*4882a593Smuzhiyun 			         card->name, len, rpp->len, readl(SAR_REG_CDC));
1135*4882a593Smuzhiyun 			recycle_rx_pool_skb(card, rpp);
1136*4882a593Smuzhiyun 			atomic_inc(&vcc->stats->rx_err);
1137*4882a593Smuzhiyun 			return;
1138*4882a593Smuzhiyun 		}
1139*4882a593Smuzhiyun 		if (stat & SAR_RSQE_CRC) {
1140*4882a593Smuzhiyun 			RXPRINTK("%s: AAL5 CRC error.\n", card->name);
1141*4882a593Smuzhiyun 			recycle_rx_pool_skb(card, rpp);
1142*4882a593Smuzhiyun 			atomic_inc(&vcc->stats->rx_err);
1143*4882a593Smuzhiyun 			return;
1144*4882a593Smuzhiyun 		}
1145*4882a593Smuzhiyun 		if (skb_queue_len(&rpp->queue) > 1) {
1146*4882a593Smuzhiyun 			struct sk_buff *sb;
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun 			skb = dev_alloc_skb(rpp->len);
1149*4882a593Smuzhiyun 			if (!skb) {
1150*4882a593Smuzhiyun 				RXPRINTK("%s: Can't alloc RX skb.\n",
1151*4882a593Smuzhiyun 					 card->name);
1152*4882a593Smuzhiyun 				recycle_rx_pool_skb(card, rpp);
1153*4882a593Smuzhiyun 				atomic_inc(&vcc->stats->rx_err);
1154*4882a593Smuzhiyun 				return;
1155*4882a593Smuzhiyun 			}
1156*4882a593Smuzhiyun 			if (!atm_charge(vcc, skb->truesize)) {
1157*4882a593Smuzhiyun 				recycle_rx_pool_skb(card, rpp);
1158*4882a593Smuzhiyun 				dev_kfree_skb(skb);
1159*4882a593Smuzhiyun 				return;
1160*4882a593Smuzhiyun 			}
1161*4882a593Smuzhiyun 			skb_queue_walk(&rpp->queue, sb)
1162*4882a593Smuzhiyun 				skb_put_data(skb, sb->data, sb->len);
1163*4882a593Smuzhiyun 
1164*4882a593Smuzhiyun 			recycle_rx_pool_skb(card, rpp);
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 			skb_trim(skb, len);
1167*4882a593Smuzhiyun 			ATM_SKB(skb)->vcc = vcc;
1168*4882a593Smuzhiyun 			__net_timestamp(skb);
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 			vcc->push(vcc, skb);
1171*4882a593Smuzhiyun 			atomic_inc(&vcc->stats->rx);
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 			return;
1174*4882a593Smuzhiyun 		}
1175*4882a593Smuzhiyun 
1176*4882a593Smuzhiyun 		flush_rx_pool(card, rpp);
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun 		if (!atm_charge(vcc, skb->truesize)) {
1179*4882a593Smuzhiyun 			recycle_rx_skb(card, skb);
1180*4882a593Smuzhiyun 			return;
1181*4882a593Smuzhiyun 		}
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun 		dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
1184*4882a593Smuzhiyun 				 skb_end_pointer(skb) - skb->data,
1185*4882a593Smuzhiyun 				 DMA_FROM_DEVICE);
1186*4882a593Smuzhiyun 		sb_pool_remove(card, skb);
1187*4882a593Smuzhiyun 
1188*4882a593Smuzhiyun 		skb_trim(skb, len);
1189*4882a593Smuzhiyun 		ATM_SKB(skb)->vcc = vcc;
1190*4882a593Smuzhiyun 		__net_timestamp(skb);
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun 		vcc->push(vcc, skb);
1193*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->rx);
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 		if (skb->truesize > SAR_FB_SIZE_3)
1196*4882a593Smuzhiyun 			add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
1197*4882a593Smuzhiyun 		else if (skb->truesize > SAR_FB_SIZE_2)
1198*4882a593Smuzhiyun 			add_rx_skb(card, 2, SAR_FB_SIZE_2, 1);
1199*4882a593Smuzhiyun 		else if (skb->truesize > SAR_FB_SIZE_1)
1200*4882a593Smuzhiyun 			add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
1201*4882a593Smuzhiyun 		else
1202*4882a593Smuzhiyun 			add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
1203*4882a593Smuzhiyun 		return;
1204*4882a593Smuzhiyun 	}
1205*4882a593Smuzhiyun }
1206*4882a593Smuzhiyun 
1207*4882a593Smuzhiyun static void
idt77252_rx(struct idt77252_dev * card)1208*4882a593Smuzhiyun idt77252_rx(struct idt77252_dev *card)
1209*4882a593Smuzhiyun {
1210*4882a593Smuzhiyun 	struct rsq_entry *rsqe;
1211*4882a593Smuzhiyun 
1212*4882a593Smuzhiyun 	if (card->rsq.next == card->rsq.last)
1213*4882a593Smuzhiyun 		rsqe = card->rsq.base;
1214*4882a593Smuzhiyun 	else
1215*4882a593Smuzhiyun 		rsqe = card->rsq.next + 1;
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun 	if (!(le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID)) {
1218*4882a593Smuzhiyun 		RXPRINTK("%s: no entry in RSQ.\n", card->name);
1219*4882a593Smuzhiyun 		return;
1220*4882a593Smuzhiyun 	}
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	do {
1223*4882a593Smuzhiyun 		dequeue_rx(card, rsqe);
1224*4882a593Smuzhiyun 		rsqe->word_4 = 0;
1225*4882a593Smuzhiyun 		card->rsq.next = rsqe;
1226*4882a593Smuzhiyun 		if (card->rsq.next == card->rsq.last)
1227*4882a593Smuzhiyun 			rsqe = card->rsq.base;
1228*4882a593Smuzhiyun 		else
1229*4882a593Smuzhiyun 			rsqe = card->rsq.next + 1;
1230*4882a593Smuzhiyun 	} while (le32_to_cpu(rsqe->word_4) & SAR_RSQE_VALID);
1231*4882a593Smuzhiyun 
1232*4882a593Smuzhiyun 	writel((unsigned long) card->rsq.next - (unsigned long) card->rsq.base,
1233*4882a593Smuzhiyun 	       SAR_REG_RSQH);
1234*4882a593Smuzhiyun }
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun static void
idt77252_rx_raw(struct idt77252_dev * card)1237*4882a593Smuzhiyun idt77252_rx_raw(struct idt77252_dev *card)
1238*4882a593Smuzhiyun {
1239*4882a593Smuzhiyun 	struct sk_buff	*queue;
1240*4882a593Smuzhiyun 	u32		head, tail;
1241*4882a593Smuzhiyun 	struct atm_vcc	*vcc;
1242*4882a593Smuzhiyun 	struct vc_map	*vc;
1243*4882a593Smuzhiyun 	struct sk_buff	*sb;
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun 	if (card->raw_cell_head == NULL) {
1246*4882a593Smuzhiyun 		u32 handle = le32_to_cpu(*(card->raw_cell_hnd + 1));
1247*4882a593Smuzhiyun 		card->raw_cell_head = sb_pool_skb(card, handle);
1248*4882a593Smuzhiyun 	}
1249*4882a593Smuzhiyun 
1250*4882a593Smuzhiyun 	queue = card->raw_cell_head;
1251*4882a593Smuzhiyun 	if (!queue)
1252*4882a593Smuzhiyun 		return;
1253*4882a593Smuzhiyun 
1254*4882a593Smuzhiyun 	head = IDT77252_PRV_PADDR(queue) + (queue->data - queue->head - 16);
1255*4882a593Smuzhiyun 	tail = readl(SAR_REG_RAWCT);
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	dma_sync_single_for_cpu(&card->pcidev->dev, IDT77252_PRV_PADDR(queue),
1258*4882a593Smuzhiyun 				skb_end_offset(queue) - 16,
1259*4882a593Smuzhiyun 				DMA_FROM_DEVICE);
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun 	while (head != tail) {
1262*4882a593Smuzhiyun 		unsigned int vpi, vci;
1263*4882a593Smuzhiyun 		u32 header;
1264*4882a593Smuzhiyun 
1265*4882a593Smuzhiyun 		header = le32_to_cpu(*(u32 *) &queue->data[0]);
1266*4882a593Smuzhiyun 
1267*4882a593Smuzhiyun 		vpi = (header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;
1268*4882a593Smuzhiyun 		vci = (header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;
1269*4882a593Smuzhiyun 
1270*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_DEBUG
1271*4882a593Smuzhiyun 		if (debug & DBG_RAW_CELL) {
1272*4882a593Smuzhiyun 			int i;
1273*4882a593Smuzhiyun 
1274*4882a593Smuzhiyun 			printk("%s: raw cell %x.%02x.%04x.%x.%x\n",
1275*4882a593Smuzhiyun 			       card->name, (header >> 28) & 0x000f,
1276*4882a593Smuzhiyun 			       (header >> 20) & 0x00ff,
1277*4882a593Smuzhiyun 			       (header >>  4) & 0xffff,
1278*4882a593Smuzhiyun 			       (header >>  1) & 0x0007,
1279*4882a593Smuzhiyun 			       (header >>  0) & 0x0001);
1280*4882a593Smuzhiyun 			for (i = 16; i < 64; i++)
1281*4882a593Smuzhiyun 				printk(" %02x", queue->data[i]);
1282*4882a593Smuzhiyun 			printk("\n");
1283*4882a593Smuzhiyun 		}
1284*4882a593Smuzhiyun #endif
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 		if (vpi >= (1<<card->vpibits) || vci >= (1<<card->vcibits)) {
1287*4882a593Smuzhiyun 			RPRINTK("%s: SDU received for out-of-range vc %u.%u\n",
1288*4882a593Smuzhiyun 				card->name, vpi, vci);
1289*4882a593Smuzhiyun 			goto drop;
1290*4882a593Smuzhiyun 		}
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun 		vc = card->vcs[VPCI2VC(card, vpi, vci)];
1293*4882a593Smuzhiyun 		if (!vc || !test_bit(VCF_RX, &vc->flags)) {
1294*4882a593Smuzhiyun 			RPRINTK("%s: SDU received on non RX vc %u.%u\n",
1295*4882a593Smuzhiyun 				card->name, vpi, vci);
1296*4882a593Smuzhiyun 			goto drop;
1297*4882a593Smuzhiyun 		}
1298*4882a593Smuzhiyun 
1299*4882a593Smuzhiyun 		vcc = vc->rx_vcc;
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 		if (vcc->qos.aal != ATM_AAL0) {
1302*4882a593Smuzhiyun 			RPRINTK("%s: raw cell for non AAL0 vc %u.%u\n",
1303*4882a593Smuzhiyun 				card->name, vpi, vci);
1304*4882a593Smuzhiyun 			atomic_inc(&vcc->stats->rx_drop);
1305*4882a593Smuzhiyun 			goto drop;
1306*4882a593Smuzhiyun 		}
1307*4882a593Smuzhiyun 
1308*4882a593Smuzhiyun 		if ((sb = dev_alloc_skb(64)) == NULL) {
1309*4882a593Smuzhiyun 			printk("%s: Can't allocate buffers for AAL0.\n",
1310*4882a593Smuzhiyun 			       card->name);
1311*4882a593Smuzhiyun 			atomic_inc(&vcc->stats->rx_err);
1312*4882a593Smuzhiyun 			goto drop;
1313*4882a593Smuzhiyun 		}
1314*4882a593Smuzhiyun 
1315*4882a593Smuzhiyun 		if (!atm_charge(vcc, sb->truesize)) {
1316*4882a593Smuzhiyun 			RXPRINTK("%s: atm_charge() dropped AAL0 packets.\n",
1317*4882a593Smuzhiyun 				 card->name);
1318*4882a593Smuzhiyun 			dev_kfree_skb(sb);
1319*4882a593Smuzhiyun 			goto drop;
1320*4882a593Smuzhiyun 		}
1321*4882a593Smuzhiyun 
1322*4882a593Smuzhiyun 		*((u32 *) sb->data) = header;
1323*4882a593Smuzhiyun 		skb_put(sb, sizeof(u32));
1324*4882a593Smuzhiyun 		skb_put_data(sb, &(queue->data[16]), ATM_CELL_PAYLOAD);
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun 		ATM_SKB(sb)->vcc = vcc;
1327*4882a593Smuzhiyun 		__net_timestamp(sb);
1328*4882a593Smuzhiyun 		vcc->push(vcc, sb);
1329*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->rx);
1330*4882a593Smuzhiyun 
1331*4882a593Smuzhiyun drop:
1332*4882a593Smuzhiyun 		skb_pull(queue, 64);
1333*4882a593Smuzhiyun 
1334*4882a593Smuzhiyun 		head = IDT77252_PRV_PADDR(queue)
1335*4882a593Smuzhiyun 					+ (queue->data - queue->head - 16);
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 		if (queue->len < 128) {
1338*4882a593Smuzhiyun 			struct sk_buff *next;
1339*4882a593Smuzhiyun 			u32 handle;
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 			head = le32_to_cpu(*(u32 *) &queue->data[0]);
1342*4882a593Smuzhiyun 			handle = le32_to_cpu(*(u32 *) &queue->data[4]);
1343*4882a593Smuzhiyun 
1344*4882a593Smuzhiyun 			next = sb_pool_skb(card, handle);
1345*4882a593Smuzhiyun 			recycle_rx_skb(card, queue);
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 			if (next) {
1348*4882a593Smuzhiyun 				card->raw_cell_head = next;
1349*4882a593Smuzhiyun 				queue = card->raw_cell_head;
1350*4882a593Smuzhiyun 				dma_sync_single_for_cpu(&card->pcidev->dev,
1351*4882a593Smuzhiyun 							IDT77252_PRV_PADDR(queue),
1352*4882a593Smuzhiyun 							(skb_end_pointer(queue) -
1353*4882a593Smuzhiyun 							 queue->data),
1354*4882a593Smuzhiyun 							DMA_FROM_DEVICE);
1355*4882a593Smuzhiyun 			} else {
1356*4882a593Smuzhiyun 				card->raw_cell_head = NULL;
1357*4882a593Smuzhiyun 				printk("%s: raw cell queue overrun\n",
1358*4882a593Smuzhiyun 				       card->name);
1359*4882a593Smuzhiyun 				break;
1360*4882a593Smuzhiyun 			}
1361*4882a593Smuzhiyun 		}
1362*4882a593Smuzhiyun 	}
1363*4882a593Smuzhiyun }
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun 
1366*4882a593Smuzhiyun /*****************************************************************************/
1367*4882a593Smuzhiyun /*                                                                           */
1368*4882a593Smuzhiyun /* TSQ Handling                                                              */
1369*4882a593Smuzhiyun /*                                                                           */
1370*4882a593Smuzhiyun /*****************************************************************************/
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun static int
init_tsq(struct idt77252_dev * card)1373*4882a593Smuzhiyun init_tsq(struct idt77252_dev *card)
1374*4882a593Smuzhiyun {
1375*4882a593Smuzhiyun 	struct tsq_entry *tsqe;
1376*4882a593Smuzhiyun 
1377*4882a593Smuzhiyun 	card->tsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE,
1378*4882a593Smuzhiyun 					    &card->tsq.paddr, GFP_KERNEL);
1379*4882a593Smuzhiyun 	if (card->tsq.base == NULL) {
1380*4882a593Smuzhiyun 		printk("%s: can't allocate TSQ.\n", card->name);
1381*4882a593Smuzhiyun 		return -1;
1382*4882a593Smuzhiyun 	}
1383*4882a593Smuzhiyun 
1384*4882a593Smuzhiyun 	card->tsq.last = card->tsq.base + TSQ_NUM_ENTRIES - 1;
1385*4882a593Smuzhiyun 	card->tsq.next = card->tsq.last;
1386*4882a593Smuzhiyun 	for (tsqe = card->tsq.base; tsqe <= card->tsq.last; tsqe++)
1387*4882a593Smuzhiyun 		tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID);
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun 	writel(card->tsq.paddr, SAR_REG_TSQB);
1390*4882a593Smuzhiyun 	writel((unsigned long) card->tsq.next - (unsigned long) card->tsq.base,
1391*4882a593Smuzhiyun 	       SAR_REG_TSQH);
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun 	return 0;
1394*4882a593Smuzhiyun }
1395*4882a593Smuzhiyun 
1396*4882a593Smuzhiyun static void
deinit_tsq(struct idt77252_dev * card)1397*4882a593Smuzhiyun deinit_tsq(struct idt77252_dev *card)
1398*4882a593Smuzhiyun {
1399*4882a593Smuzhiyun 	dma_free_coherent(&card->pcidev->dev, TSQSIZE,
1400*4882a593Smuzhiyun 			  card->tsq.base, card->tsq.paddr);
1401*4882a593Smuzhiyun }
1402*4882a593Smuzhiyun 
1403*4882a593Smuzhiyun static void
idt77252_tx(struct idt77252_dev * card)1404*4882a593Smuzhiyun idt77252_tx(struct idt77252_dev *card)
1405*4882a593Smuzhiyun {
1406*4882a593Smuzhiyun 	struct tsq_entry *tsqe;
1407*4882a593Smuzhiyun 	unsigned int vpi, vci;
1408*4882a593Smuzhiyun 	struct vc_map *vc;
1409*4882a593Smuzhiyun 	u32 conn, stat;
1410*4882a593Smuzhiyun 
1411*4882a593Smuzhiyun 	if (card->tsq.next == card->tsq.last)
1412*4882a593Smuzhiyun 		tsqe = card->tsq.base;
1413*4882a593Smuzhiyun 	else
1414*4882a593Smuzhiyun 		tsqe = card->tsq.next + 1;
1415*4882a593Smuzhiyun 
1416*4882a593Smuzhiyun 	TXPRINTK("idt77252_tx: tsq  %p: base %p, next %p, last %p\n", tsqe,
1417*4882a593Smuzhiyun 		 card->tsq.base, card->tsq.next, card->tsq.last);
1418*4882a593Smuzhiyun 	TXPRINTK("idt77252_tx: tsqb %08x, tsqt %08x, tsqh %08x, \n",
1419*4882a593Smuzhiyun 		 readl(SAR_REG_TSQB),
1420*4882a593Smuzhiyun 		 readl(SAR_REG_TSQT),
1421*4882a593Smuzhiyun 		 readl(SAR_REG_TSQH));
1422*4882a593Smuzhiyun 
1423*4882a593Smuzhiyun 	stat = le32_to_cpu(tsqe->word_2);
1424*4882a593Smuzhiyun 
1425*4882a593Smuzhiyun 	if (stat & SAR_TSQE_INVALID)
1426*4882a593Smuzhiyun 		return;
1427*4882a593Smuzhiyun 
1428*4882a593Smuzhiyun 	do {
1429*4882a593Smuzhiyun 		TXPRINTK("tsqe: 0x%p [0x%08x 0x%08x]\n", tsqe,
1430*4882a593Smuzhiyun 			 le32_to_cpu(tsqe->word_1),
1431*4882a593Smuzhiyun 			 le32_to_cpu(tsqe->word_2));
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun 		switch (stat & SAR_TSQE_TYPE) {
1434*4882a593Smuzhiyun 		case SAR_TSQE_TYPE_TIMER:
1435*4882a593Smuzhiyun 			TXPRINTK("%s: Timer RollOver detected.\n", card->name);
1436*4882a593Smuzhiyun 			break;
1437*4882a593Smuzhiyun 
1438*4882a593Smuzhiyun 		case SAR_TSQE_TYPE_IDLE:
1439*4882a593Smuzhiyun 
1440*4882a593Smuzhiyun 			conn = le32_to_cpu(tsqe->word_1);
1441*4882a593Smuzhiyun 
1442*4882a593Smuzhiyun 			if (SAR_TSQE_TAG(stat) == 0x10) {
1443*4882a593Smuzhiyun #ifdef	NOTDEF
1444*4882a593Smuzhiyun 				printk("%s: Connection %d halted.\n",
1445*4882a593Smuzhiyun 				       card->name,
1446*4882a593Smuzhiyun 				       le32_to_cpu(tsqe->word_1) & 0x1fff);
1447*4882a593Smuzhiyun #endif
1448*4882a593Smuzhiyun 				break;
1449*4882a593Smuzhiyun 			}
1450*4882a593Smuzhiyun 
1451*4882a593Smuzhiyun 			vc = card->vcs[conn & 0x1fff];
1452*4882a593Smuzhiyun 			if (!vc) {
1453*4882a593Smuzhiyun 				printk("%s: could not find VC from conn %d\n",
1454*4882a593Smuzhiyun 				       card->name, conn & 0x1fff);
1455*4882a593Smuzhiyun 				break;
1456*4882a593Smuzhiyun 			}
1457*4882a593Smuzhiyun 
1458*4882a593Smuzhiyun 			printk("%s: Connection %d IDLE.\n",
1459*4882a593Smuzhiyun 			       card->name, vc->index);
1460*4882a593Smuzhiyun 
1461*4882a593Smuzhiyun 			set_bit(VCF_IDLE, &vc->flags);
1462*4882a593Smuzhiyun 			break;
1463*4882a593Smuzhiyun 
1464*4882a593Smuzhiyun 		case SAR_TSQE_TYPE_TSR:
1465*4882a593Smuzhiyun 
1466*4882a593Smuzhiyun 			conn = le32_to_cpu(tsqe->word_1);
1467*4882a593Smuzhiyun 
1468*4882a593Smuzhiyun 			vc = card->vcs[conn & 0x1fff];
1469*4882a593Smuzhiyun 			if (!vc) {
1470*4882a593Smuzhiyun 				printk("%s: no VC at index %d\n",
1471*4882a593Smuzhiyun 				       card->name,
1472*4882a593Smuzhiyun 				       le32_to_cpu(tsqe->word_1) & 0x1fff);
1473*4882a593Smuzhiyun 				break;
1474*4882a593Smuzhiyun 			}
1475*4882a593Smuzhiyun 
1476*4882a593Smuzhiyun 			drain_scq(card, vc);
1477*4882a593Smuzhiyun 			break;
1478*4882a593Smuzhiyun 
1479*4882a593Smuzhiyun 		case SAR_TSQE_TYPE_TBD_COMP:
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun 			conn = le32_to_cpu(tsqe->word_1);
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 			vpi = (conn >> SAR_TBD_VPI_SHIFT) & 0x00ff;
1484*4882a593Smuzhiyun 			vci = (conn >> SAR_TBD_VCI_SHIFT) & 0xffff;
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun 			if (vpi >= (1 << card->vpibits) ||
1487*4882a593Smuzhiyun 			    vci >= (1 << card->vcibits)) {
1488*4882a593Smuzhiyun 				printk("%s: TBD complete: "
1489*4882a593Smuzhiyun 				       "out of range VPI.VCI %u.%u\n",
1490*4882a593Smuzhiyun 				       card->name, vpi, vci);
1491*4882a593Smuzhiyun 				break;
1492*4882a593Smuzhiyun 			}
1493*4882a593Smuzhiyun 
1494*4882a593Smuzhiyun 			vc = card->vcs[VPCI2VC(card, vpi, vci)];
1495*4882a593Smuzhiyun 			if (!vc) {
1496*4882a593Smuzhiyun 				printk("%s: TBD complete: "
1497*4882a593Smuzhiyun 				       "no VC at VPI.VCI %u.%u\n",
1498*4882a593Smuzhiyun 				       card->name, vpi, vci);
1499*4882a593Smuzhiyun 				break;
1500*4882a593Smuzhiyun 			}
1501*4882a593Smuzhiyun 
1502*4882a593Smuzhiyun 			drain_scq(card, vc);
1503*4882a593Smuzhiyun 			break;
1504*4882a593Smuzhiyun 		}
1505*4882a593Smuzhiyun 
1506*4882a593Smuzhiyun 		tsqe->word_2 = cpu_to_le32(SAR_TSQE_INVALID);
1507*4882a593Smuzhiyun 
1508*4882a593Smuzhiyun 		card->tsq.next = tsqe;
1509*4882a593Smuzhiyun 		if (card->tsq.next == card->tsq.last)
1510*4882a593Smuzhiyun 			tsqe = card->tsq.base;
1511*4882a593Smuzhiyun 		else
1512*4882a593Smuzhiyun 			tsqe = card->tsq.next + 1;
1513*4882a593Smuzhiyun 
1514*4882a593Smuzhiyun 		TXPRINTK("tsqe: %p: base %p, next %p, last %p\n", tsqe,
1515*4882a593Smuzhiyun 			 card->tsq.base, card->tsq.next, card->tsq.last);
1516*4882a593Smuzhiyun 
1517*4882a593Smuzhiyun 		stat = le32_to_cpu(tsqe->word_2);
1518*4882a593Smuzhiyun 
1519*4882a593Smuzhiyun 	} while (!(stat & SAR_TSQE_INVALID));
1520*4882a593Smuzhiyun 
1521*4882a593Smuzhiyun 	writel((unsigned long)card->tsq.next - (unsigned long)card->tsq.base,
1522*4882a593Smuzhiyun 	       SAR_REG_TSQH);
1523*4882a593Smuzhiyun 
1524*4882a593Smuzhiyun 	XPRINTK("idt77252_tx-after writel%d: TSQ head = 0x%x, tail = 0x%x, next = 0x%p.\n",
1525*4882a593Smuzhiyun 		card->index, readl(SAR_REG_TSQH),
1526*4882a593Smuzhiyun 		readl(SAR_REG_TSQT), card->tsq.next);
1527*4882a593Smuzhiyun }
1528*4882a593Smuzhiyun 
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun static void
tst_timer(struct timer_list * t)1531*4882a593Smuzhiyun tst_timer(struct timer_list *t)
1532*4882a593Smuzhiyun {
1533*4882a593Smuzhiyun 	struct idt77252_dev *card = from_timer(card, t, tst_timer);
1534*4882a593Smuzhiyun 	unsigned long base, idle, jump;
1535*4882a593Smuzhiyun 	unsigned long flags;
1536*4882a593Smuzhiyun 	u32 pc;
1537*4882a593Smuzhiyun 	int e;
1538*4882a593Smuzhiyun 
1539*4882a593Smuzhiyun 	spin_lock_irqsave(&card->tst_lock, flags);
1540*4882a593Smuzhiyun 
1541*4882a593Smuzhiyun 	base = card->tst[card->tst_index];
1542*4882a593Smuzhiyun 	idle = card->tst[card->tst_index ^ 1];
1543*4882a593Smuzhiyun 
1544*4882a593Smuzhiyun 	if (test_bit(TST_SWITCH_WAIT, &card->tst_state)) {
1545*4882a593Smuzhiyun 		jump = base + card->tst_size - 2;
1546*4882a593Smuzhiyun 
1547*4882a593Smuzhiyun 		pc = readl(SAR_REG_NOW) >> 2;
1548*4882a593Smuzhiyun 		if ((pc ^ idle) & ~(card->tst_size - 1)) {
1549*4882a593Smuzhiyun 			mod_timer(&card->tst_timer, jiffies + 1);
1550*4882a593Smuzhiyun 			goto out;
1551*4882a593Smuzhiyun 		}
1552*4882a593Smuzhiyun 
1553*4882a593Smuzhiyun 		clear_bit(TST_SWITCH_WAIT, &card->tst_state);
1554*4882a593Smuzhiyun 
1555*4882a593Smuzhiyun 		card->tst_index ^= 1;
1556*4882a593Smuzhiyun 		write_sram(card, jump, TSTE_OPC_JMP | (base << 2));
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun 		base = card->tst[card->tst_index];
1559*4882a593Smuzhiyun 		idle = card->tst[card->tst_index ^ 1];
1560*4882a593Smuzhiyun 
1561*4882a593Smuzhiyun 		for (e = 0; e < card->tst_size - 2; e++) {
1562*4882a593Smuzhiyun 			if (card->soft_tst[e].tste & TSTE_PUSH_IDLE) {
1563*4882a593Smuzhiyun 				write_sram(card, idle + e,
1564*4882a593Smuzhiyun 					   card->soft_tst[e].tste & TSTE_MASK);
1565*4882a593Smuzhiyun 				card->soft_tst[e].tste &= ~(TSTE_PUSH_IDLE);
1566*4882a593Smuzhiyun 			}
1567*4882a593Smuzhiyun 		}
1568*4882a593Smuzhiyun 	}
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun 	if (test_and_clear_bit(TST_SWITCH_PENDING, &card->tst_state)) {
1571*4882a593Smuzhiyun 
1572*4882a593Smuzhiyun 		for (e = 0; e < card->tst_size - 2; e++) {
1573*4882a593Smuzhiyun 			if (card->soft_tst[e].tste & TSTE_PUSH_ACTIVE) {
1574*4882a593Smuzhiyun 				write_sram(card, idle + e,
1575*4882a593Smuzhiyun 					   card->soft_tst[e].tste & TSTE_MASK);
1576*4882a593Smuzhiyun 				card->soft_tst[e].tste &= ~(TSTE_PUSH_ACTIVE);
1577*4882a593Smuzhiyun 				card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
1578*4882a593Smuzhiyun 			}
1579*4882a593Smuzhiyun 		}
1580*4882a593Smuzhiyun 
1581*4882a593Smuzhiyun 		jump = base + card->tst_size - 2;
1582*4882a593Smuzhiyun 
1583*4882a593Smuzhiyun 		write_sram(card, jump, TSTE_OPC_NULL);
1584*4882a593Smuzhiyun 		set_bit(TST_SWITCH_WAIT, &card->tst_state);
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun 		mod_timer(&card->tst_timer, jiffies + 1);
1587*4882a593Smuzhiyun 	}
1588*4882a593Smuzhiyun 
1589*4882a593Smuzhiyun out:
1590*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->tst_lock, flags);
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun 
1593*4882a593Smuzhiyun static int
__fill_tst(struct idt77252_dev * card,struct vc_map * vc,int n,unsigned int opc)1594*4882a593Smuzhiyun __fill_tst(struct idt77252_dev *card, struct vc_map *vc,
1595*4882a593Smuzhiyun 	   int n, unsigned int opc)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun 	unsigned long cl, avail;
1598*4882a593Smuzhiyun 	unsigned long idle;
1599*4882a593Smuzhiyun 	int e, r;
1600*4882a593Smuzhiyun 	u32 data;
1601*4882a593Smuzhiyun 
1602*4882a593Smuzhiyun 	avail = card->tst_size - 2;
1603*4882a593Smuzhiyun 	for (e = 0; e < avail; e++) {
1604*4882a593Smuzhiyun 		if (card->soft_tst[e].vc == NULL)
1605*4882a593Smuzhiyun 			break;
1606*4882a593Smuzhiyun 	}
1607*4882a593Smuzhiyun 	if (e >= avail) {
1608*4882a593Smuzhiyun 		printk("%s: No free TST entries found\n", card->name);
1609*4882a593Smuzhiyun 		return -1;
1610*4882a593Smuzhiyun 	}
1611*4882a593Smuzhiyun 
1612*4882a593Smuzhiyun 	NPRINTK("%s: conn %d: first TST entry at %d.\n",
1613*4882a593Smuzhiyun 		card->name, vc ? vc->index : -1, e);
1614*4882a593Smuzhiyun 
1615*4882a593Smuzhiyun 	r = n;
1616*4882a593Smuzhiyun 	cl = avail;
1617*4882a593Smuzhiyun 	data = opc & TSTE_OPC_MASK;
1618*4882a593Smuzhiyun 	if (vc && (opc != TSTE_OPC_NULL))
1619*4882a593Smuzhiyun 		data = opc | vc->index;
1620*4882a593Smuzhiyun 
1621*4882a593Smuzhiyun 	idle = card->tst[card->tst_index ^ 1];
1622*4882a593Smuzhiyun 
1623*4882a593Smuzhiyun 	/*
1624*4882a593Smuzhiyun 	 * Fill Soft TST.
1625*4882a593Smuzhiyun 	 */
1626*4882a593Smuzhiyun 	while (r > 0) {
1627*4882a593Smuzhiyun 		if ((cl >= avail) && (card->soft_tst[e].vc == NULL)) {
1628*4882a593Smuzhiyun 			if (vc)
1629*4882a593Smuzhiyun 				card->soft_tst[e].vc = vc;
1630*4882a593Smuzhiyun 			else
1631*4882a593Smuzhiyun 				card->soft_tst[e].vc = (void *)-1;
1632*4882a593Smuzhiyun 
1633*4882a593Smuzhiyun 			card->soft_tst[e].tste = data;
1634*4882a593Smuzhiyun 			if (timer_pending(&card->tst_timer))
1635*4882a593Smuzhiyun 				card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE;
1636*4882a593Smuzhiyun 			else {
1637*4882a593Smuzhiyun 				write_sram(card, idle + e, data);
1638*4882a593Smuzhiyun 				card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
1639*4882a593Smuzhiyun 			}
1640*4882a593Smuzhiyun 
1641*4882a593Smuzhiyun 			cl -= card->tst_size;
1642*4882a593Smuzhiyun 			r--;
1643*4882a593Smuzhiyun 		}
1644*4882a593Smuzhiyun 
1645*4882a593Smuzhiyun 		if (++e == avail)
1646*4882a593Smuzhiyun 			e = 0;
1647*4882a593Smuzhiyun 		cl += n;
1648*4882a593Smuzhiyun 	}
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun 	return 0;
1651*4882a593Smuzhiyun }
1652*4882a593Smuzhiyun 
1653*4882a593Smuzhiyun static int
fill_tst(struct idt77252_dev * card,struct vc_map * vc,int n,unsigned int opc)1654*4882a593Smuzhiyun fill_tst(struct idt77252_dev *card, struct vc_map *vc, int n, unsigned int opc)
1655*4882a593Smuzhiyun {
1656*4882a593Smuzhiyun 	unsigned long flags;
1657*4882a593Smuzhiyun 	int res;
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun 	spin_lock_irqsave(&card->tst_lock, flags);
1660*4882a593Smuzhiyun 
1661*4882a593Smuzhiyun 	res = __fill_tst(card, vc, n, opc);
1662*4882a593Smuzhiyun 
1663*4882a593Smuzhiyun 	set_bit(TST_SWITCH_PENDING, &card->tst_state);
1664*4882a593Smuzhiyun 	if (!timer_pending(&card->tst_timer))
1665*4882a593Smuzhiyun 		mod_timer(&card->tst_timer, jiffies + 1);
1666*4882a593Smuzhiyun 
1667*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->tst_lock, flags);
1668*4882a593Smuzhiyun 	return res;
1669*4882a593Smuzhiyun }
1670*4882a593Smuzhiyun 
1671*4882a593Smuzhiyun static int
__clear_tst(struct idt77252_dev * card,struct vc_map * vc)1672*4882a593Smuzhiyun __clear_tst(struct idt77252_dev *card, struct vc_map *vc)
1673*4882a593Smuzhiyun {
1674*4882a593Smuzhiyun 	unsigned long idle;
1675*4882a593Smuzhiyun 	int e;
1676*4882a593Smuzhiyun 
1677*4882a593Smuzhiyun 	idle = card->tst[card->tst_index ^ 1];
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun 	for (e = 0; e < card->tst_size - 2; e++) {
1680*4882a593Smuzhiyun 		if (card->soft_tst[e].vc == vc) {
1681*4882a593Smuzhiyun 			card->soft_tst[e].vc = NULL;
1682*4882a593Smuzhiyun 
1683*4882a593Smuzhiyun 			card->soft_tst[e].tste = TSTE_OPC_VAR;
1684*4882a593Smuzhiyun 			if (timer_pending(&card->tst_timer))
1685*4882a593Smuzhiyun 				card->soft_tst[e].tste |= TSTE_PUSH_ACTIVE;
1686*4882a593Smuzhiyun 			else {
1687*4882a593Smuzhiyun 				write_sram(card, idle + e, TSTE_OPC_VAR);
1688*4882a593Smuzhiyun 				card->soft_tst[e].tste |= TSTE_PUSH_IDLE;
1689*4882a593Smuzhiyun 			}
1690*4882a593Smuzhiyun 		}
1691*4882a593Smuzhiyun 	}
1692*4882a593Smuzhiyun 
1693*4882a593Smuzhiyun 	return 0;
1694*4882a593Smuzhiyun }
1695*4882a593Smuzhiyun 
1696*4882a593Smuzhiyun static int
clear_tst(struct idt77252_dev * card,struct vc_map * vc)1697*4882a593Smuzhiyun clear_tst(struct idt77252_dev *card, struct vc_map *vc)
1698*4882a593Smuzhiyun {
1699*4882a593Smuzhiyun 	unsigned long flags;
1700*4882a593Smuzhiyun 	int res;
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun 	spin_lock_irqsave(&card->tst_lock, flags);
1703*4882a593Smuzhiyun 
1704*4882a593Smuzhiyun 	res = __clear_tst(card, vc);
1705*4882a593Smuzhiyun 
1706*4882a593Smuzhiyun 	set_bit(TST_SWITCH_PENDING, &card->tst_state);
1707*4882a593Smuzhiyun 	if (!timer_pending(&card->tst_timer))
1708*4882a593Smuzhiyun 		mod_timer(&card->tst_timer, jiffies + 1);
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->tst_lock, flags);
1711*4882a593Smuzhiyun 	return res;
1712*4882a593Smuzhiyun }
1713*4882a593Smuzhiyun 
1714*4882a593Smuzhiyun static int
change_tst(struct idt77252_dev * card,struct vc_map * vc,int n,unsigned int opc)1715*4882a593Smuzhiyun change_tst(struct idt77252_dev *card, struct vc_map *vc,
1716*4882a593Smuzhiyun 	   int n, unsigned int opc)
1717*4882a593Smuzhiyun {
1718*4882a593Smuzhiyun 	unsigned long flags;
1719*4882a593Smuzhiyun 	int res;
1720*4882a593Smuzhiyun 
1721*4882a593Smuzhiyun 	spin_lock_irqsave(&card->tst_lock, flags);
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun 	__clear_tst(card, vc);
1724*4882a593Smuzhiyun 	res = __fill_tst(card, vc, n, opc);
1725*4882a593Smuzhiyun 
1726*4882a593Smuzhiyun 	set_bit(TST_SWITCH_PENDING, &card->tst_state);
1727*4882a593Smuzhiyun 	if (!timer_pending(&card->tst_timer))
1728*4882a593Smuzhiyun 		mod_timer(&card->tst_timer, jiffies + 1);
1729*4882a593Smuzhiyun 
1730*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->tst_lock, flags);
1731*4882a593Smuzhiyun 	return res;
1732*4882a593Smuzhiyun }
1733*4882a593Smuzhiyun 
1734*4882a593Smuzhiyun 
1735*4882a593Smuzhiyun static int
set_tct(struct idt77252_dev * card,struct vc_map * vc)1736*4882a593Smuzhiyun set_tct(struct idt77252_dev *card, struct vc_map *vc)
1737*4882a593Smuzhiyun {
1738*4882a593Smuzhiyun 	unsigned long tct;
1739*4882a593Smuzhiyun 
1740*4882a593Smuzhiyun 	tct = (unsigned long) (card->tct_base + vc->index * SAR_SRAM_TCT_SIZE);
1741*4882a593Smuzhiyun 
1742*4882a593Smuzhiyun 	switch (vc->class) {
1743*4882a593Smuzhiyun 	case SCHED_CBR:
1744*4882a593Smuzhiyun 		OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",
1745*4882a593Smuzhiyun 		        card->name, tct, vc->scq->scd);
1746*4882a593Smuzhiyun 
1747*4882a593Smuzhiyun 		write_sram(card, tct + 0, TCT_CBR | vc->scq->scd);
1748*4882a593Smuzhiyun 		write_sram(card, tct + 1, 0);
1749*4882a593Smuzhiyun 		write_sram(card, tct + 2, 0);
1750*4882a593Smuzhiyun 		write_sram(card, tct + 3, 0);
1751*4882a593Smuzhiyun 		write_sram(card, tct + 4, 0);
1752*4882a593Smuzhiyun 		write_sram(card, tct + 5, 0);
1753*4882a593Smuzhiyun 		write_sram(card, tct + 6, 0);
1754*4882a593Smuzhiyun 		write_sram(card, tct + 7, 0);
1755*4882a593Smuzhiyun 		break;
1756*4882a593Smuzhiyun 
1757*4882a593Smuzhiyun 	case SCHED_UBR:
1758*4882a593Smuzhiyun 		OPRINTK("%s: writing TCT at 0x%lx, SCD 0x%lx.\n",
1759*4882a593Smuzhiyun 		        card->name, tct, vc->scq->scd);
1760*4882a593Smuzhiyun 
1761*4882a593Smuzhiyun 		write_sram(card, tct + 0, TCT_UBR | vc->scq->scd);
1762*4882a593Smuzhiyun 		write_sram(card, tct + 1, 0);
1763*4882a593Smuzhiyun 		write_sram(card, tct + 2, TCT_TSIF);
1764*4882a593Smuzhiyun 		write_sram(card, tct + 3, TCT_HALT | TCT_IDLE);
1765*4882a593Smuzhiyun 		write_sram(card, tct + 4, 0);
1766*4882a593Smuzhiyun 		write_sram(card, tct + 5, vc->init_er);
1767*4882a593Smuzhiyun 		write_sram(card, tct + 6, 0);
1768*4882a593Smuzhiyun 		write_sram(card, tct + 7, TCT_FLAG_UBR);
1769*4882a593Smuzhiyun 		break;
1770*4882a593Smuzhiyun 
1771*4882a593Smuzhiyun 	case SCHED_VBR:
1772*4882a593Smuzhiyun 	case SCHED_ABR:
1773*4882a593Smuzhiyun 	default:
1774*4882a593Smuzhiyun 		return -ENOSYS;
1775*4882a593Smuzhiyun 	}
1776*4882a593Smuzhiyun 
1777*4882a593Smuzhiyun 	return 0;
1778*4882a593Smuzhiyun }
1779*4882a593Smuzhiyun 
1780*4882a593Smuzhiyun /*****************************************************************************/
1781*4882a593Smuzhiyun /*                                                                           */
1782*4882a593Smuzhiyun /* FBQ Handling                                                              */
1783*4882a593Smuzhiyun /*                                                                           */
1784*4882a593Smuzhiyun /*****************************************************************************/
1785*4882a593Smuzhiyun 
1786*4882a593Smuzhiyun static __inline__ int
idt77252_fbq_level(struct idt77252_dev * card,int queue)1787*4882a593Smuzhiyun idt77252_fbq_level(struct idt77252_dev *card, int queue)
1788*4882a593Smuzhiyun {
1789*4882a593Smuzhiyun 	return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) & 0x0f;
1790*4882a593Smuzhiyun }
1791*4882a593Smuzhiyun 
1792*4882a593Smuzhiyun static __inline__ int
idt77252_fbq_full(struct idt77252_dev * card,int queue)1793*4882a593Smuzhiyun idt77252_fbq_full(struct idt77252_dev *card, int queue)
1794*4882a593Smuzhiyun {
1795*4882a593Smuzhiyun 	return (readl(SAR_REG_STAT) >> (16 + (queue << 2))) == 0x0f;
1796*4882a593Smuzhiyun }
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun static int
push_rx_skb(struct idt77252_dev * card,struct sk_buff * skb,int queue)1799*4882a593Smuzhiyun push_rx_skb(struct idt77252_dev *card, struct sk_buff *skb, int queue)
1800*4882a593Smuzhiyun {
1801*4882a593Smuzhiyun 	unsigned long flags;
1802*4882a593Smuzhiyun 	u32 handle;
1803*4882a593Smuzhiyun 	u32 addr;
1804*4882a593Smuzhiyun 
1805*4882a593Smuzhiyun 	skb->data = skb->head;
1806*4882a593Smuzhiyun 	skb_reset_tail_pointer(skb);
1807*4882a593Smuzhiyun 	skb->len = 0;
1808*4882a593Smuzhiyun 
1809*4882a593Smuzhiyun 	skb_reserve(skb, 16);
1810*4882a593Smuzhiyun 
1811*4882a593Smuzhiyun 	switch (queue) {
1812*4882a593Smuzhiyun 	case 0:
1813*4882a593Smuzhiyun 		skb_put(skb, SAR_FB_SIZE_0);
1814*4882a593Smuzhiyun 		break;
1815*4882a593Smuzhiyun 	case 1:
1816*4882a593Smuzhiyun 		skb_put(skb, SAR_FB_SIZE_1);
1817*4882a593Smuzhiyun 		break;
1818*4882a593Smuzhiyun 	case 2:
1819*4882a593Smuzhiyun 		skb_put(skb, SAR_FB_SIZE_2);
1820*4882a593Smuzhiyun 		break;
1821*4882a593Smuzhiyun 	case 3:
1822*4882a593Smuzhiyun 		skb_put(skb, SAR_FB_SIZE_3);
1823*4882a593Smuzhiyun 		break;
1824*4882a593Smuzhiyun 	default:
1825*4882a593Smuzhiyun 		return -1;
1826*4882a593Smuzhiyun 	}
1827*4882a593Smuzhiyun 
1828*4882a593Smuzhiyun 	if (idt77252_fbq_full(card, queue))
1829*4882a593Smuzhiyun 		return -1;
1830*4882a593Smuzhiyun 
1831*4882a593Smuzhiyun 	memset(&skb->data[(skb->len & ~(0x3f)) - 64], 0, 2 * sizeof(u32));
1832*4882a593Smuzhiyun 
1833*4882a593Smuzhiyun 	handle = IDT77252_PRV_POOL(skb);
1834*4882a593Smuzhiyun 	addr = IDT77252_PRV_PADDR(skb);
1835*4882a593Smuzhiyun 
1836*4882a593Smuzhiyun 	spin_lock_irqsave(&card->cmd_lock, flags);
1837*4882a593Smuzhiyun 	writel(handle, card->fbq[queue]);
1838*4882a593Smuzhiyun 	writel(addr, card->fbq[queue]);
1839*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->cmd_lock, flags);
1840*4882a593Smuzhiyun 
1841*4882a593Smuzhiyun 	return 0;
1842*4882a593Smuzhiyun }
1843*4882a593Smuzhiyun 
1844*4882a593Smuzhiyun static void
add_rx_skb(struct idt77252_dev * card,int queue,unsigned int size,unsigned int count)1845*4882a593Smuzhiyun add_rx_skb(struct idt77252_dev *card, int queue,
1846*4882a593Smuzhiyun 	   unsigned int size, unsigned int count)
1847*4882a593Smuzhiyun {
1848*4882a593Smuzhiyun 	struct sk_buff *skb;
1849*4882a593Smuzhiyun 	dma_addr_t paddr;
1850*4882a593Smuzhiyun 	u32 handle;
1851*4882a593Smuzhiyun 
1852*4882a593Smuzhiyun 	while (count--) {
1853*4882a593Smuzhiyun 		skb = dev_alloc_skb(size);
1854*4882a593Smuzhiyun 		if (!skb)
1855*4882a593Smuzhiyun 			return;
1856*4882a593Smuzhiyun 
1857*4882a593Smuzhiyun 		if (sb_pool_add(card, skb, queue)) {
1858*4882a593Smuzhiyun 			printk("%s: SB POOL full\n", __func__);
1859*4882a593Smuzhiyun 			goto outfree;
1860*4882a593Smuzhiyun 		}
1861*4882a593Smuzhiyun 
1862*4882a593Smuzhiyun 		paddr = dma_map_single(&card->pcidev->dev, skb->data,
1863*4882a593Smuzhiyun 				       skb_end_pointer(skb) - skb->data,
1864*4882a593Smuzhiyun 				       DMA_FROM_DEVICE);
1865*4882a593Smuzhiyun 		IDT77252_PRV_PADDR(skb) = paddr;
1866*4882a593Smuzhiyun 
1867*4882a593Smuzhiyun 		if (push_rx_skb(card, skb, queue)) {
1868*4882a593Smuzhiyun 			printk("%s: FB QUEUE full\n", __func__);
1869*4882a593Smuzhiyun 			goto outunmap;
1870*4882a593Smuzhiyun 		}
1871*4882a593Smuzhiyun 	}
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun 	return;
1874*4882a593Smuzhiyun 
1875*4882a593Smuzhiyun outunmap:
1876*4882a593Smuzhiyun 	dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
1877*4882a593Smuzhiyun 			 skb_end_pointer(skb) - skb->data, DMA_FROM_DEVICE);
1878*4882a593Smuzhiyun 
1879*4882a593Smuzhiyun 	handle = IDT77252_PRV_POOL(skb);
1880*4882a593Smuzhiyun 	card->sbpool[POOL_QUEUE(handle)].skb[POOL_INDEX(handle)] = NULL;
1881*4882a593Smuzhiyun 
1882*4882a593Smuzhiyun outfree:
1883*4882a593Smuzhiyun 	dev_kfree_skb(skb);
1884*4882a593Smuzhiyun }
1885*4882a593Smuzhiyun 
1886*4882a593Smuzhiyun 
1887*4882a593Smuzhiyun static void
recycle_rx_skb(struct idt77252_dev * card,struct sk_buff * skb)1888*4882a593Smuzhiyun recycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb)
1889*4882a593Smuzhiyun {
1890*4882a593Smuzhiyun 	u32 handle = IDT77252_PRV_POOL(skb);
1891*4882a593Smuzhiyun 	int err;
1892*4882a593Smuzhiyun 
1893*4882a593Smuzhiyun 	dma_sync_single_for_device(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
1894*4882a593Smuzhiyun 				   skb_end_pointer(skb) - skb->data,
1895*4882a593Smuzhiyun 				   DMA_FROM_DEVICE);
1896*4882a593Smuzhiyun 
1897*4882a593Smuzhiyun 	err = push_rx_skb(card, skb, POOL_QUEUE(handle));
1898*4882a593Smuzhiyun 	if (err) {
1899*4882a593Smuzhiyun 		dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb),
1900*4882a593Smuzhiyun 				 skb_end_pointer(skb) - skb->data,
1901*4882a593Smuzhiyun 				 DMA_FROM_DEVICE);
1902*4882a593Smuzhiyun 		sb_pool_remove(card, skb);
1903*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1904*4882a593Smuzhiyun 	}
1905*4882a593Smuzhiyun }
1906*4882a593Smuzhiyun 
1907*4882a593Smuzhiyun static void
flush_rx_pool(struct idt77252_dev * card,struct rx_pool * rpp)1908*4882a593Smuzhiyun flush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp)
1909*4882a593Smuzhiyun {
1910*4882a593Smuzhiyun 	skb_queue_head_init(&rpp->queue);
1911*4882a593Smuzhiyun 	rpp->len = 0;
1912*4882a593Smuzhiyun }
1913*4882a593Smuzhiyun 
1914*4882a593Smuzhiyun static void
recycle_rx_pool_skb(struct idt77252_dev * card,struct rx_pool * rpp)1915*4882a593Smuzhiyun recycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp)
1916*4882a593Smuzhiyun {
1917*4882a593Smuzhiyun 	struct sk_buff *skb, *tmp;
1918*4882a593Smuzhiyun 
1919*4882a593Smuzhiyun 	skb_queue_walk_safe(&rpp->queue, skb, tmp)
1920*4882a593Smuzhiyun 		recycle_rx_skb(card, skb);
1921*4882a593Smuzhiyun 
1922*4882a593Smuzhiyun 	flush_rx_pool(card, rpp);
1923*4882a593Smuzhiyun }
1924*4882a593Smuzhiyun 
1925*4882a593Smuzhiyun /*****************************************************************************/
1926*4882a593Smuzhiyun /*                                                                           */
1927*4882a593Smuzhiyun /* ATM Interface                                                             */
1928*4882a593Smuzhiyun /*                                                                           */
1929*4882a593Smuzhiyun /*****************************************************************************/
1930*4882a593Smuzhiyun 
1931*4882a593Smuzhiyun static void
idt77252_phy_put(struct atm_dev * dev,unsigned char value,unsigned long addr)1932*4882a593Smuzhiyun idt77252_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr)
1933*4882a593Smuzhiyun {
1934*4882a593Smuzhiyun 	write_utility(dev->dev_data, 0x100 + (addr & 0x1ff), value);
1935*4882a593Smuzhiyun }
1936*4882a593Smuzhiyun 
1937*4882a593Smuzhiyun static unsigned char
idt77252_phy_get(struct atm_dev * dev,unsigned long addr)1938*4882a593Smuzhiyun idt77252_phy_get(struct atm_dev *dev, unsigned long addr)
1939*4882a593Smuzhiyun {
1940*4882a593Smuzhiyun 	return read_utility(dev->dev_data, 0x100 + (addr & 0x1ff));
1941*4882a593Smuzhiyun }
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun static inline int
idt77252_send_skb(struct atm_vcc * vcc,struct sk_buff * skb,int oam)1944*4882a593Smuzhiyun idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam)
1945*4882a593Smuzhiyun {
1946*4882a593Smuzhiyun 	struct atm_dev *dev = vcc->dev;
1947*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
1948*4882a593Smuzhiyun 	struct vc_map *vc = vcc->dev_data;
1949*4882a593Smuzhiyun 	int err;
1950*4882a593Smuzhiyun 
1951*4882a593Smuzhiyun 	if (vc == NULL) {
1952*4882a593Smuzhiyun 		printk("%s: NULL connection in send().\n", card->name);
1953*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->tx_err);
1954*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1955*4882a593Smuzhiyun 		return -EINVAL;
1956*4882a593Smuzhiyun 	}
1957*4882a593Smuzhiyun 	if (!test_bit(VCF_TX, &vc->flags)) {
1958*4882a593Smuzhiyun 		printk("%s: Trying to transmit on a non-tx VC.\n", card->name);
1959*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->tx_err);
1960*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1961*4882a593Smuzhiyun 		return -EINVAL;
1962*4882a593Smuzhiyun 	}
1963*4882a593Smuzhiyun 
1964*4882a593Smuzhiyun 	switch (vcc->qos.aal) {
1965*4882a593Smuzhiyun 	case ATM_AAL0:
1966*4882a593Smuzhiyun 	case ATM_AAL1:
1967*4882a593Smuzhiyun 	case ATM_AAL5:
1968*4882a593Smuzhiyun 		break;
1969*4882a593Smuzhiyun 	default:
1970*4882a593Smuzhiyun 		printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
1971*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->tx_err);
1972*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1973*4882a593Smuzhiyun 		return -EINVAL;
1974*4882a593Smuzhiyun 	}
1975*4882a593Smuzhiyun 
1976*4882a593Smuzhiyun 	if (skb_shinfo(skb)->nr_frags != 0) {
1977*4882a593Smuzhiyun 		printk("%s: No scatter-gather yet.\n", card->name);
1978*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->tx_err);
1979*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1980*4882a593Smuzhiyun 		return -EINVAL;
1981*4882a593Smuzhiyun 	}
1982*4882a593Smuzhiyun 	ATM_SKB(skb)->vcc = vcc;
1983*4882a593Smuzhiyun 
1984*4882a593Smuzhiyun 	err = queue_skb(card, vc, skb, oam);
1985*4882a593Smuzhiyun 	if (err) {
1986*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->tx_err);
1987*4882a593Smuzhiyun 		dev_kfree_skb(skb);
1988*4882a593Smuzhiyun 		return err;
1989*4882a593Smuzhiyun 	}
1990*4882a593Smuzhiyun 
1991*4882a593Smuzhiyun 	return 0;
1992*4882a593Smuzhiyun }
1993*4882a593Smuzhiyun 
idt77252_send(struct atm_vcc * vcc,struct sk_buff * skb)1994*4882a593Smuzhiyun static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb)
1995*4882a593Smuzhiyun {
1996*4882a593Smuzhiyun 	return idt77252_send_skb(vcc, skb, 0);
1997*4882a593Smuzhiyun }
1998*4882a593Smuzhiyun 
1999*4882a593Smuzhiyun static int
idt77252_send_oam(struct atm_vcc * vcc,void * cell,int flags)2000*4882a593Smuzhiyun idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)
2001*4882a593Smuzhiyun {
2002*4882a593Smuzhiyun 	struct atm_dev *dev = vcc->dev;
2003*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
2004*4882a593Smuzhiyun 	struct sk_buff *skb;
2005*4882a593Smuzhiyun 
2006*4882a593Smuzhiyun 	skb = dev_alloc_skb(64);
2007*4882a593Smuzhiyun 	if (!skb) {
2008*4882a593Smuzhiyun 		printk("%s: Out of memory in send_oam().\n", card->name);
2009*4882a593Smuzhiyun 		atomic_inc(&vcc->stats->tx_err);
2010*4882a593Smuzhiyun 		return -ENOMEM;
2011*4882a593Smuzhiyun 	}
2012*4882a593Smuzhiyun 	refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun 	skb_put_data(skb, cell, 52);
2015*4882a593Smuzhiyun 
2016*4882a593Smuzhiyun 	return idt77252_send_skb(vcc, skb, 1);
2017*4882a593Smuzhiyun }
2018*4882a593Smuzhiyun 
2019*4882a593Smuzhiyun static __inline__ unsigned int
idt77252_fls(unsigned int x)2020*4882a593Smuzhiyun idt77252_fls(unsigned int x)
2021*4882a593Smuzhiyun {
2022*4882a593Smuzhiyun 	int r = 1;
2023*4882a593Smuzhiyun 
2024*4882a593Smuzhiyun 	if (x == 0)
2025*4882a593Smuzhiyun 		return 0;
2026*4882a593Smuzhiyun 	if (x & 0xffff0000) {
2027*4882a593Smuzhiyun 		x >>= 16;
2028*4882a593Smuzhiyun 		r += 16;
2029*4882a593Smuzhiyun 	}
2030*4882a593Smuzhiyun 	if (x & 0xff00) {
2031*4882a593Smuzhiyun 		x >>= 8;
2032*4882a593Smuzhiyun 		r += 8;
2033*4882a593Smuzhiyun 	}
2034*4882a593Smuzhiyun 	if (x & 0xf0) {
2035*4882a593Smuzhiyun 		x >>= 4;
2036*4882a593Smuzhiyun 		r += 4;
2037*4882a593Smuzhiyun 	}
2038*4882a593Smuzhiyun 	if (x & 0xc) {
2039*4882a593Smuzhiyun 		x >>= 2;
2040*4882a593Smuzhiyun 		r += 2;
2041*4882a593Smuzhiyun 	}
2042*4882a593Smuzhiyun 	if (x & 0x2)
2043*4882a593Smuzhiyun 		r += 1;
2044*4882a593Smuzhiyun 	return r;
2045*4882a593Smuzhiyun }
2046*4882a593Smuzhiyun 
2047*4882a593Smuzhiyun static u16
idt77252_int_to_atmfp(unsigned int rate)2048*4882a593Smuzhiyun idt77252_int_to_atmfp(unsigned int rate)
2049*4882a593Smuzhiyun {
2050*4882a593Smuzhiyun 	u16 m, e;
2051*4882a593Smuzhiyun 
2052*4882a593Smuzhiyun 	if (rate == 0)
2053*4882a593Smuzhiyun 		return 0;
2054*4882a593Smuzhiyun 	e = idt77252_fls(rate) - 1;
2055*4882a593Smuzhiyun 	if (e < 9)
2056*4882a593Smuzhiyun 		m = (rate - (1 << e)) << (9 - e);
2057*4882a593Smuzhiyun 	else if (e == 9)
2058*4882a593Smuzhiyun 		m = (rate - (1 << e));
2059*4882a593Smuzhiyun 	else /* e > 9 */
2060*4882a593Smuzhiyun 		m = (rate - (1 << e)) >> (e - 9);
2061*4882a593Smuzhiyun 	return 0x4000 | (e << 9) | m;
2062*4882a593Smuzhiyun }
2063*4882a593Smuzhiyun 
2064*4882a593Smuzhiyun static u8
idt77252_rate_logindex(struct idt77252_dev * card,int pcr)2065*4882a593Smuzhiyun idt77252_rate_logindex(struct idt77252_dev *card, int pcr)
2066*4882a593Smuzhiyun {
2067*4882a593Smuzhiyun 	u16 afp;
2068*4882a593Smuzhiyun 
2069*4882a593Smuzhiyun 	afp = idt77252_int_to_atmfp(pcr < 0 ? -pcr : pcr);
2070*4882a593Smuzhiyun 	if (pcr < 0)
2071*4882a593Smuzhiyun 		return rate_to_log[(afp >> 5) & 0x1ff];
2072*4882a593Smuzhiyun 	return rate_to_log[((afp >> 5) + 1) & 0x1ff];
2073*4882a593Smuzhiyun }
2074*4882a593Smuzhiyun 
2075*4882a593Smuzhiyun static void
idt77252_est_timer(struct timer_list * t)2076*4882a593Smuzhiyun idt77252_est_timer(struct timer_list *t)
2077*4882a593Smuzhiyun {
2078*4882a593Smuzhiyun 	struct rate_estimator *est = from_timer(est, t, timer);
2079*4882a593Smuzhiyun 	struct vc_map *vc = est->vc;
2080*4882a593Smuzhiyun 	struct idt77252_dev *card = vc->card;
2081*4882a593Smuzhiyun 	unsigned long flags;
2082*4882a593Smuzhiyun 	u32 rate, cps;
2083*4882a593Smuzhiyun 	u64 ncells;
2084*4882a593Smuzhiyun 	u8 lacr;
2085*4882a593Smuzhiyun 
2086*4882a593Smuzhiyun 	spin_lock_irqsave(&vc->lock, flags);
2087*4882a593Smuzhiyun 	if (!vc->estimator)
2088*4882a593Smuzhiyun 		goto out;
2089*4882a593Smuzhiyun 	ncells = est->cells;
2090*4882a593Smuzhiyun 
2091*4882a593Smuzhiyun 	rate = ((u32)(ncells - est->last_cells)) << (7 - est->interval);
2092*4882a593Smuzhiyun 	est->last_cells = ncells;
2093*4882a593Smuzhiyun 	est->avcps += ((long)rate - (long)est->avcps) >> est->ewma_log;
2094*4882a593Smuzhiyun 	est->cps = (est->avcps + 0x1f) >> 5;
2095*4882a593Smuzhiyun 
2096*4882a593Smuzhiyun 	cps = est->cps;
2097*4882a593Smuzhiyun 	if (cps < (est->maxcps >> 4))
2098*4882a593Smuzhiyun 		cps = est->maxcps >> 4;
2099*4882a593Smuzhiyun 
2100*4882a593Smuzhiyun 	lacr = idt77252_rate_logindex(card, cps);
2101*4882a593Smuzhiyun 	if (lacr > vc->max_er)
2102*4882a593Smuzhiyun 		lacr = vc->max_er;
2103*4882a593Smuzhiyun 
2104*4882a593Smuzhiyun 	if (lacr != vc->lacr) {
2105*4882a593Smuzhiyun 		vc->lacr = lacr;
2106*4882a593Smuzhiyun 		writel(TCMDQ_LACR|(vc->lacr << 16)|vc->index, SAR_REG_TCMDQ);
2107*4882a593Smuzhiyun 	}
2108*4882a593Smuzhiyun 
2109*4882a593Smuzhiyun 	est->timer.expires = jiffies + ((HZ / 4) << est->interval);
2110*4882a593Smuzhiyun 	add_timer(&est->timer);
2111*4882a593Smuzhiyun 
2112*4882a593Smuzhiyun out:
2113*4882a593Smuzhiyun 	spin_unlock_irqrestore(&vc->lock, flags);
2114*4882a593Smuzhiyun }
2115*4882a593Smuzhiyun 
2116*4882a593Smuzhiyun static struct rate_estimator *
idt77252_init_est(struct vc_map * vc,int pcr)2117*4882a593Smuzhiyun idt77252_init_est(struct vc_map *vc, int pcr)
2118*4882a593Smuzhiyun {
2119*4882a593Smuzhiyun 	struct rate_estimator *est;
2120*4882a593Smuzhiyun 
2121*4882a593Smuzhiyun 	est = kzalloc(sizeof(struct rate_estimator), GFP_KERNEL);
2122*4882a593Smuzhiyun 	if (!est)
2123*4882a593Smuzhiyun 		return NULL;
2124*4882a593Smuzhiyun 	est->maxcps = pcr < 0 ? -pcr : pcr;
2125*4882a593Smuzhiyun 	est->cps = est->maxcps;
2126*4882a593Smuzhiyun 	est->avcps = est->cps << 5;
2127*4882a593Smuzhiyun 	est->vc = vc;
2128*4882a593Smuzhiyun 
2129*4882a593Smuzhiyun 	est->interval = 2;		/* XXX: make this configurable */
2130*4882a593Smuzhiyun 	est->ewma_log = 2;		/* XXX: make this configurable */
2131*4882a593Smuzhiyun 	timer_setup(&est->timer, idt77252_est_timer, 0);
2132*4882a593Smuzhiyun 	mod_timer(&est->timer, jiffies + ((HZ / 4) << est->interval));
2133*4882a593Smuzhiyun 
2134*4882a593Smuzhiyun 	return est;
2135*4882a593Smuzhiyun }
2136*4882a593Smuzhiyun 
2137*4882a593Smuzhiyun static int
idt77252_init_cbr(struct idt77252_dev * card,struct vc_map * vc,struct atm_vcc * vcc,struct atm_qos * qos)2138*4882a593Smuzhiyun idt77252_init_cbr(struct idt77252_dev *card, struct vc_map *vc,
2139*4882a593Smuzhiyun 		  struct atm_vcc *vcc, struct atm_qos *qos)
2140*4882a593Smuzhiyun {
2141*4882a593Smuzhiyun 	int tst_free, tst_used, tst_entries;
2142*4882a593Smuzhiyun 	unsigned long tmpl, modl;
2143*4882a593Smuzhiyun 	int tcr, tcra;
2144*4882a593Smuzhiyun 
2145*4882a593Smuzhiyun 	if ((qos->txtp.max_pcr == 0) &&
2146*4882a593Smuzhiyun 	    (qos->txtp.pcr == 0) && (qos->txtp.min_pcr == 0)) {
2147*4882a593Smuzhiyun 		printk("%s: trying to open a CBR VC with cell rate = 0\n",
2148*4882a593Smuzhiyun 		       card->name);
2149*4882a593Smuzhiyun 		return -EINVAL;
2150*4882a593Smuzhiyun 	}
2151*4882a593Smuzhiyun 
2152*4882a593Smuzhiyun 	tst_used = 0;
2153*4882a593Smuzhiyun 	tst_free = card->tst_free;
2154*4882a593Smuzhiyun 	if (test_bit(VCF_TX, &vc->flags))
2155*4882a593Smuzhiyun 		tst_used = vc->ntste;
2156*4882a593Smuzhiyun 	tst_free += tst_used;
2157*4882a593Smuzhiyun 
2158*4882a593Smuzhiyun 	tcr = atm_pcr_goal(&qos->txtp);
2159*4882a593Smuzhiyun 	tcra = tcr >= 0 ? tcr : -tcr;
2160*4882a593Smuzhiyun 
2161*4882a593Smuzhiyun 	TXPRINTK("%s: CBR target cell rate = %d\n", card->name, tcra);
2162*4882a593Smuzhiyun 
2163*4882a593Smuzhiyun 	tmpl = (unsigned long) tcra * ((unsigned long) card->tst_size - 2);
2164*4882a593Smuzhiyun 	modl = tmpl % (unsigned long)card->utopia_pcr;
2165*4882a593Smuzhiyun 
2166*4882a593Smuzhiyun 	tst_entries = (int) (tmpl / card->utopia_pcr);
2167*4882a593Smuzhiyun 	if (tcr > 0) {
2168*4882a593Smuzhiyun 		if (modl > 0)
2169*4882a593Smuzhiyun 			tst_entries++;
2170*4882a593Smuzhiyun 	} else if (tcr == 0) {
2171*4882a593Smuzhiyun 		tst_entries = tst_free - SAR_TST_RESERVED;
2172*4882a593Smuzhiyun 		if (tst_entries <= 0) {
2173*4882a593Smuzhiyun 			printk("%s: no CBR bandwidth free.\n", card->name);
2174*4882a593Smuzhiyun 			return -ENOSR;
2175*4882a593Smuzhiyun 		}
2176*4882a593Smuzhiyun 	}
2177*4882a593Smuzhiyun 
2178*4882a593Smuzhiyun 	if (tst_entries == 0) {
2179*4882a593Smuzhiyun 		printk("%s: selected CBR bandwidth < granularity.\n",
2180*4882a593Smuzhiyun 		       card->name);
2181*4882a593Smuzhiyun 		return -EINVAL;
2182*4882a593Smuzhiyun 	}
2183*4882a593Smuzhiyun 
2184*4882a593Smuzhiyun 	if (tst_entries > (tst_free - SAR_TST_RESERVED)) {
2185*4882a593Smuzhiyun 		printk("%s: not enough CBR bandwidth free.\n", card->name);
2186*4882a593Smuzhiyun 		return -ENOSR;
2187*4882a593Smuzhiyun 	}
2188*4882a593Smuzhiyun 
2189*4882a593Smuzhiyun 	vc->ntste = tst_entries;
2190*4882a593Smuzhiyun 
2191*4882a593Smuzhiyun 	card->tst_free = tst_free - tst_entries;
2192*4882a593Smuzhiyun 	if (test_bit(VCF_TX, &vc->flags)) {
2193*4882a593Smuzhiyun 		if (tst_used == tst_entries)
2194*4882a593Smuzhiyun 			return 0;
2195*4882a593Smuzhiyun 
2196*4882a593Smuzhiyun 		OPRINTK("%s: modify %d -> %d entries in TST.\n",
2197*4882a593Smuzhiyun 			card->name, tst_used, tst_entries);
2198*4882a593Smuzhiyun 		change_tst(card, vc, tst_entries, TSTE_OPC_CBR);
2199*4882a593Smuzhiyun 		return 0;
2200*4882a593Smuzhiyun 	}
2201*4882a593Smuzhiyun 
2202*4882a593Smuzhiyun 	OPRINTK("%s: setting %d entries in TST.\n", card->name, tst_entries);
2203*4882a593Smuzhiyun 	fill_tst(card, vc, tst_entries, TSTE_OPC_CBR);
2204*4882a593Smuzhiyun 	return 0;
2205*4882a593Smuzhiyun }
2206*4882a593Smuzhiyun 
2207*4882a593Smuzhiyun static int
idt77252_init_ubr(struct idt77252_dev * card,struct vc_map * vc,struct atm_vcc * vcc,struct atm_qos * qos)2208*4882a593Smuzhiyun idt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc,
2209*4882a593Smuzhiyun 		  struct atm_vcc *vcc, struct atm_qos *qos)
2210*4882a593Smuzhiyun {
2211*4882a593Smuzhiyun 	struct rate_estimator *est = NULL;
2212*4882a593Smuzhiyun 	unsigned long flags;
2213*4882a593Smuzhiyun 	int tcr;
2214*4882a593Smuzhiyun 
2215*4882a593Smuzhiyun 	spin_lock_irqsave(&vc->lock, flags);
2216*4882a593Smuzhiyun 	if (vc->estimator) {
2217*4882a593Smuzhiyun 		est = vc->estimator;
2218*4882a593Smuzhiyun 		vc->estimator = NULL;
2219*4882a593Smuzhiyun 	}
2220*4882a593Smuzhiyun 	spin_unlock_irqrestore(&vc->lock, flags);
2221*4882a593Smuzhiyun 	if (est) {
2222*4882a593Smuzhiyun 		del_timer_sync(&est->timer);
2223*4882a593Smuzhiyun 		kfree(est);
2224*4882a593Smuzhiyun 	}
2225*4882a593Smuzhiyun 
2226*4882a593Smuzhiyun 	tcr = atm_pcr_goal(&qos->txtp);
2227*4882a593Smuzhiyun 	if (tcr == 0)
2228*4882a593Smuzhiyun 		tcr = card->link_pcr;
2229*4882a593Smuzhiyun 
2230*4882a593Smuzhiyun 	vc->estimator = idt77252_init_est(vc, tcr);
2231*4882a593Smuzhiyun 
2232*4882a593Smuzhiyun 	vc->class = SCHED_UBR;
2233*4882a593Smuzhiyun 	vc->init_er = idt77252_rate_logindex(card, tcr);
2234*4882a593Smuzhiyun 	vc->lacr = vc->init_er;
2235*4882a593Smuzhiyun 	if (tcr < 0)
2236*4882a593Smuzhiyun 		vc->max_er = vc->init_er;
2237*4882a593Smuzhiyun 	else
2238*4882a593Smuzhiyun 		vc->max_er = 0xff;
2239*4882a593Smuzhiyun 
2240*4882a593Smuzhiyun 	return 0;
2241*4882a593Smuzhiyun }
2242*4882a593Smuzhiyun 
2243*4882a593Smuzhiyun static int
idt77252_init_tx(struct idt77252_dev * card,struct vc_map * vc,struct atm_vcc * vcc,struct atm_qos * qos)2244*4882a593Smuzhiyun idt77252_init_tx(struct idt77252_dev *card, struct vc_map *vc,
2245*4882a593Smuzhiyun 		 struct atm_vcc *vcc, struct atm_qos *qos)
2246*4882a593Smuzhiyun {
2247*4882a593Smuzhiyun 	int error;
2248*4882a593Smuzhiyun 
2249*4882a593Smuzhiyun 	if (test_bit(VCF_TX, &vc->flags))
2250*4882a593Smuzhiyun 		return -EBUSY;
2251*4882a593Smuzhiyun 
2252*4882a593Smuzhiyun 	switch (qos->txtp.traffic_class) {
2253*4882a593Smuzhiyun 		case ATM_CBR:
2254*4882a593Smuzhiyun 			vc->class = SCHED_CBR;
2255*4882a593Smuzhiyun 			break;
2256*4882a593Smuzhiyun 
2257*4882a593Smuzhiyun 		case ATM_UBR:
2258*4882a593Smuzhiyun 			vc->class = SCHED_UBR;
2259*4882a593Smuzhiyun 			break;
2260*4882a593Smuzhiyun 
2261*4882a593Smuzhiyun 		case ATM_VBR:
2262*4882a593Smuzhiyun 		case ATM_ABR:
2263*4882a593Smuzhiyun 		default:
2264*4882a593Smuzhiyun 			return -EPROTONOSUPPORT;
2265*4882a593Smuzhiyun 	}
2266*4882a593Smuzhiyun 
2267*4882a593Smuzhiyun 	vc->scq = alloc_scq(card, vc->class);
2268*4882a593Smuzhiyun 	if (!vc->scq) {
2269*4882a593Smuzhiyun 		printk("%s: can't get SCQ.\n", card->name);
2270*4882a593Smuzhiyun 		return -ENOMEM;
2271*4882a593Smuzhiyun 	}
2272*4882a593Smuzhiyun 
2273*4882a593Smuzhiyun 	vc->scq->scd = get_free_scd(card, vc);
2274*4882a593Smuzhiyun 	if (vc->scq->scd == 0) {
2275*4882a593Smuzhiyun 		printk("%s: no SCD available.\n", card->name);
2276*4882a593Smuzhiyun 		free_scq(card, vc->scq);
2277*4882a593Smuzhiyun 		return -ENOMEM;
2278*4882a593Smuzhiyun 	}
2279*4882a593Smuzhiyun 
2280*4882a593Smuzhiyun 	fill_scd(card, vc->scq, vc->class);
2281*4882a593Smuzhiyun 
2282*4882a593Smuzhiyun 	if (set_tct(card, vc)) {
2283*4882a593Smuzhiyun 		printk("%s: class %d not supported.\n",
2284*4882a593Smuzhiyun 		       card->name, qos->txtp.traffic_class);
2285*4882a593Smuzhiyun 
2286*4882a593Smuzhiyun 		card->scd2vc[vc->scd_index] = NULL;
2287*4882a593Smuzhiyun 		free_scq(card, vc->scq);
2288*4882a593Smuzhiyun 		return -EPROTONOSUPPORT;
2289*4882a593Smuzhiyun 	}
2290*4882a593Smuzhiyun 
2291*4882a593Smuzhiyun 	switch (vc->class) {
2292*4882a593Smuzhiyun 		case SCHED_CBR:
2293*4882a593Smuzhiyun 			error = idt77252_init_cbr(card, vc, vcc, qos);
2294*4882a593Smuzhiyun 			if (error) {
2295*4882a593Smuzhiyun 				card->scd2vc[vc->scd_index] = NULL;
2296*4882a593Smuzhiyun 				free_scq(card, vc->scq);
2297*4882a593Smuzhiyun 				return error;
2298*4882a593Smuzhiyun 			}
2299*4882a593Smuzhiyun 
2300*4882a593Smuzhiyun 			clear_bit(VCF_IDLE, &vc->flags);
2301*4882a593Smuzhiyun 			writel(TCMDQ_START | vc->index, SAR_REG_TCMDQ);
2302*4882a593Smuzhiyun 			break;
2303*4882a593Smuzhiyun 
2304*4882a593Smuzhiyun 		case SCHED_UBR:
2305*4882a593Smuzhiyun 			error = idt77252_init_ubr(card, vc, vcc, qos);
2306*4882a593Smuzhiyun 			if (error) {
2307*4882a593Smuzhiyun 				card->scd2vc[vc->scd_index] = NULL;
2308*4882a593Smuzhiyun 				free_scq(card, vc->scq);
2309*4882a593Smuzhiyun 				return error;
2310*4882a593Smuzhiyun 			}
2311*4882a593Smuzhiyun 
2312*4882a593Smuzhiyun 			set_bit(VCF_IDLE, &vc->flags);
2313*4882a593Smuzhiyun 			break;
2314*4882a593Smuzhiyun 	}
2315*4882a593Smuzhiyun 
2316*4882a593Smuzhiyun 	vc->tx_vcc = vcc;
2317*4882a593Smuzhiyun 	set_bit(VCF_TX, &vc->flags);
2318*4882a593Smuzhiyun 	return 0;
2319*4882a593Smuzhiyun }
2320*4882a593Smuzhiyun 
2321*4882a593Smuzhiyun static int
idt77252_init_rx(struct idt77252_dev * card,struct vc_map * vc,struct atm_vcc * vcc,struct atm_qos * qos)2322*4882a593Smuzhiyun idt77252_init_rx(struct idt77252_dev *card, struct vc_map *vc,
2323*4882a593Smuzhiyun 		 struct atm_vcc *vcc, struct atm_qos *qos)
2324*4882a593Smuzhiyun {
2325*4882a593Smuzhiyun 	unsigned long flags;
2326*4882a593Smuzhiyun 	unsigned long addr;
2327*4882a593Smuzhiyun 	u32 rcte = 0;
2328*4882a593Smuzhiyun 
2329*4882a593Smuzhiyun 	if (test_bit(VCF_RX, &vc->flags))
2330*4882a593Smuzhiyun 		return -EBUSY;
2331*4882a593Smuzhiyun 
2332*4882a593Smuzhiyun 	vc->rx_vcc = vcc;
2333*4882a593Smuzhiyun 	set_bit(VCF_RX, &vc->flags);
2334*4882a593Smuzhiyun 
2335*4882a593Smuzhiyun 	if ((vcc->vci == 3) || (vcc->vci == 4))
2336*4882a593Smuzhiyun 		return 0;
2337*4882a593Smuzhiyun 
2338*4882a593Smuzhiyun 	flush_rx_pool(card, &vc->rcv.rx_pool);
2339*4882a593Smuzhiyun 
2340*4882a593Smuzhiyun 	rcte |= SAR_RCTE_CONNECTOPEN;
2341*4882a593Smuzhiyun 	rcte |= SAR_RCTE_RAWCELLINTEN;
2342*4882a593Smuzhiyun 
2343*4882a593Smuzhiyun 	switch (qos->aal) {
2344*4882a593Smuzhiyun 		case ATM_AAL0:
2345*4882a593Smuzhiyun 			rcte |= SAR_RCTE_RCQ;
2346*4882a593Smuzhiyun 			break;
2347*4882a593Smuzhiyun 		case ATM_AAL1:
2348*4882a593Smuzhiyun 			rcte |= SAR_RCTE_OAM; /* Let SAR drop Video */
2349*4882a593Smuzhiyun 			break;
2350*4882a593Smuzhiyun 		case ATM_AAL34:
2351*4882a593Smuzhiyun 			rcte |= SAR_RCTE_AAL34;
2352*4882a593Smuzhiyun 			break;
2353*4882a593Smuzhiyun 		case ATM_AAL5:
2354*4882a593Smuzhiyun 			rcte |= SAR_RCTE_AAL5;
2355*4882a593Smuzhiyun 			break;
2356*4882a593Smuzhiyun 		default:
2357*4882a593Smuzhiyun 			rcte |= SAR_RCTE_RCQ;
2358*4882a593Smuzhiyun 			break;
2359*4882a593Smuzhiyun 	}
2360*4882a593Smuzhiyun 
2361*4882a593Smuzhiyun 	if (qos->aal != ATM_AAL5)
2362*4882a593Smuzhiyun 		rcte |= SAR_RCTE_FBP_1;
2363*4882a593Smuzhiyun 	else if (qos->rxtp.max_sdu > SAR_FB_SIZE_2)
2364*4882a593Smuzhiyun 		rcte |= SAR_RCTE_FBP_3;
2365*4882a593Smuzhiyun 	else if (qos->rxtp.max_sdu > SAR_FB_SIZE_1)
2366*4882a593Smuzhiyun 		rcte |= SAR_RCTE_FBP_2;
2367*4882a593Smuzhiyun 	else if (qos->rxtp.max_sdu > SAR_FB_SIZE_0)
2368*4882a593Smuzhiyun 		rcte |= SAR_RCTE_FBP_1;
2369*4882a593Smuzhiyun 	else
2370*4882a593Smuzhiyun 		rcte |= SAR_RCTE_FBP_01;
2371*4882a593Smuzhiyun 
2372*4882a593Smuzhiyun 	addr = card->rct_base + (vc->index << 2);
2373*4882a593Smuzhiyun 
2374*4882a593Smuzhiyun 	OPRINTK("%s: writing RCT at 0x%lx\n", card->name, addr);
2375*4882a593Smuzhiyun 	write_sram(card, addr, rcte);
2376*4882a593Smuzhiyun 
2377*4882a593Smuzhiyun 	spin_lock_irqsave(&card->cmd_lock, flags);
2378*4882a593Smuzhiyun 	writel(SAR_CMD_OPEN_CONNECTION | (addr << 2), SAR_REG_CMD);
2379*4882a593Smuzhiyun 	waitfor_idle(card);
2380*4882a593Smuzhiyun 	spin_unlock_irqrestore(&card->cmd_lock, flags);
2381*4882a593Smuzhiyun 
2382*4882a593Smuzhiyun 	return 0;
2383*4882a593Smuzhiyun }
2384*4882a593Smuzhiyun 
2385*4882a593Smuzhiyun static int
idt77252_open(struct atm_vcc * vcc)2386*4882a593Smuzhiyun idt77252_open(struct atm_vcc *vcc)
2387*4882a593Smuzhiyun {
2388*4882a593Smuzhiyun 	struct atm_dev *dev = vcc->dev;
2389*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
2390*4882a593Smuzhiyun 	struct vc_map *vc;
2391*4882a593Smuzhiyun 	unsigned int index;
2392*4882a593Smuzhiyun 	unsigned int inuse;
2393*4882a593Smuzhiyun 	int error;
2394*4882a593Smuzhiyun 	int vci = vcc->vci;
2395*4882a593Smuzhiyun 	short vpi = vcc->vpi;
2396*4882a593Smuzhiyun 
2397*4882a593Smuzhiyun 	if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC)
2398*4882a593Smuzhiyun 		return 0;
2399*4882a593Smuzhiyun 
2400*4882a593Smuzhiyun 	if (vpi >= (1 << card->vpibits)) {
2401*4882a593Smuzhiyun 		printk("%s: unsupported VPI: %d\n", card->name, vpi);
2402*4882a593Smuzhiyun 		return -EINVAL;
2403*4882a593Smuzhiyun 	}
2404*4882a593Smuzhiyun 
2405*4882a593Smuzhiyun 	if (vci >= (1 << card->vcibits)) {
2406*4882a593Smuzhiyun 		printk("%s: unsupported VCI: %d\n", card->name, vci);
2407*4882a593Smuzhiyun 		return -EINVAL;
2408*4882a593Smuzhiyun 	}
2409*4882a593Smuzhiyun 
2410*4882a593Smuzhiyun 	set_bit(ATM_VF_ADDR, &vcc->flags);
2411*4882a593Smuzhiyun 
2412*4882a593Smuzhiyun 	mutex_lock(&card->mutex);
2413*4882a593Smuzhiyun 
2414*4882a593Smuzhiyun 	OPRINTK("%s: opening vpi.vci: %d.%d\n", card->name, vpi, vci);
2415*4882a593Smuzhiyun 
2416*4882a593Smuzhiyun 	switch (vcc->qos.aal) {
2417*4882a593Smuzhiyun 	case ATM_AAL0:
2418*4882a593Smuzhiyun 	case ATM_AAL1:
2419*4882a593Smuzhiyun 	case ATM_AAL5:
2420*4882a593Smuzhiyun 		break;
2421*4882a593Smuzhiyun 	default:
2422*4882a593Smuzhiyun 		printk("%s: Unsupported AAL: %d\n", card->name, vcc->qos.aal);
2423*4882a593Smuzhiyun 		mutex_unlock(&card->mutex);
2424*4882a593Smuzhiyun 		return -EPROTONOSUPPORT;
2425*4882a593Smuzhiyun 	}
2426*4882a593Smuzhiyun 
2427*4882a593Smuzhiyun 	index = VPCI2VC(card, vpi, vci);
2428*4882a593Smuzhiyun 	if (!card->vcs[index]) {
2429*4882a593Smuzhiyun 		card->vcs[index] = kzalloc(sizeof(struct vc_map), GFP_KERNEL);
2430*4882a593Smuzhiyun 		if (!card->vcs[index]) {
2431*4882a593Smuzhiyun 			printk("%s: can't alloc vc in open()\n", card->name);
2432*4882a593Smuzhiyun 			mutex_unlock(&card->mutex);
2433*4882a593Smuzhiyun 			return -ENOMEM;
2434*4882a593Smuzhiyun 		}
2435*4882a593Smuzhiyun 		card->vcs[index]->card = card;
2436*4882a593Smuzhiyun 		card->vcs[index]->index = index;
2437*4882a593Smuzhiyun 
2438*4882a593Smuzhiyun 		spin_lock_init(&card->vcs[index]->lock);
2439*4882a593Smuzhiyun 	}
2440*4882a593Smuzhiyun 	vc = card->vcs[index];
2441*4882a593Smuzhiyun 
2442*4882a593Smuzhiyun 	vcc->dev_data = vc;
2443*4882a593Smuzhiyun 
2444*4882a593Smuzhiyun 	IPRINTK("%s: idt77252_open: vc = %d (%d.%d) %s/%s (max RX SDU: %u)\n",
2445*4882a593Smuzhiyun 	        card->name, vc->index, vcc->vpi, vcc->vci,
2446*4882a593Smuzhiyun 	        vcc->qos.rxtp.traffic_class != ATM_NONE ? "rx" : "--",
2447*4882a593Smuzhiyun 	        vcc->qos.txtp.traffic_class != ATM_NONE ? "tx" : "--",
2448*4882a593Smuzhiyun 	        vcc->qos.rxtp.max_sdu);
2449*4882a593Smuzhiyun 
2450*4882a593Smuzhiyun 	inuse = 0;
2451*4882a593Smuzhiyun 	if (vcc->qos.txtp.traffic_class != ATM_NONE &&
2452*4882a593Smuzhiyun 	    test_bit(VCF_TX, &vc->flags))
2453*4882a593Smuzhiyun 		inuse = 1;
2454*4882a593Smuzhiyun 	if (vcc->qos.rxtp.traffic_class != ATM_NONE &&
2455*4882a593Smuzhiyun 	    test_bit(VCF_RX, &vc->flags))
2456*4882a593Smuzhiyun 		inuse += 2;
2457*4882a593Smuzhiyun 
2458*4882a593Smuzhiyun 	if (inuse) {
2459*4882a593Smuzhiyun 		printk("%s: %s vci already in use.\n", card->name,
2460*4882a593Smuzhiyun 		       inuse == 1 ? "tx" : inuse == 2 ? "rx" : "tx and rx");
2461*4882a593Smuzhiyun 		mutex_unlock(&card->mutex);
2462*4882a593Smuzhiyun 		return -EADDRINUSE;
2463*4882a593Smuzhiyun 	}
2464*4882a593Smuzhiyun 
2465*4882a593Smuzhiyun 	if (vcc->qos.txtp.traffic_class != ATM_NONE) {
2466*4882a593Smuzhiyun 		error = idt77252_init_tx(card, vc, vcc, &vcc->qos);
2467*4882a593Smuzhiyun 		if (error) {
2468*4882a593Smuzhiyun 			mutex_unlock(&card->mutex);
2469*4882a593Smuzhiyun 			return error;
2470*4882a593Smuzhiyun 		}
2471*4882a593Smuzhiyun 	}
2472*4882a593Smuzhiyun 
2473*4882a593Smuzhiyun 	if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
2474*4882a593Smuzhiyun 		error = idt77252_init_rx(card, vc, vcc, &vcc->qos);
2475*4882a593Smuzhiyun 		if (error) {
2476*4882a593Smuzhiyun 			mutex_unlock(&card->mutex);
2477*4882a593Smuzhiyun 			return error;
2478*4882a593Smuzhiyun 		}
2479*4882a593Smuzhiyun 	}
2480*4882a593Smuzhiyun 
2481*4882a593Smuzhiyun 	set_bit(ATM_VF_READY, &vcc->flags);
2482*4882a593Smuzhiyun 
2483*4882a593Smuzhiyun 	mutex_unlock(&card->mutex);
2484*4882a593Smuzhiyun 	return 0;
2485*4882a593Smuzhiyun }
2486*4882a593Smuzhiyun 
2487*4882a593Smuzhiyun static void
idt77252_close(struct atm_vcc * vcc)2488*4882a593Smuzhiyun idt77252_close(struct atm_vcc *vcc)
2489*4882a593Smuzhiyun {
2490*4882a593Smuzhiyun 	struct atm_dev *dev = vcc->dev;
2491*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
2492*4882a593Smuzhiyun 	struct vc_map *vc = vcc->dev_data;
2493*4882a593Smuzhiyun 	unsigned long flags;
2494*4882a593Smuzhiyun 	unsigned long addr;
2495*4882a593Smuzhiyun 	unsigned long timeout;
2496*4882a593Smuzhiyun 
2497*4882a593Smuzhiyun 	mutex_lock(&card->mutex);
2498*4882a593Smuzhiyun 
2499*4882a593Smuzhiyun 	IPRINTK("%s: idt77252_close: vc = %d (%d.%d)\n",
2500*4882a593Smuzhiyun 		card->name, vc->index, vcc->vpi, vcc->vci);
2501*4882a593Smuzhiyun 
2502*4882a593Smuzhiyun 	clear_bit(ATM_VF_READY, &vcc->flags);
2503*4882a593Smuzhiyun 
2504*4882a593Smuzhiyun 	if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
2505*4882a593Smuzhiyun 
2506*4882a593Smuzhiyun 		spin_lock_irqsave(&vc->lock, flags);
2507*4882a593Smuzhiyun 		clear_bit(VCF_RX, &vc->flags);
2508*4882a593Smuzhiyun 		vc->rx_vcc = NULL;
2509*4882a593Smuzhiyun 		spin_unlock_irqrestore(&vc->lock, flags);
2510*4882a593Smuzhiyun 
2511*4882a593Smuzhiyun 		if ((vcc->vci == 3) || (vcc->vci == 4))
2512*4882a593Smuzhiyun 			goto done;
2513*4882a593Smuzhiyun 
2514*4882a593Smuzhiyun 		addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE;
2515*4882a593Smuzhiyun 
2516*4882a593Smuzhiyun 		spin_lock_irqsave(&card->cmd_lock, flags);
2517*4882a593Smuzhiyun 		writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2), SAR_REG_CMD);
2518*4882a593Smuzhiyun 		waitfor_idle(card);
2519*4882a593Smuzhiyun 		spin_unlock_irqrestore(&card->cmd_lock, flags);
2520*4882a593Smuzhiyun 
2521*4882a593Smuzhiyun 		if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) {
2522*4882a593Smuzhiyun 			DPRINTK("%s: closing a VC with pending rx buffers.\n",
2523*4882a593Smuzhiyun 				card->name);
2524*4882a593Smuzhiyun 
2525*4882a593Smuzhiyun 			recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
2526*4882a593Smuzhiyun 		}
2527*4882a593Smuzhiyun 	}
2528*4882a593Smuzhiyun 
2529*4882a593Smuzhiyun done:
2530*4882a593Smuzhiyun 	if (vcc->qos.txtp.traffic_class != ATM_NONE) {
2531*4882a593Smuzhiyun 
2532*4882a593Smuzhiyun 		spin_lock_irqsave(&vc->lock, flags);
2533*4882a593Smuzhiyun 		clear_bit(VCF_TX, &vc->flags);
2534*4882a593Smuzhiyun 		clear_bit(VCF_IDLE, &vc->flags);
2535*4882a593Smuzhiyun 		clear_bit(VCF_RSV, &vc->flags);
2536*4882a593Smuzhiyun 		vc->tx_vcc = NULL;
2537*4882a593Smuzhiyun 
2538*4882a593Smuzhiyun 		if (vc->estimator) {
2539*4882a593Smuzhiyun 			del_timer(&vc->estimator->timer);
2540*4882a593Smuzhiyun 			kfree(vc->estimator);
2541*4882a593Smuzhiyun 			vc->estimator = NULL;
2542*4882a593Smuzhiyun 		}
2543*4882a593Smuzhiyun 		spin_unlock_irqrestore(&vc->lock, flags);
2544*4882a593Smuzhiyun 
2545*4882a593Smuzhiyun 		timeout = 5 * 1000;
2546*4882a593Smuzhiyun 		while (atomic_read(&vc->scq->used) > 0) {
2547*4882a593Smuzhiyun 			timeout = msleep_interruptible(timeout);
2548*4882a593Smuzhiyun 			if (!timeout) {
2549*4882a593Smuzhiyun 				pr_warn("%s: SCQ drain timeout: %u used\n",
2550*4882a593Smuzhiyun 					card->name, atomic_read(&vc->scq->used));
2551*4882a593Smuzhiyun 				break;
2552*4882a593Smuzhiyun 			}
2553*4882a593Smuzhiyun 		}
2554*4882a593Smuzhiyun 
2555*4882a593Smuzhiyun 		writel(TCMDQ_HALT | vc->index, SAR_REG_TCMDQ);
2556*4882a593Smuzhiyun 		clear_scd(card, vc->scq, vc->class);
2557*4882a593Smuzhiyun 
2558*4882a593Smuzhiyun 		if (vc->class == SCHED_CBR) {
2559*4882a593Smuzhiyun 			clear_tst(card, vc);
2560*4882a593Smuzhiyun 			card->tst_free += vc->ntste;
2561*4882a593Smuzhiyun 			vc->ntste = 0;
2562*4882a593Smuzhiyun 		}
2563*4882a593Smuzhiyun 
2564*4882a593Smuzhiyun 		card->scd2vc[vc->scd_index] = NULL;
2565*4882a593Smuzhiyun 		free_scq(card, vc->scq);
2566*4882a593Smuzhiyun 	}
2567*4882a593Smuzhiyun 
2568*4882a593Smuzhiyun 	mutex_unlock(&card->mutex);
2569*4882a593Smuzhiyun }
2570*4882a593Smuzhiyun 
2571*4882a593Smuzhiyun static int
idt77252_change_qos(struct atm_vcc * vcc,struct atm_qos * qos,int flags)2572*4882a593Smuzhiyun idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
2573*4882a593Smuzhiyun {
2574*4882a593Smuzhiyun 	struct atm_dev *dev = vcc->dev;
2575*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
2576*4882a593Smuzhiyun 	struct vc_map *vc = vcc->dev_data;
2577*4882a593Smuzhiyun 	int error = 0;
2578*4882a593Smuzhiyun 
2579*4882a593Smuzhiyun 	mutex_lock(&card->mutex);
2580*4882a593Smuzhiyun 
2581*4882a593Smuzhiyun 	if (qos->txtp.traffic_class != ATM_NONE) {
2582*4882a593Smuzhiyun 	    	if (!test_bit(VCF_TX, &vc->flags)) {
2583*4882a593Smuzhiyun 			error = idt77252_init_tx(card, vc, vcc, qos);
2584*4882a593Smuzhiyun 			if (error)
2585*4882a593Smuzhiyun 				goto out;
2586*4882a593Smuzhiyun 		} else {
2587*4882a593Smuzhiyun 			switch (qos->txtp.traffic_class) {
2588*4882a593Smuzhiyun 			case ATM_CBR:
2589*4882a593Smuzhiyun 				error = idt77252_init_cbr(card, vc, vcc, qos);
2590*4882a593Smuzhiyun 				if (error)
2591*4882a593Smuzhiyun 					goto out;
2592*4882a593Smuzhiyun 				break;
2593*4882a593Smuzhiyun 
2594*4882a593Smuzhiyun 			case ATM_UBR:
2595*4882a593Smuzhiyun 				error = idt77252_init_ubr(card, vc, vcc, qos);
2596*4882a593Smuzhiyun 				if (error)
2597*4882a593Smuzhiyun 					goto out;
2598*4882a593Smuzhiyun 
2599*4882a593Smuzhiyun 				if (!test_bit(VCF_IDLE, &vc->flags)) {
2600*4882a593Smuzhiyun 					writel(TCMDQ_LACR | (vc->lacr << 16) |
2601*4882a593Smuzhiyun 					       vc->index, SAR_REG_TCMDQ);
2602*4882a593Smuzhiyun 				}
2603*4882a593Smuzhiyun 				break;
2604*4882a593Smuzhiyun 
2605*4882a593Smuzhiyun 			case ATM_VBR:
2606*4882a593Smuzhiyun 			case ATM_ABR:
2607*4882a593Smuzhiyun 				error = -EOPNOTSUPP;
2608*4882a593Smuzhiyun 				goto out;
2609*4882a593Smuzhiyun 			}
2610*4882a593Smuzhiyun 		}
2611*4882a593Smuzhiyun 	}
2612*4882a593Smuzhiyun 
2613*4882a593Smuzhiyun 	if ((qos->rxtp.traffic_class != ATM_NONE) &&
2614*4882a593Smuzhiyun 	    !test_bit(VCF_RX, &vc->flags)) {
2615*4882a593Smuzhiyun 		error = idt77252_init_rx(card, vc, vcc, qos);
2616*4882a593Smuzhiyun 		if (error)
2617*4882a593Smuzhiyun 			goto out;
2618*4882a593Smuzhiyun 	}
2619*4882a593Smuzhiyun 
2620*4882a593Smuzhiyun 	memcpy(&vcc->qos, qos, sizeof(struct atm_qos));
2621*4882a593Smuzhiyun 
2622*4882a593Smuzhiyun 	set_bit(ATM_VF_HASQOS, &vcc->flags);
2623*4882a593Smuzhiyun 
2624*4882a593Smuzhiyun out:
2625*4882a593Smuzhiyun 	mutex_unlock(&card->mutex);
2626*4882a593Smuzhiyun 	return error;
2627*4882a593Smuzhiyun }
2628*4882a593Smuzhiyun 
2629*4882a593Smuzhiyun static int
idt77252_proc_read(struct atm_dev * dev,loff_t * pos,char * page)2630*4882a593Smuzhiyun idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page)
2631*4882a593Smuzhiyun {
2632*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
2633*4882a593Smuzhiyun 	int i, left;
2634*4882a593Smuzhiyun 
2635*4882a593Smuzhiyun 	left = (int) *pos;
2636*4882a593Smuzhiyun 	if (!left--)
2637*4882a593Smuzhiyun 		return sprintf(page, "IDT77252 Interrupts:\n");
2638*4882a593Smuzhiyun 	if (!left--)
2639*4882a593Smuzhiyun 		return sprintf(page, "TSIF:  %lu\n", card->irqstat[15]);
2640*4882a593Smuzhiyun 	if (!left--)
2641*4882a593Smuzhiyun 		return sprintf(page, "TXICP: %lu\n", card->irqstat[14]);
2642*4882a593Smuzhiyun 	if (!left--)
2643*4882a593Smuzhiyun 		return sprintf(page, "TSQF:  %lu\n", card->irqstat[12]);
2644*4882a593Smuzhiyun 	if (!left--)
2645*4882a593Smuzhiyun 		return sprintf(page, "TMROF: %lu\n", card->irqstat[11]);
2646*4882a593Smuzhiyun 	if (!left--)
2647*4882a593Smuzhiyun 		return sprintf(page, "PHYI:  %lu\n", card->irqstat[10]);
2648*4882a593Smuzhiyun 	if (!left--)
2649*4882a593Smuzhiyun 		return sprintf(page, "FBQ3A: %lu\n", card->irqstat[8]);
2650*4882a593Smuzhiyun 	if (!left--)
2651*4882a593Smuzhiyun 		return sprintf(page, "FBQ2A: %lu\n", card->irqstat[7]);
2652*4882a593Smuzhiyun 	if (!left--)
2653*4882a593Smuzhiyun 		return sprintf(page, "RSQF:  %lu\n", card->irqstat[6]);
2654*4882a593Smuzhiyun 	if (!left--)
2655*4882a593Smuzhiyun 		return sprintf(page, "EPDU:  %lu\n", card->irqstat[5]);
2656*4882a593Smuzhiyun 	if (!left--)
2657*4882a593Smuzhiyun 		return sprintf(page, "RAWCF: %lu\n", card->irqstat[4]);
2658*4882a593Smuzhiyun 	if (!left--)
2659*4882a593Smuzhiyun 		return sprintf(page, "FBQ1A: %lu\n", card->irqstat[3]);
2660*4882a593Smuzhiyun 	if (!left--)
2661*4882a593Smuzhiyun 		return sprintf(page, "FBQ0A: %lu\n", card->irqstat[2]);
2662*4882a593Smuzhiyun 	if (!left--)
2663*4882a593Smuzhiyun 		return sprintf(page, "RSQAF: %lu\n", card->irqstat[1]);
2664*4882a593Smuzhiyun 	if (!left--)
2665*4882a593Smuzhiyun 		return sprintf(page, "IDT77252 Transmit Connection Table:\n");
2666*4882a593Smuzhiyun 
2667*4882a593Smuzhiyun 	for (i = 0; i < card->tct_size; i++) {
2668*4882a593Smuzhiyun 		unsigned long tct;
2669*4882a593Smuzhiyun 		struct atm_vcc *vcc;
2670*4882a593Smuzhiyun 		struct vc_map *vc;
2671*4882a593Smuzhiyun 		char *p;
2672*4882a593Smuzhiyun 
2673*4882a593Smuzhiyun 		vc = card->vcs[i];
2674*4882a593Smuzhiyun 		if (!vc)
2675*4882a593Smuzhiyun 			continue;
2676*4882a593Smuzhiyun 
2677*4882a593Smuzhiyun 		vcc = NULL;
2678*4882a593Smuzhiyun 		if (vc->tx_vcc)
2679*4882a593Smuzhiyun 			vcc = vc->tx_vcc;
2680*4882a593Smuzhiyun 		if (!vcc)
2681*4882a593Smuzhiyun 			continue;
2682*4882a593Smuzhiyun 		if (left--)
2683*4882a593Smuzhiyun 			continue;
2684*4882a593Smuzhiyun 
2685*4882a593Smuzhiyun 		p = page;
2686*4882a593Smuzhiyun 		p += sprintf(p, "  %4u: %u.%u: ", i, vcc->vpi, vcc->vci);
2687*4882a593Smuzhiyun 		tct = (unsigned long) (card->tct_base + i * SAR_SRAM_TCT_SIZE);
2688*4882a593Smuzhiyun 
2689*4882a593Smuzhiyun 		for (i = 0; i < 8; i++)
2690*4882a593Smuzhiyun 			p += sprintf(p, " %08x", read_sram(card, tct + i));
2691*4882a593Smuzhiyun 		p += sprintf(p, "\n");
2692*4882a593Smuzhiyun 		return p - page;
2693*4882a593Smuzhiyun 	}
2694*4882a593Smuzhiyun 	return 0;
2695*4882a593Smuzhiyun }
2696*4882a593Smuzhiyun 
2697*4882a593Smuzhiyun /*****************************************************************************/
2698*4882a593Smuzhiyun /*                                                                           */
2699*4882a593Smuzhiyun /* Interrupt handler                                                         */
2700*4882a593Smuzhiyun /*                                                                           */
2701*4882a593Smuzhiyun /*****************************************************************************/
2702*4882a593Smuzhiyun 
2703*4882a593Smuzhiyun static void
idt77252_collect_stat(struct idt77252_dev * card)2704*4882a593Smuzhiyun idt77252_collect_stat(struct idt77252_dev *card)
2705*4882a593Smuzhiyun {
2706*4882a593Smuzhiyun 	(void) readl(SAR_REG_CDC);
2707*4882a593Smuzhiyun 	(void) readl(SAR_REG_VPEC);
2708*4882a593Smuzhiyun 	(void) readl(SAR_REG_ICC);
2709*4882a593Smuzhiyun 
2710*4882a593Smuzhiyun }
2711*4882a593Smuzhiyun 
2712*4882a593Smuzhiyun static irqreturn_t
idt77252_interrupt(int irq,void * dev_id)2713*4882a593Smuzhiyun idt77252_interrupt(int irq, void *dev_id)
2714*4882a593Smuzhiyun {
2715*4882a593Smuzhiyun 	struct idt77252_dev *card = dev_id;
2716*4882a593Smuzhiyun 	u32 stat;
2717*4882a593Smuzhiyun 
2718*4882a593Smuzhiyun 	stat = readl(SAR_REG_STAT) & 0xffff;
2719*4882a593Smuzhiyun 	if (!stat)	/* no interrupt for us */
2720*4882a593Smuzhiyun 		return IRQ_NONE;
2721*4882a593Smuzhiyun 
2722*4882a593Smuzhiyun 	if (test_and_set_bit(IDT77252_BIT_INTERRUPT, &card->flags)) {
2723*4882a593Smuzhiyun 		printk("%s: Re-entering irq_handler()\n", card->name);
2724*4882a593Smuzhiyun 		goto out;
2725*4882a593Smuzhiyun 	}
2726*4882a593Smuzhiyun 
2727*4882a593Smuzhiyun 	writel(stat, SAR_REG_STAT);	/* reset interrupt */
2728*4882a593Smuzhiyun 
2729*4882a593Smuzhiyun 	if (stat & SAR_STAT_TSIF) {	/* entry written to TSQ  */
2730*4882a593Smuzhiyun 		INTPRINTK("%s: TSIF\n", card->name);
2731*4882a593Smuzhiyun 		card->irqstat[15]++;
2732*4882a593Smuzhiyun 		idt77252_tx(card);
2733*4882a593Smuzhiyun 	}
2734*4882a593Smuzhiyun 	if (stat & SAR_STAT_TXICP) {	/* Incomplete CS-PDU has  */
2735*4882a593Smuzhiyun 		INTPRINTK("%s: TXICP\n", card->name);
2736*4882a593Smuzhiyun 		card->irqstat[14]++;
2737*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_DEBUG
2738*4882a593Smuzhiyun 		idt77252_tx_dump(card);
2739*4882a593Smuzhiyun #endif
2740*4882a593Smuzhiyun 	}
2741*4882a593Smuzhiyun 	if (stat & SAR_STAT_TSQF) {	/* TSQ 7/8 full           */
2742*4882a593Smuzhiyun 		INTPRINTK("%s: TSQF\n", card->name);
2743*4882a593Smuzhiyun 		card->irqstat[12]++;
2744*4882a593Smuzhiyun 		idt77252_tx(card);
2745*4882a593Smuzhiyun 	}
2746*4882a593Smuzhiyun 	if (stat & SAR_STAT_TMROF) {	/* Timer overflow         */
2747*4882a593Smuzhiyun 		INTPRINTK("%s: TMROF\n", card->name);
2748*4882a593Smuzhiyun 		card->irqstat[11]++;
2749*4882a593Smuzhiyun 		idt77252_collect_stat(card);
2750*4882a593Smuzhiyun 	}
2751*4882a593Smuzhiyun 
2752*4882a593Smuzhiyun 	if (stat & SAR_STAT_EPDU) {	/* Got complete CS-PDU    */
2753*4882a593Smuzhiyun 		INTPRINTK("%s: EPDU\n", card->name);
2754*4882a593Smuzhiyun 		card->irqstat[5]++;
2755*4882a593Smuzhiyun 		idt77252_rx(card);
2756*4882a593Smuzhiyun 	}
2757*4882a593Smuzhiyun 	if (stat & SAR_STAT_RSQAF) {	/* RSQ is 7/8 full        */
2758*4882a593Smuzhiyun 		INTPRINTK("%s: RSQAF\n", card->name);
2759*4882a593Smuzhiyun 		card->irqstat[1]++;
2760*4882a593Smuzhiyun 		idt77252_rx(card);
2761*4882a593Smuzhiyun 	}
2762*4882a593Smuzhiyun 	if (stat & SAR_STAT_RSQF) {	/* RSQ is full            */
2763*4882a593Smuzhiyun 		INTPRINTK("%s: RSQF\n", card->name);
2764*4882a593Smuzhiyun 		card->irqstat[6]++;
2765*4882a593Smuzhiyun 		idt77252_rx(card);
2766*4882a593Smuzhiyun 	}
2767*4882a593Smuzhiyun 	if (stat & SAR_STAT_RAWCF) {	/* Raw cell received      */
2768*4882a593Smuzhiyun 		INTPRINTK("%s: RAWCF\n", card->name);
2769*4882a593Smuzhiyun 		card->irqstat[4]++;
2770*4882a593Smuzhiyun 		idt77252_rx_raw(card);
2771*4882a593Smuzhiyun 	}
2772*4882a593Smuzhiyun 
2773*4882a593Smuzhiyun 	if (stat & SAR_STAT_PHYI) {	/* PHY device interrupt   */
2774*4882a593Smuzhiyun 		INTPRINTK("%s: PHYI", card->name);
2775*4882a593Smuzhiyun 		card->irqstat[10]++;
2776*4882a593Smuzhiyun 		if (card->atmdev->phy && card->atmdev->phy->interrupt)
2777*4882a593Smuzhiyun 			card->atmdev->phy->interrupt(card->atmdev);
2778*4882a593Smuzhiyun 	}
2779*4882a593Smuzhiyun 
2780*4882a593Smuzhiyun 	if (stat & (SAR_STAT_FBQ0A | SAR_STAT_FBQ1A |
2781*4882a593Smuzhiyun 		    SAR_STAT_FBQ2A | SAR_STAT_FBQ3A)) {
2782*4882a593Smuzhiyun 
2783*4882a593Smuzhiyun 		writel(readl(SAR_REG_CFG) & ~(SAR_CFG_FBIE), SAR_REG_CFG);
2784*4882a593Smuzhiyun 
2785*4882a593Smuzhiyun 		INTPRINTK("%s: FBQA: %04x\n", card->name, stat);
2786*4882a593Smuzhiyun 
2787*4882a593Smuzhiyun 		if (stat & SAR_STAT_FBQ0A)
2788*4882a593Smuzhiyun 			card->irqstat[2]++;
2789*4882a593Smuzhiyun 		if (stat & SAR_STAT_FBQ1A)
2790*4882a593Smuzhiyun 			card->irqstat[3]++;
2791*4882a593Smuzhiyun 		if (stat & SAR_STAT_FBQ2A)
2792*4882a593Smuzhiyun 			card->irqstat[7]++;
2793*4882a593Smuzhiyun 		if (stat & SAR_STAT_FBQ3A)
2794*4882a593Smuzhiyun 			card->irqstat[8]++;
2795*4882a593Smuzhiyun 
2796*4882a593Smuzhiyun 		schedule_work(&card->tqueue);
2797*4882a593Smuzhiyun 	}
2798*4882a593Smuzhiyun 
2799*4882a593Smuzhiyun out:
2800*4882a593Smuzhiyun 	clear_bit(IDT77252_BIT_INTERRUPT, &card->flags);
2801*4882a593Smuzhiyun 	return IRQ_HANDLED;
2802*4882a593Smuzhiyun }
2803*4882a593Smuzhiyun 
2804*4882a593Smuzhiyun static void
idt77252_softint(struct work_struct * work)2805*4882a593Smuzhiyun idt77252_softint(struct work_struct *work)
2806*4882a593Smuzhiyun {
2807*4882a593Smuzhiyun 	struct idt77252_dev *card =
2808*4882a593Smuzhiyun 		container_of(work, struct idt77252_dev, tqueue);
2809*4882a593Smuzhiyun 	u32 stat;
2810*4882a593Smuzhiyun 	int done;
2811*4882a593Smuzhiyun 
2812*4882a593Smuzhiyun 	for (done = 1; ; done = 1) {
2813*4882a593Smuzhiyun 		stat = readl(SAR_REG_STAT) >> 16;
2814*4882a593Smuzhiyun 
2815*4882a593Smuzhiyun 		if ((stat & 0x0f) < SAR_FBQ0_HIGH) {
2816*4882a593Smuzhiyun 			add_rx_skb(card, 0, SAR_FB_SIZE_0, 32);
2817*4882a593Smuzhiyun 			done = 0;
2818*4882a593Smuzhiyun 		}
2819*4882a593Smuzhiyun 
2820*4882a593Smuzhiyun 		stat >>= 4;
2821*4882a593Smuzhiyun 		if ((stat & 0x0f) < SAR_FBQ1_HIGH) {
2822*4882a593Smuzhiyun 			add_rx_skb(card, 1, SAR_FB_SIZE_1, 32);
2823*4882a593Smuzhiyun 			done = 0;
2824*4882a593Smuzhiyun 		}
2825*4882a593Smuzhiyun 
2826*4882a593Smuzhiyun 		stat >>= 4;
2827*4882a593Smuzhiyun 		if ((stat & 0x0f) < SAR_FBQ2_HIGH) {
2828*4882a593Smuzhiyun 			add_rx_skb(card, 2, SAR_FB_SIZE_2, 32);
2829*4882a593Smuzhiyun 			done = 0;
2830*4882a593Smuzhiyun 		}
2831*4882a593Smuzhiyun 
2832*4882a593Smuzhiyun 		stat >>= 4;
2833*4882a593Smuzhiyun 		if ((stat & 0x0f) < SAR_FBQ3_HIGH) {
2834*4882a593Smuzhiyun 			add_rx_skb(card, 3, SAR_FB_SIZE_3, 32);
2835*4882a593Smuzhiyun 			done = 0;
2836*4882a593Smuzhiyun 		}
2837*4882a593Smuzhiyun 
2838*4882a593Smuzhiyun 		if (done)
2839*4882a593Smuzhiyun 			break;
2840*4882a593Smuzhiyun 	}
2841*4882a593Smuzhiyun 
2842*4882a593Smuzhiyun 	writel(readl(SAR_REG_CFG) | SAR_CFG_FBIE, SAR_REG_CFG);
2843*4882a593Smuzhiyun }
2844*4882a593Smuzhiyun 
2845*4882a593Smuzhiyun 
2846*4882a593Smuzhiyun static int
open_card_oam(struct idt77252_dev * card)2847*4882a593Smuzhiyun open_card_oam(struct idt77252_dev *card)
2848*4882a593Smuzhiyun {
2849*4882a593Smuzhiyun 	unsigned long flags;
2850*4882a593Smuzhiyun 	unsigned long addr;
2851*4882a593Smuzhiyun 	struct vc_map *vc;
2852*4882a593Smuzhiyun 	int vpi, vci;
2853*4882a593Smuzhiyun 	int index;
2854*4882a593Smuzhiyun 	u32 rcte;
2855*4882a593Smuzhiyun 
2856*4882a593Smuzhiyun 	for (vpi = 0; vpi < (1 << card->vpibits); vpi++) {
2857*4882a593Smuzhiyun 		for (vci = 3; vci < 5; vci++) {
2858*4882a593Smuzhiyun 			index = VPCI2VC(card, vpi, vci);
2859*4882a593Smuzhiyun 
2860*4882a593Smuzhiyun 			vc = kzalloc(sizeof(struct vc_map), GFP_KERNEL);
2861*4882a593Smuzhiyun 			if (!vc) {
2862*4882a593Smuzhiyun 				printk("%s: can't alloc vc\n", card->name);
2863*4882a593Smuzhiyun 				return -ENOMEM;
2864*4882a593Smuzhiyun 			}
2865*4882a593Smuzhiyun 			vc->index = index;
2866*4882a593Smuzhiyun 			card->vcs[index] = vc;
2867*4882a593Smuzhiyun 
2868*4882a593Smuzhiyun 			flush_rx_pool(card, &vc->rcv.rx_pool);
2869*4882a593Smuzhiyun 
2870*4882a593Smuzhiyun 			rcte = SAR_RCTE_CONNECTOPEN |
2871*4882a593Smuzhiyun 			       SAR_RCTE_RAWCELLINTEN |
2872*4882a593Smuzhiyun 			       SAR_RCTE_RCQ |
2873*4882a593Smuzhiyun 			       SAR_RCTE_FBP_1;
2874*4882a593Smuzhiyun 
2875*4882a593Smuzhiyun 			addr = card->rct_base + (vc->index << 2);
2876*4882a593Smuzhiyun 			write_sram(card, addr, rcte);
2877*4882a593Smuzhiyun 
2878*4882a593Smuzhiyun 			spin_lock_irqsave(&card->cmd_lock, flags);
2879*4882a593Smuzhiyun 			writel(SAR_CMD_OPEN_CONNECTION | (addr << 2),
2880*4882a593Smuzhiyun 			       SAR_REG_CMD);
2881*4882a593Smuzhiyun 			waitfor_idle(card);
2882*4882a593Smuzhiyun 			spin_unlock_irqrestore(&card->cmd_lock, flags);
2883*4882a593Smuzhiyun 		}
2884*4882a593Smuzhiyun 	}
2885*4882a593Smuzhiyun 
2886*4882a593Smuzhiyun 	return 0;
2887*4882a593Smuzhiyun }
2888*4882a593Smuzhiyun 
2889*4882a593Smuzhiyun static void
close_card_oam(struct idt77252_dev * card)2890*4882a593Smuzhiyun close_card_oam(struct idt77252_dev *card)
2891*4882a593Smuzhiyun {
2892*4882a593Smuzhiyun 	unsigned long flags;
2893*4882a593Smuzhiyun 	unsigned long addr;
2894*4882a593Smuzhiyun 	struct vc_map *vc;
2895*4882a593Smuzhiyun 	int vpi, vci;
2896*4882a593Smuzhiyun 	int index;
2897*4882a593Smuzhiyun 
2898*4882a593Smuzhiyun 	for (vpi = 0; vpi < (1 << card->vpibits); vpi++) {
2899*4882a593Smuzhiyun 		for (vci = 3; vci < 5; vci++) {
2900*4882a593Smuzhiyun 			index = VPCI2VC(card, vpi, vci);
2901*4882a593Smuzhiyun 			vc = card->vcs[index];
2902*4882a593Smuzhiyun 
2903*4882a593Smuzhiyun 			addr = card->rct_base + vc->index * SAR_SRAM_RCT_SIZE;
2904*4882a593Smuzhiyun 
2905*4882a593Smuzhiyun 			spin_lock_irqsave(&card->cmd_lock, flags);
2906*4882a593Smuzhiyun 			writel(SAR_CMD_CLOSE_CONNECTION | (addr << 2),
2907*4882a593Smuzhiyun 			       SAR_REG_CMD);
2908*4882a593Smuzhiyun 			waitfor_idle(card);
2909*4882a593Smuzhiyun 			spin_unlock_irqrestore(&card->cmd_lock, flags);
2910*4882a593Smuzhiyun 
2911*4882a593Smuzhiyun 			if (skb_queue_len(&vc->rcv.rx_pool.queue) != 0) {
2912*4882a593Smuzhiyun 				DPRINTK("%s: closing a VC "
2913*4882a593Smuzhiyun 					"with pending rx buffers.\n",
2914*4882a593Smuzhiyun 					card->name);
2915*4882a593Smuzhiyun 
2916*4882a593Smuzhiyun 				recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
2917*4882a593Smuzhiyun 			}
2918*4882a593Smuzhiyun 		}
2919*4882a593Smuzhiyun 	}
2920*4882a593Smuzhiyun }
2921*4882a593Smuzhiyun 
2922*4882a593Smuzhiyun static int
open_card_ubr0(struct idt77252_dev * card)2923*4882a593Smuzhiyun open_card_ubr0(struct idt77252_dev *card)
2924*4882a593Smuzhiyun {
2925*4882a593Smuzhiyun 	struct vc_map *vc;
2926*4882a593Smuzhiyun 
2927*4882a593Smuzhiyun 	vc = kzalloc(sizeof(struct vc_map), GFP_KERNEL);
2928*4882a593Smuzhiyun 	if (!vc) {
2929*4882a593Smuzhiyun 		printk("%s: can't alloc vc\n", card->name);
2930*4882a593Smuzhiyun 		return -ENOMEM;
2931*4882a593Smuzhiyun 	}
2932*4882a593Smuzhiyun 	card->vcs[0] = vc;
2933*4882a593Smuzhiyun 	vc->class = SCHED_UBR0;
2934*4882a593Smuzhiyun 
2935*4882a593Smuzhiyun 	vc->scq = alloc_scq(card, vc->class);
2936*4882a593Smuzhiyun 	if (!vc->scq) {
2937*4882a593Smuzhiyun 		printk("%s: can't get SCQ.\n", card->name);
2938*4882a593Smuzhiyun 		return -ENOMEM;
2939*4882a593Smuzhiyun 	}
2940*4882a593Smuzhiyun 
2941*4882a593Smuzhiyun 	card->scd2vc[0] = vc;
2942*4882a593Smuzhiyun 	vc->scd_index = 0;
2943*4882a593Smuzhiyun 	vc->scq->scd = card->scd_base;
2944*4882a593Smuzhiyun 
2945*4882a593Smuzhiyun 	fill_scd(card, vc->scq, vc->class);
2946*4882a593Smuzhiyun 
2947*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 0, TCT_UBR | card->scd_base);
2948*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 1, 0);
2949*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 2, 0);
2950*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 3, 0);
2951*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 4, 0);
2952*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 5, 0);
2953*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 6, 0);
2954*4882a593Smuzhiyun 	write_sram(card, card->tct_base + 7, TCT_FLAG_UBR);
2955*4882a593Smuzhiyun 
2956*4882a593Smuzhiyun 	clear_bit(VCF_IDLE, &vc->flags);
2957*4882a593Smuzhiyun 	writel(TCMDQ_START | 0, SAR_REG_TCMDQ);
2958*4882a593Smuzhiyun 	return 0;
2959*4882a593Smuzhiyun }
2960*4882a593Smuzhiyun 
2961*4882a593Smuzhiyun static int
idt77252_dev_open(struct idt77252_dev * card)2962*4882a593Smuzhiyun idt77252_dev_open(struct idt77252_dev *card)
2963*4882a593Smuzhiyun {
2964*4882a593Smuzhiyun 	u32 conf;
2965*4882a593Smuzhiyun 
2966*4882a593Smuzhiyun 	if (!test_bit(IDT77252_BIT_INIT, &card->flags)) {
2967*4882a593Smuzhiyun 		printk("%s: SAR not yet initialized.\n", card->name);
2968*4882a593Smuzhiyun 		return -1;
2969*4882a593Smuzhiyun 	}
2970*4882a593Smuzhiyun 
2971*4882a593Smuzhiyun 	conf = SAR_CFG_RXPTH|	/* enable receive path                  */
2972*4882a593Smuzhiyun 	    SAR_RX_DELAY |	/* interrupt on complete PDU		*/
2973*4882a593Smuzhiyun 	    SAR_CFG_RAWIE |	/* interrupt enable on raw cells        */
2974*4882a593Smuzhiyun 	    SAR_CFG_RQFIE |	/* interrupt on RSQ almost full         */
2975*4882a593Smuzhiyun 	    SAR_CFG_TMOIE |	/* interrupt on timer overflow          */
2976*4882a593Smuzhiyun 	    SAR_CFG_FBIE |	/* interrupt on low free buffers        */
2977*4882a593Smuzhiyun 	    SAR_CFG_TXEN |	/* transmit operation enable            */
2978*4882a593Smuzhiyun 	    SAR_CFG_TXINT |	/* interrupt on transmit status         */
2979*4882a593Smuzhiyun 	    SAR_CFG_TXUIE |	/* interrupt on transmit underrun       */
2980*4882a593Smuzhiyun 	    SAR_CFG_TXSFI |	/* interrupt on TSQ almost full         */
2981*4882a593Smuzhiyun 	    SAR_CFG_PHYIE	/* enable PHY interrupts		*/
2982*4882a593Smuzhiyun 	    ;
2983*4882a593Smuzhiyun 
2984*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_RCV_ALL
2985*4882a593Smuzhiyun 	/* Test RAW cell receive. */
2986*4882a593Smuzhiyun 	conf |= SAR_CFG_VPECA;
2987*4882a593Smuzhiyun #endif
2988*4882a593Smuzhiyun 
2989*4882a593Smuzhiyun 	writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
2990*4882a593Smuzhiyun 
2991*4882a593Smuzhiyun 	if (open_card_oam(card)) {
2992*4882a593Smuzhiyun 		printk("%s: Error initializing OAM.\n", card->name);
2993*4882a593Smuzhiyun 		return -1;
2994*4882a593Smuzhiyun 	}
2995*4882a593Smuzhiyun 
2996*4882a593Smuzhiyun 	if (open_card_ubr0(card)) {
2997*4882a593Smuzhiyun 		printk("%s: Error initializing UBR0.\n", card->name);
2998*4882a593Smuzhiyun 		return -1;
2999*4882a593Smuzhiyun 	}
3000*4882a593Smuzhiyun 
3001*4882a593Smuzhiyun 	IPRINTK("%s: opened IDT77252 ABR SAR.\n", card->name);
3002*4882a593Smuzhiyun 	return 0;
3003*4882a593Smuzhiyun }
3004*4882a593Smuzhiyun 
idt77252_dev_close(struct atm_dev * dev)3005*4882a593Smuzhiyun static void idt77252_dev_close(struct atm_dev *dev)
3006*4882a593Smuzhiyun {
3007*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
3008*4882a593Smuzhiyun 	u32 conf;
3009*4882a593Smuzhiyun 
3010*4882a593Smuzhiyun 	close_card_oam(card);
3011*4882a593Smuzhiyun 
3012*4882a593Smuzhiyun 	conf = SAR_CFG_RXPTH |	/* enable receive path           */
3013*4882a593Smuzhiyun 	    SAR_RX_DELAY |	/* interrupt on complete PDU     */
3014*4882a593Smuzhiyun 	    SAR_CFG_RAWIE |	/* interrupt enable on raw cells */
3015*4882a593Smuzhiyun 	    SAR_CFG_RQFIE |	/* interrupt on RSQ almost full  */
3016*4882a593Smuzhiyun 	    SAR_CFG_TMOIE |	/* interrupt on timer overflow   */
3017*4882a593Smuzhiyun 	    SAR_CFG_FBIE |	/* interrupt on low free buffers */
3018*4882a593Smuzhiyun 	    SAR_CFG_TXEN |	/* transmit operation enable     */
3019*4882a593Smuzhiyun 	    SAR_CFG_TXINT |	/* interrupt on transmit status  */
3020*4882a593Smuzhiyun 	    SAR_CFG_TXUIE |	/* interrupt on xmit underrun    */
3021*4882a593Smuzhiyun 	    SAR_CFG_TXSFI	/* interrupt on TSQ almost full  */
3022*4882a593Smuzhiyun 	    ;
3023*4882a593Smuzhiyun 
3024*4882a593Smuzhiyun 	writel(readl(SAR_REG_CFG) & ~(conf), SAR_REG_CFG);
3025*4882a593Smuzhiyun 
3026*4882a593Smuzhiyun 	DIPRINTK("%s: closed IDT77252 ABR SAR.\n", card->name);
3027*4882a593Smuzhiyun }
3028*4882a593Smuzhiyun 
3029*4882a593Smuzhiyun 
3030*4882a593Smuzhiyun /*****************************************************************************/
3031*4882a593Smuzhiyun /*                                                                           */
3032*4882a593Smuzhiyun /* Initialisation and Deinitialization of IDT77252                           */
3033*4882a593Smuzhiyun /*                                                                           */
3034*4882a593Smuzhiyun /*****************************************************************************/
3035*4882a593Smuzhiyun 
3036*4882a593Smuzhiyun 
3037*4882a593Smuzhiyun static void
deinit_card(struct idt77252_dev * card)3038*4882a593Smuzhiyun deinit_card(struct idt77252_dev *card)
3039*4882a593Smuzhiyun {
3040*4882a593Smuzhiyun 	struct sk_buff *skb;
3041*4882a593Smuzhiyun 	int i, j;
3042*4882a593Smuzhiyun 
3043*4882a593Smuzhiyun 	if (!test_bit(IDT77252_BIT_INIT, &card->flags)) {
3044*4882a593Smuzhiyun 		printk("%s: SAR not yet initialized.\n", card->name);
3045*4882a593Smuzhiyun 		return;
3046*4882a593Smuzhiyun 	}
3047*4882a593Smuzhiyun 	DIPRINTK("idt77252: deinitialize card %u\n", card->index);
3048*4882a593Smuzhiyun 
3049*4882a593Smuzhiyun 	writel(0, SAR_REG_CFG);
3050*4882a593Smuzhiyun 
3051*4882a593Smuzhiyun 	if (card->atmdev)
3052*4882a593Smuzhiyun 		atm_dev_deregister(card->atmdev);
3053*4882a593Smuzhiyun 
3054*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
3055*4882a593Smuzhiyun 		for (j = 0; j < FBQ_SIZE; j++) {
3056*4882a593Smuzhiyun 			skb = card->sbpool[i].skb[j];
3057*4882a593Smuzhiyun 			if (skb) {
3058*4882a593Smuzhiyun 				dma_unmap_single(&card->pcidev->dev,
3059*4882a593Smuzhiyun 						 IDT77252_PRV_PADDR(skb),
3060*4882a593Smuzhiyun 						 (skb_end_pointer(skb) -
3061*4882a593Smuzhiyun 						  skb->data),
3062*4882a593Smuzhiyun 						 DMA_FROM_DEVICE);
3063*4882a593Smuzhiyun 				card->sbpool[i].skb[j] = NULL;
3064*4882a593Smuzhiyun 				dev_kfree_skb(skb);
3065*4882a593Smuzhiyun 			}
3066*4882a593Smuzhiyun 		}
3067*4882a593Smuzhiyun 	}
3068*4882a593Smuzhiyun 
3069*4882a593Smuzhiyun 	vfree(card->soft_tst);
3070*4882a593Smuzhiyun 
3071*4882a593Smuzhiyun 	vfree(card->scd2vc);
3072*4882a593Smuzhiyun 
3073*4882a593Smuzhiyun 	vfree(card->vcs);
3074*4882a593Smuzhiyun 
3075*4882a593Smuzhiyun 	if (card->raw_cell_hnd) {
3076*4882a593Smuzhiyun 		dma_free_coherent(&card->pcidev->dev, 2 * sizeof(u32),
3077*4882a593Smuzhiyun 				  card->raw_cell_hnd, card->raw_cell_paddr);
3078*4882a593Smuzhiyun 	}
3079*4882a593Smuzhiyun 
3080*4882a593Smuzhiyun 	if (card->rsq.base) {
3081*4882a593Smuzhiyun 		DIPRINTK("%s: Release RSQ ...\n", card->name);
3082*4882a593Smuzhiyun 		deinit_rsq(card);
3083*4882a593Smuzhiyun 	}
3084*4882a593Smuzhiyun 
3085*4882a593Smuzhiyun 	if (card->tsq.base) {
3086*4882a593Smuzhiyun 		DIPRINTK("%s: Release TSQ ...\n", card->name);
3087*4882a593Smuzhiyun 		deinit_tsq(card);
3088*4882a593Smuzhiyun 	}
3089*4882a593Smuzhiyun 
3090*4882a593Smuzhiyun 	DIPRINTK("idt77252: Release IRQ.\n");
3091*4882a593Smuzhiyun 	free_irq(card->pcidev->irq, card);
3092*4882a593Smuzhiyun 
3093*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
3094*4882a593Smuzhiyun 		if (card->fbq[i])
3095*4882a593Smuzhiyun 			iounmap(card->fbq[i]);
3096*4882a593Smuzhiyun 	}
3097*4882a593Smuzhiyun 
3098*4882a593Smuzhiyun 	if (card->membase)
3099*4882a593Smuzhiyun 		iounmap(card->membase);
3100*4882a593Smuzhiyun 
3101*4882a593Smuzhiyun 	clear_bit(IDT77252_BIT_INIT, &card->flags);
3102*4882a593Smuzhiyun 	DIPRINTK("%s: Card deinitialized.\n", card->name);
3103*4882a593Smuzhiyun }
3104*4882a593Smuzhiyun 
3105*4882a593Smuzhiyun 
init_sram(struct idt77252_dev * card)3106*4882a593Smuzhiyun static void init_sram(struct idt77252_dev *card)
3107*4882a593Smuzhiyun {
3108*4882a593Smuzhiyun 	int i;
3109*4882a593Smuzhiyun 
3110*4882a593Smuzhiyun 	for (i = 0; i < card->sramsize; i += 4)
3111*4882a593Smuzhiyun 		write_sram(card, (i >> 2), 0);
3112*4882a593Smuzhiyun 
3113*4882a593Smuzhiyun 	/* set SRAM layout for THIS card */
3114*4882a593Smuzhiyun 	if (card->sramsize == (512 * 1024)) {
3115*4882a593Smuzhiyun 		card->tct_base = SAR_SRAM_TCT_128_BASE;
3116*4882a593Smuzhiyun 		card->tct_size = (SAR_SRAM_TCT_128_TOP - card->tct_base + 1)
3117*4882a593Smuzhiyun 		    / SAR_SRAM_TCT_SIZE;
3118*4882a593Smuzhiyun 		card->rct_base = SAR_SRAM_RCT_128_BASE;
3119*4882a593Smuzhiyun 		card->rct_size = (SAR_SRAM_RCT_128_TOP - card->rct_base + 1)
3120*4882a593Smuzhiyun 		    / SAR_SRAM_RCT_SIZE;
3121*4882a593Smuzhiyun 		card->rt_base = SAR_SRAM_RT_128_BASE;
3122*4882a593Smuzhiyun 		card->scd_base = SAR_SRAM_SCD_128_BASE;
3123*4882a593Smuzhiyun 		card->scd_size = (SAR_SRAM_SCD_128_TOP - card->scd_base + 1)
3124*4882a593Smuzhiyun 		    / SAR_SRAM_SCD_SIZE;
3125*4882a593Smuzhiyun 		card->tst[0] = SAR_SRAM_TST1_128_BASE;
3126*4882a593Smuzhiyun 		card->tst[1] = SAR_SRAM_TST2_128_BASE;
3127*4882a593Smuzhiyun 		card->tst_size = SAR_SRAM_TST1_128_TOP - card->tst[0] + 1;
3128*4882a593Smuzhiyun 		card->abrst_base = SAR_SRAM_ABRSTD_128_BASE;
3129*4882a593Smuzhiyun 		card->abrst_size = SAR_ABRSTD_SIZE_8K;
3130*4882a593Smuzhiyun 		card->fifo_base = SAR_SRAM_FIFO_128_BASE;
3131*4882a593Smuzhiyun 		card->fifo_size = SAR_RXFD_SIZE_32K;
3132*4882a593Smuzhiyun 	} else {
3133*4882a593Smuzhiyun 		card->tct_base = SAR_SRAM_TCT_32_BASE;
3134*4882a593Smuzhiyun 		card->tct_size = (SAR_SRAM_TCT_32_TOP - card->tct_base + 1)
3135*4882a593Smuzhiyun 		    / SAR_SRAM_TCT_SIZE;
3136*4882a593Smuzhiyun 		card->rct_base = SAR_SRAM_RCT_32_BASE;
3137*4882a593Smuzhiyun 		card->rct_size = (SAR_SRAM_RCT_32_TOP - card->rct_base + 1)
3138*4882a593Smuzhiyun 		    / SAR_SRAM_RCT_SIZE;
3139*4882a593Smuzhiyun 		card->rt_base = SAR_SRAM_RT_32_BASE;
3140*4882a593Smuzhiyun 		card->scd_base = SAR_SRAM_SCD_32_BASE;
3141*4882a593Smuzhiyun 		card->scd_size = (SAR_SRAM_SCD_32_TOP - card->scd_base + 1)
3142*4882a593Smuzhiyun 		    / SAR_SRAM_SCD_SIZE;
3143*4882a593Smuzhiyun 		card->tst[0] = SAR_SRAM_TST1_32_BASE;
3144*4882a593Smuzhiyun 		card->tst[1] = SAR_SRAM_TST2_32_BASE;
3145*4882a593Smuzhiyun 		card->tst_size = (SAR_SRAM_TST1_32_TOP - card->tst[0] + 1);
3146*4882a593Smuzhiyun 		card->abrst_base = SAR_SRAM_ABRSTD_32_BASE;
3147*4882a593Smuzhiyun 		card->abrst_size = SAR_ABRSTD_SIZE_1K;
3148*4882a593Smuzhiyun 		card->fifo_base = SAR_SRAM_FIFO_32_BASE;
3149*4882a593Smuzhiyun 		card->fifo_size = SAR_RXFD_SIZE_4K;
3150*4882a593Smuzhiyun 	}
3151*4882a593Smuzhiyun 
3152*4882a593Smuzhiyun 	/* Initialize TCT */
3153*4882a593Smuzhiyun 	for (i = 0; i < card->tct_size; i++) {
3154*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 0, 0);
3155*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 1, 0);
3156*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 2, 0);
3157*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 3, 0);
3158*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 4, 0);
3159*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 5, 0);
3160*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 6, 0);
3161*4882a593Smuzhiyun 		write_sram(card, i * SAR_SRAM_TCT_SIZE + 7, 0);
3162*4882a593Smuzhiyun 	}
3163*4882a593Smuzhiyun 
3164*4882a593Smuzhiyun 	/* Initialize RCT */
3165*4882a593Smuzhiyun 	for (i = 0; i < card->rct_size; i++) {
3166*4882a593Smuzhiyun 		write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE,
3167*4882a593Smuzhiyun 				    (u32) SAR_RCTE_RAWCELLINTEN);
3168*4882a593Smuzhiyun 		write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 1,
3169*4882a593Smuzhiyun 				    (u32) 0);
3170*4882a593Smuzhiyun 		write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 2,
3171*4882a593Smuzhiyun 				    (u32) 0);
3172*4882a593Smuzhiyun 		write_sram(card, card->rct_base + i * SAR_SRAM_RCT_SIZE + 3,
3173*4882a593Smuzhiyun 				    (u32) 0xffffffff);
3174*4882a593Smuzhiyun 	}
3175*4882a593Smuzhiyun 
3176*4882a593Smuzhiyun 	writel((SAR_FBQ0_LOW << 28) | (SAR_FB_SIZE_0 / 48), SAR_REG_FBQS0);
3177*4882a593Smuzhiyun 	writel((SAR_FBQ1_LOW << 28) | (SAR_FB_SIZE_1 / 48), SAR_REG_FBQS1);
3178*4882a593Smuzhiyun 	writel((SAR_FBQ2_LOW << 28) | (SAR_FB_SIZE_2 / 48), SAR_REG_FBQS2);
3179*4882a593Smuzhiyun 	writel((SAR_FBQ3_LOW << 28) | (SAR_FB_SIZE_3 / 48), SAR_REG_FBQS3);
3180*4882a593Smuzhiyun 
3181*4882a593Smuzhiyun 	/* Initialize rate table  */
3182*4882a593Smuzhiyun 	for (i = 0; i < 256; i++) {
3183*4882a593Smuzhiyun 		write_sram(card, card->rt_base + i, log_to_rate[i]);
3184*4882a593Smuzhiyun 	}
3185*4882a593Smuzhiyun 
3186*4882a593Smuzhiyun 	for (i = 0; i < 128; i++) {
3187*4882a593Smuzhiyun 		unsigned int tmp;
3188*4882a593Smuzhiyun 
3189*4882a593Smuzhiyun 		tmp  = rate_to_log[(i << 2) + 0] << 0;
3190*4882a593Smuzhiyun 		tmp |= rate_to_log[(i << 2) + 1] << 8;
3191*4882a593Smuzhiyun 		tmp |= rate_to_log[(i << 2) + 2] << 16;
3192*4882a593Smuzhiyun 		tmp |= rate_to_log[(i << 2) + 3] << 24;
3193*4882a593Smuzhiyun 		write_sram(card, card->rt_base + 256 + i, tmp);
3194*4882a593Smuzhiyun 	}
3195*4882a593Smuzhiyun 
3196*4882a593Smuzhiyun #if 0 /* Fill RDF and AIR tables. */
3197*4882a593Smuzhiyun 	for (i = 0; i < 128; i++) {
3198*4882a593Smuzhiyun 		unsigned int tmp;
3199*4882a593Smuzhiyun 
3200*4882a593Smuzhiyun 		tmp = RDF[0][(i << 1) + 0] << 16;
3201*4882a593Smuzhiyun 		tmp |= RDF[0][(i << 1) + 1] << 0;
3202*4882a593Smuzhiyun 		write_sram(card, card->rt_base + 512 + i, tmp);
3203*4882a593Smuzhiyun 	}
3204*4882a593Smuzhiyun 
3205*4882a593Smuzhiyun 	for (i = 0; i < 128; i++) {
3206*4882a593Smuzhiyun 		unsigned int tmp;
3207*4882a593Smuzhiyun 
3208*4882a593Smuzhiyun 		tmp = AIR[0][(i << 1) + 0] << 16;
3209*4882a593Smuzhiyun 		tmp |= AIR[0][(i << 1) + 1] << 0;
3210*4882a593Smuzhiyun 		write_sram(card, card->rt_base + 640 + i, tmp);
3211*4882a593Smuzhiyun 	}
3212*4882a593Smuzhiyun #endif
3213*4882a593Smuzhiyun 
3214*4882a593Smuzhiyun 	IPRINTK("%s: initialize rate table ...\n", card->name);
3215*4882a593Smuzhiyun 	writel(card->rt_base << 2, SAR_REG_RTBL);
3216*4882a593Smuzhiyun 
3217*4882a593Smuzhiyun 	/* Initialize TSTs */
3218*4882a593Smuzhiyun 	IPRINTK("%s: initialize TST ...\n", card->name);
3219*4882a593Smuzhiyun 	card->tst_free = card->tst_size - 2;	/* last two are jumps */
3220*4882a593Smuzhiyun 
3221*4882a593Smuzhiyun 	for (i = card->tst[0]; i < card->tst[0] + card->tst_size - 2; i++)
3222*4882a593Smuzhiyun 		write_sram(card, i, TSTE_OPC_VAR);
3223*4882a593Smuzhiyun 	write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2));
3224*4882a593Smuzhiyun 	idt77252_sram_write_errors = 1;
3225*4882a593Smuzhiyun 	write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2));
3226*4882a593Smuzhiyun 	idt77252_sram_write_errors = 0;
3227*4882a593Smuzhiyun 	for (i = card->tst[1]; i < card->tst[1] + card->tst_size - 2; i++)
3228*4882a593Smuzhiyun 		write_sram(card, i, TSTE_OPC_VAR);
3229*4882a593Smuzhiyun 	write_sram(card, i++, TSTE_OPC_JMP | (card->tst[1] << 2));
3230*4882a593Smuzhiyun 	idt77252_sram_write_errors = 1;
3231*4882a593Smuzhiyun 	write_sram(card, i++, TSTE_OPC_JMP | (card->tst[0] << 2));
3232*4882a593Smuzhiyun 	idt77252_sram_write_errors = 0;
3233*4882a593Smuzhiyun 
3234*4882a593Smuzhiyun 	card->tst_index = 0;
3235*4882a593Smuzhiyun 	writel(card->tst[0] << 2, SAR_REG_TSTB);
3236*4882a593Smuzhiyun 
3237*4882a593Smuzhiyun 	/* Initialize ABRSTD and Receive FIFO */
3238*4882a593Smuzhiyun 	IPRINTK("%s: initialize ABRSTD ...\n", card->name);
3239*4882a593Smuzhiyun 	writel(card->abrst_size | (card->abrst_base << 2),
3240*4882a593Smuzhiyun 	       SAR_REG_ABRSTD);
3241*4882a593Smuzhiyun 
3242*4882a593Smuzhiyun 	IPRINTK("%s: initialize receive fifo ...\n", card->name);
3243*4882a593Smuzhiyun 	writel(card->fifo_size | (card->fifo_base << 2),
3244*4882a593Smuzhiyun 	       SAR_REG_RXFD);
3245*4882a593Smuzhiyun 
3246*4882a593Smuzhiyun 	IPRINTK("%s: SRAM initialization complete.\n", card->name);
3247*4882a593Smuzhiyun }
3248*4882a593Smuzhiyun 
init_card(struct atm_dev * dev)3249*4882a593Smuzhiyun static int init_card(struct atm_dev *dev)
3250*4882a593Smuzhiyun {
3251*4882a593Smuzhiyun 	struct idt77252_dev *card = dev->dev_data;
3252*4882a593Smuzhiyun 	struct pci_dev *pcidev = card->pcidev;
3253*4882a593Smuzhiyun 	unsigned long tmpl, modl;
3254*4882a593Smuzhiyun 	unsigned int linkrate, rsvdcr;
3255*4882a593Smuzhiyun 	unsigned int tst_entries;
3256*4882a593Smuzhiyun 	struct net_device *tmp;
3257*4882a593Smuzhiyun 	char tname[10];
3258*4882a593Smuzhiyun 
3259*4882a593Smuzhiyun 	u32 size;
3260*4882a593Smuzhiyun 	u_char pci_byte;
3261*4882a593Smuzhiyun 	u32 conf;
3262*4882a593Smuzhiyun 	int i, k;
3263*4882a593Smuzhiyun 
3264*4882a593Smuzhiyun 	if (test_bit(IDT77252_BIT_INIT, &card->flags)) {
3265*4882a593Smuzhiyun 		printk("Error: SAR already initialized.\n");
3266*4882a593Smuzhiyun 		return -1;
3267*4882a593Smuzhiyun 	}
3268*4882a593Smuzhiyun 
3269*4882a593Smuzhiyun /*****************************************************************/
3270*4882a593Smuzhiyun /*   P C I   C O N F I G U R A T I O N                           */
3271*4882a593Smuzhiyun /*****************************************************************/
3272*4882a593Smuzhiyun 
3273*4882a593Smuzhiyun 	/* Set PCI Retry-Timeout and TRDY timeout */
3274*4882a593Smuzhiyun 	IPRINTK("%s: Checking PCI retries.\n", card->name);
3275*4882a593Smuzhiyun 	if (pci_read_config_byte(pcidev, 0x40, &pci_byte) != 0) {
3276*4882a593Smuzhiyun 		printk("%s: can't read PCI retry timeout.\n", card->name);
3277*4882a593Smuzhiyun 		deinit_card(card);
3278*4882a593Smuzhiyun 		return -1;
3279*4882a593Smuzhiyun 	}
3280*4882a593Smuzhiyun 	if (pci_byte != 0) {
3281*4882a593Smuzhiyun 		IPRINTK("%s: PCI retry timeout: %d, set to 0.\n",
3282*4882a593Smuzhiyun 			card->name, pci_byte);
3283*4882a593Smuzhiyun 		if (pci_write_config_byte(pcidev, 0x40, 0) != 0) {
3284*4882a593Smuzhiyun 			printk("%s: can't set PCI retry timeout.\n",
3285*4882a593Smuzhiyun 			       card->name);
3286*4882a593Smuzhiyun 			deinit_card(card);
3287*4882a593Smuzhiyun 			return -1;
3288*4882a593Smuzhiyun 		}
3289*4882a593Smuzhiyun 	}
3290*4882a593Smuzhiyun 	IPRINTK("%s: Checking PCI TRDY.\n", card->name);
3291*4882a593Smuzhiyun 	if (pci_read_config_byte(pcidev, 0x41, &pci_byte) != 0) {
3292*4882a593Smuzhiyun 		printk("%s: can't read PCI TRDY timeout.\n", card->name);
3293*4882a593Smuzhiyun 		deinit_card(card);
3294*4882a593Smuzhiyun 		return -1;
3295*4882a593Smuzhiyun 	}
3296*4882a593Smuzhiyun 	if (pci_byte != 0) {
3297*4882a593Smuzhiyun 		IPRINTK("%s: PCI TRDY timeout: %d, set to 0.\n",
3298*4882a593Smuzhiyun 		        card->name, pci_byte);
3299*4882a593Smuzhiyun 		if (pci_write_config_byte(pcidev, 0x41, 0) != 0) {
3300*4882a593Smuzhiyun 			printk("%s: can't set PCI TRDY timeout.\n", card->name);
3301*4882a593Smuzhiyun 			deinit_card(card);
3302*4882a593Smuzhiyun 			return -1;
3303*4882a593Smuzhiyun 		}
3304*4882a593Smuzhiyun 	}
3305*4882a593Smuzhiyun 	/* Reset Timer register */
3306*4882a593Smuzhiyun 	if (readl(SAR_REG_STAT) & SAR_STAT_TMROF) {
3307*4882a593Smuzhiyun 		printk("%s: resetting timer overflow.\n", card->name);
3308*4882a593Smuzhiyun 		writel(SAR_STAT_TMROF, SAR_REG_STAT);
3309*4882a593Smuzhiyun 	}
3310*4882a593Smuzhiyun 	IPRINTK("%s: Request IRQ ... ", card->name);
3311*4882a593Smuzhiyun 	if (request_irq(pcidev->irq, idt77252_interrupt, IRQF_SHARED,
3312*4882a593Smuzhiyun 			card->name, card) != 0) {
3313*4882a593Smuzhiyun 		printk("%s: can't allocate IRQ.\n", card->name);
3314*4882a593Smuzhiyun 		deinit_card(card);
3315*4882a593Smuzhiyun 		return -1;
3316*4882a593Smuzhiyun 	}
3317*4882a593Smuzhiyun 	IPRINTK("got %d.\n", pcidev->irq);
3318*4882a593Smuzhiyun 
3319*4882a593Smuzhiyun /*****************************************************************/
3320*4882a593Smuzhiyun /*   C H E C K   A N D   I N I T   S R A M                       */
3321*4882a593Smuzhiyun /*****************************************************************/
3322*4882a593Smuzhiyun 
3323*4882a593Smuzhiyun 	IPRINTK("%s: Initializing SRAM\n", card->name);
3324*4882a593Smuzhiyun 
3325*4882a593Smuzhiyun 	/* preset size of connecton table, so that init_sram() knows about it */
3326*4882a593Smuzhiyun 	conf =	SAR_CFG_TX_FIFO_SIZE_9 |	/* Use maximum fifo size */
3327*4882a593Smuzhiyun 		SAR_CFG_RXSTQ_SIZE_8k |		/* Receive Status Queue is 8k */
3328*4882a593Smuzhiyun 		SAR_CFG_IDLE_CLP |		/* Set CLP on idle cells */
3329*4882a593Smuzhiyun #ifndef ATM_IDT77252_SEND_IDLE
3330*4882a593Smuzhiyun 		SAR_CFG_NO_IDLE |		/* Do not send idle cells */
3331*4882a593Smuzhiyun #endif
3332*4882a593Smuzhiyun 		0;
3333*4882a593Smuzhiyun 
3334*4882a593Smuzhiyun 	if (card->sramsize == (512 * 1024))
3335*4882a593Smuzhiyun 		conf |= SAR_CFG_CNTBL_1k;
3336*4882a593Smuzhiyun 	else
3337*4882a593Smuzhiyun 		conf |= SAR_CFG_CNTBL_512;
3338*4882a593Smuzhiyun 
3339*4882a593Smuzhiyun 	switch (vpibits) {
3340*4882a593Smuzhiyun 	case 0:
3341*4882a593Smuzhiyun 		conf |= SAR_CFG_VPVCS_0;
3342*4882a593Smuzhiyun 		break;
3343*4882a593Smuzhiyun 	default:
3344*4882a593Smuzhiyun 	case 1:
3345*4882a593Smuzhiyun 		conf |= SAR_CFG_VPVCS_1;
3346*4882a593Smuzhiyun 		break;
3347*4882a593Smuzhiyun 	case 2:
3348*4882a593Smuzhiyun 		conf |= SAR_CFG_VPVCS_2;
3349*4882a593Smuzhiyun 		break;
3350*4882a593Smuzhiyun 	case 8:
3351*4882a593Smuzhiyun 		conf |= SAR_CFG_VPVCS_8;
3352*4882a593Smuzhiyun 		break;
3353*4882a593Smuzhiyun 	}
3354*4882a593Smuzhiyun 
3355*4882a593Smuzhiyun 	writel(readl(SAR_REG_CFG) | conf, SAR_REG_CFG);
3356*4882a593Smuzhiyun 
3357*4882a593Smuzhiyun 	init_sram(card);
3358*4882a593Smuzhiyun 
3359*4882a593Smuzhiyun /********************************************************************/
3360*4882a593Smuzhiyun /*  A L L O C   R A M   A N D   S E T   V A R I O U S   T H I N G S */
3361*4882a593Smuzhiyun /********************************************************************/
3362*4882a593Smuzhiyun 	/* Initialize TSQ */
3363*4882a593Smuzhiyun 	if (0 != init_tsq(card)) {
3364*4882a593Smuzhiyun 		deinit_card(card);
3365*4882a593Smuzhiyun 		return -1;
3366*4882a593Smuzhiyun 	}
3367*4882a593Smuzhiyun 	/* Initialize RSQ */
3368*4882a593Smuzhiyun 	if (0 != init_rsq(card)) {
3369*4882a593Smuzhiyun 		deinit_card(card);
3370*4882a593Smuzhiyun 		return -1;
3371*4882a593Smuzhiyun 	}
3372*4882a593Smuzhiyun 
3373*4882a593Smuzhiyun 	card->vpibits = vpibits;
3374*4882a593Smuzhiyun 	if (card->sramsize == (512 * 1024)) {
3375*4882a593Smuzhiyun 		card->vcibits = 10 - card->vpibits;
3376*4882a593Smuzhiyun 	} else {
3377*4882a593Smuzhiyun 		card->vcibits = 9 - card->vpibits;
3378*4882a593Smuzhiyun 	}
3379*4882a593Smuzhiyun 
3380*4882a593Smuzhiyun 	card->vcimask = 0;
3381*4882a593Smuzhiyun 	for (k = 0, i = 1; k < card->vcibits; k++) {
3382*4882a593Smuzhiyun 		card->vcimask |= i;
3383*4882a593Smuzhiyun 		i <<= 1;
3384*4882a593Smuzhiyun 	}
3385*4882a593Smuzhiyun 
3386*4882a593Smuzhiyun 	IPRINTK("%s: Setting VPI/VCI mask to zero.\n", card->name);
3387*4882a593Smuzhiyun 	writel(0, SAR_REG_VPM);
3388*4882a593Smuzhiyun 
3389*4882a593Smuzhiyun 	/* Little Endian Order   */
3390*4882a593Smuzhiyun 	writel(0, SAR_REG_GP);
3391*4882a593Smuzhiyun 
3392*4882a593Smuzhiyun 	/* Initialize RAW Cell Handle Register  */
3393*4882a593Smuzhiyun 	card->raw_cell_hnd = dma_alloc_coherent(&card->pcidev->dev,
3394*4882a593Smuzhiyun 						2 * sizeof(u32),
3395*4882a593Smuzhiyun 						&card->raw_cell_paddr,
3396*4882a593Smuzhiyun 						GFP_KERNEL);
3397*4882a593Smuzhiyun 	if (!card->raw_cell_hnd) {
3398*4882a593Smuzhiyun 		printk("%s: memory allocation failure.\n", card->name);
3399*4882a593Smuzhiyun 		deinit_card(card);
3400*4882a593Smuzhiyun 		return -1;
3401*4882a593Smuzhiyun 	}
3402*4882a593Smuzhiyun 	writel(card->raw_cell_paddr, SAR_REG_RAWHND);
3403*4882a593Smuzhiyun 	IPRINTK("%s: raw cell handle is at 0x%p.\n", card->name,
3404*4882a593Smuzhiyun 		card->raw_cell_hnd);
3405*4882a593Smuzhiyun 
3406*4882a593Smuzhiyun 	size = sizeof(struct vc_map *) * card->tct_size;
3407*4882a593Smuzhiyun 	IPRINTK("%s: allocate %d byte for VC map.\n", card->name, size);
3408*4882a593Smuzhiyun 	card->vcs = vzalloc(size);
3409*4882a593Smuzhiyun 	if (!card->vcs) {
3410*4882a593Smuzhiyun 		printk("%s: memory allocation failure.\n", card->name);
3411*4882a593Smuzhiyun 		deinit_card(card);
3412*4882a593Smuzhiyun 		return -1;
3413*4882a593Smuzhiyun 	}
3414*4882a593Smuzhiyun 
3415*4882a593Smuzhiyun 	size = sizeof(struct vc_map *) * card->scd_size;
3416*4882a593Smuzhiyun 	IPRINTK("%s: allocate %d byte for SCD to VC mapping.\n",
3417*4882a593Smuzhiyun 	        card->name, size);
3418*4882a593Smuzhiyun 	card->scd2vc = vzalloc(size);
3419*4882a593Smuzhiyun 	if (!card->scd2vc) {
3420*4882a593Smuzhiyun 		printk("%s: memory allocation failure.\n", card->name);
3421*4882a593Smuzhiyun 		deinit_card(card);
3422*4882a593Smuzhiyun 		return -1;
3423*4882a593Smuzhiyun 	}
3424*4882a593Smuzhiyun 
3425*4882a593Smuzhiyun 	size = sizeof(struct tst_info) * (card->tst_size - 2);
3426*4882a593Smuzhiyun 	IPRINTK("%s: allocate %d byte for TST to VC mapping.\n",
3427*4882a593Smuzhiyun 		card->name, size);
3428*4882a593Smuzhiyun 	card->soft_tst = vmalloc(size);
3429*4882a593Smuzhiyun 	if (!card->soft_tst) {
3430*4882a593Smuzhiyun 		printk("%s: memory allocation failure.\n", card->name);
3431*4882a593Smuzhiyun 		deinit_card(card);
3432*4882a593Smuzhiyun 		return -1;
3433*4882a593Smuzhiyun 	}
3434*4882a593Smuzhiyun 	for (i = 0; i < card->tst_size - 2; i++) {
3435*4882a593Smuzhiyun 		card->soft_tst[i].tste = TSTE_OPC_VAR;
3436*4882a593Smuzhiyun 		card->soft_tst[i].vc = NULL;
3437*4882a593Smuzhiyun 	}
3438*4882a593Smuzhiyun 
3439*4882a593Smuzhiyun 	if (dev->phy == NULL) {
3440*4882a593Smuzhiyun 		printk("%s: No LT device defined.\n", card->name);
3441*4882a593Smuzhiyun 		deinit_card(card);
3442*4882a593Smuzhiyun 		return -1;
3443*4882a593Smuzhiyun 	}
3444*4882a593Smuzhiyun 	if (dev->phy->ioctl == NULL) {
3445*4882a593Smuzhiyun 		printk("%s: LT had no IOCTL function defined.\n", card->name);
3446*4882a593Smuzhiyun 		deinit_card(card);
3447*4882a593Smuzhiyun 		return -1;
3448*4882a593Smuzhiyun 	}
3449*4882a593Smuzhiyun 
3450*4882a593Smuzhiyun #ifdef	CONFIG_ATM_IDT77252_USE_SUNI
3451*4882a593Smuzhiyun 	/*
3452*4882a593Smuzhiyun 	 * this is a jhs hack to get around special functionality in the
3453*4882a593Smuzhiyun 	 * phy driver for the atecom hardware; the functionality doesn't
3454*4882a593Smuzhiyun 	 * exist in the linux atm suni driver
3455*4882a593Smuzhiyun 	 *
3456*4882a593Smuzhiyun 	 * it isn't the right way to do things, but as the guy from NIST
3457*4882a593Smuzhiyun 	 * said, talking about their measurement of the fine structure
3458*4882a593Smuzhiyun 	 * constant, "it's good enough for government work."
3459*4882a593Smuzhiyun 	 */
3460*4882a593Smuzhiyun 	linkrate = 149760000;
3461*4882a593Smuzhiyun #endif
3462*4882a593Smuzhiyun 
3463*4882a593Smuzhiyun 	card->link_pcr = (linkrate / 8 / 53);
3464*4882a593Smuzhiyun 	printk("%s: Linkrate on ATM line : %u bit/s, %u cell/s.\n",
3465*4882a593Smuzhiyun 	       card->name, linkrate, card->link_pcr);
3466*4882a593Smuzhiyun 
3467*4882a593Smuzhiyun #ifdef ATM_IDT77252_SEND_IDLE
3468*4882a593Smuzhiyun 	card->utopia_pcr = card->link_pcr;
3469*4882a593Smuzhiyun #else
3470*4882a593Smuzhiyun 	card->utopia_pcr = (160000000 / 8 / 54);
3471*4882a593Smuzhiyun #endif
3472*4882a593Smuzhiyun 
3473*4882a593Smuzhiyun 	rsvdcr = 0;
3474*4882a593Smuzhiyun 	if (card->utopia_pcr > card->link_pcr)
3475*4882a593Smuzhiyun 		rsvdcr = card->utopia_pcr - card->link_pcr;
3476*4882a593Smuzhiyun 
3477*4882a593Smuzhiyun 	tmpl = (unsigned long) rsvdcr * ((unsigned long) card->tst_size - 2);
3478*4882a593Smuzhiyun 	modl = tmpl % (unsigned long)card->utopia_pcr;
3479*4882a593Smuzhiyun 	tst_entries = (int) (tmpl / (unsigned long)card->utopia_pcr);
3480*4882a593Smuzhiyun 	if (modl)
3481*4882a593Smuzhiyun 		tst_entries++;
3482*4882a593Smuzhiyun 	card->tst_free -= tst_entries;
3483*4882a593Smuzhiyun 	fill_tst(card, NULL, tst_entries, TSTE_OPC_NULL);
3484*4882a593Smuzhiyun 
3485*4882a593Smuzhiyun #ifdef HAVE_EEPROM
3486*4882a593Smuzhiyun 	idt77252_eeprom_init(card);
3487*4882a593Smuzhiyun 	printk("%s: EEPROM: %02x:", card->name,
3488*4882a593Smuzhiyun 		idt77252_eeprom_read_status(card));
3489*4882a593Smuzhiyun 
3490*4882a593Smuzhiyun 	for (i = 0; i < 0x80; i++) {
3491*4882a593Smuzhiyun 		printk(" %02x",
3492*4882a593Smuzhiyun 		idt77252_eeprom_read_byte(card, i)
3493*4882a593Smuzhiyun 		);
3494*4882a593Smuzhiyun 	}
3495*4882a593Smuzhiyun 	printk("\n");
3496*4882a593Smuzhiyun #endif /* HAVE_EEPROM */
3497*4882a593Smuzhiyun 
3498*4882a593Smuzhiyun 	/*
3499*4882a593Smuzhiyun 	 * XXX: <hack>
3500*4882a593Smuzhiyun 	 */
3501*4882a593Smuzhiyun 	sprintf(tname, "eth%d", card->index);
3502*4882a593Smuzhiyun 	tmp = dev_get_by_name(&init_net, tname);	/* jhs: was "tmp = dev_get(tname);" */
3503*4882a593Smuzhiyun 	if (tmp) {
3504*4882a593Smuzhiyun 		memcpy(card->atmdev->esi, tmp->dev_addr, 6);
3505*4882a593Smuzhiyun 		dev_put(tmp);
3506*4882a593Smuzhiyun 		printk("%s: ESI %pM\n", card->name, card->atmdev->esi);
3507*4882a593Smuzhiyun 	}
3508*4882a593Smuzhiyun 	/*
3509*4882a593Smuzhiyun 	 * XXX: </hack>
3510*4882a593Smuzhiyun 	 */
3511*4882a593Smuzhiyun 
3512*4882a593Smuzhiyun 	/* Set Maximum Deficit Count for now. */
3513*4882a593Smuzhiyun 	writel(0xffff, SAR_REG_MDFCT);
3514*4882a593Smuzhiyun 
3515*4882a593Smuzhiyun 	set_bit(IDT77252_BIT_INIT, &card->flags);
3516*4882a593Smuzhiyun 
3517*4882a593Smuzhiyun 	XPRINTK("%s: IDT77252 ABR SAR initialization complete.\n", card->name);
3518*4882a593Smuzhiyun 	return 0;
3519*4882a593Smuzhiyun }
3520*4882a593Smuzhiyun 
3521*4882a593Smuzhiyun 
3522*4882a593Smuzhiyun /*****************************************************************************/
3523*4882a593Smuzhiyun /*                                                                           */
3524*4882a593Smuzhiyun /* Probing of IDT77252 ABR SAR                                               */
3525*4882a593Smuzhiyun /*                                                                           */
3526*4882a593Smuzhiyun /*****************************************************************************/
3527*4882a593Smuzhiyun 
3528*4882a593Smuzhiyun 
idt77252_preset(struct idt77252_dev * card)3529*4882a593Smuzhiyun static int idt77252_preset(struct idt77252_dev *card)
3530*4882a593Smuzhiyun {
3531*4882a593Smuzhiyun 	u16 pci_command;
3532*4882a593Smuzhiyun 
3533*4882a593Smuzhiyun /*****************************************************************/
3534*4882a593Smuzhiyun /*   P C I   C O N F I G U R A T I O N                           */
3535*4882a593Smuzhiyun /*****************************************************************/
3536*4882a593Smuzhiyun 
3537*4882a593Smuzhiyun 	XPRINTK("%s: Enable PCI master and memory access for SAR.\n",
3538*4882a593Smuzhiyun 		card->name);
3539*4882a593Smuzhiyun 	if (pci_read_config_word(card->pcidev, PCI_COMMAND, &pci_command)) {
3540*4882a593Smuzhiyun 		printk("%s: can't read PCI_COMMAND.\n", card->name);
3541*4882a593Smuzhiyun 		deinit_card(card);
3542*4882a593Smuzhiyun 		return -1;
3543*4882a593Smuzhiyun 	}
3544*4882a593Smuzhiyun 	if (!(pci_command & PCI_COMMAND_IO)) {
3545*4882a593Smuzhiyun 		printk("%s: PCI_COMMAND: %04x (???)\n",
3546*4882a593Smuzhiyun 		       card->name, pci_command);
3547*4882a593Smuzhiyun 		deinit_card(card);
3548*4882a593Smuzhiyun 		return (-1);
3549*4882a593Smuzhiyun 	}
3550*4882a593Smuzhiyun 	pci_command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
3551*4882a593Smuzhiyun 	if (pci_write_config_word(card->pcidev, PCI_COMMAND, pci_command)) {
3552*4882a593Smuzhiyun 		printk("%s: can't write PCI_COMMAND.\n", card->name);
3553*4882a593Smuzhiyun 		deinit_card(card);
3554*4882a593Smuzhiyun 		return -1;
3555*4882a593Smuzhiyun 	}
3556*4882a593Smuzhiyun /*****************************************************************/
3557*4882a593Smuzhiyun /*   G E N E R I C   R E S E T                                   */
3558*4882a593Smuzhiyun /*****************************************************************/
3559*4882a593Smuzhiyun 
3560*4882a593Smuzhiyun 	/* Software reset */
3561*4882a593Smuzhiyun 	writel(SAR_CFG_SWRST, SAR_REG_CFG);
3562*4882a593Smuzhiyun 	mdelay(1);
3563*4882a593Smuzhiyun 	writel(0, SAR_REG_CFG);
3564*4882a593Smuzhiyun 
3565*4882a593Smuzhiyun 	IPRINTK("%s: Software resetted.\n", card->name);
3566*4882a593Smuzhiyun 	return 0;
3567*4882a593Smuzhiyun }
3568*4882a593Smuzhiyun 
3569*4882a593Smuzhiyun 
probe_sram(struct idt77252_dev * card)3570*4882a593Smuzhiyun static unsigned long probe_sram(struct idt77252_dev *card)
3571*4882a593Smuzhiyun {
3572*4882a593Smuzhiyun 	u32 data, addr;
3573*4882a593Smuzhiyun 
3574*4882a593Smuzhiyun 	writel(0, SAR_REG_DR0);
3575*4882a593Smuzhiyun 	writel(SAR_CMD_WRITE_SRAM | (0 << 2), SAR_REG_CMD);
3576*4882a593Smuzhiyun 
3577*4882a593Smuzhiyun 	for (addr = 0x4000; addr < 0x80000; addr += 0x4000) {
3578*4882a593Smuzhiyun 		writel(ATM_POISON, SAR_REG_DR0);
3579*4882a593Smuzhiyun 		writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD);
3580*4882a593Smuzhiyun 
3581*4882a593Smuzhiyun 		writel(SAR_CMD_READ_SRAM | (0 << 2), SAR_REG_CMD);
3582*4882a593Smuzhiyun 		data = readl(SAR_REG_DR0);
3583*4882a593Smuzhiyun 
3584*4882a593Smuzhiyun 		if (data != 0)
3585*4882a593Smuzhiyun 			break;
3586*4882a593Smuzhiyun 	}
3587*4882a593Smuzhiyun 
3588*4882a593Smuzhiyun 	return addr * sizeof(u32);
3589*4882a593Smuzhiyun }
3590*4882a593Smuzhiyun 
idt77252_init_one(struct pci_dev * pcidev,const struct pci_device_id * id)3591*4882a593Smuzhiyun static int idt77252_init_one(struct pci_dev *pcidev,
3592*4882a593Smuzhiyun 			     const struct pci_device_id *id)
3593*4882a593Smuzhiyun {
3594*4882a593Smuzhiyun 	static struct idt77252_dev **last = &idt77252_chain;
3595*4882a593Smuzhiyun 	static int index = 0;
3596*4882a593Smuzhiyun 
3597*4882a593Smuzhiyun 	unsigned long membase, srambase;
3598*4882a593Smuzhiyun 	struct idt77252_dev *card;
3599*4882a593Smuzhiyun 	struct atm_dev *dev;
3600*4882a593Smuzhiyun 	int i, err;
3601*4882a593Smuzhiyun 
3602*4882a593Smuzhiyun 
3603*4882a593Smuzhiyun 	if ((err = pci_enable_device(pcidev))) {
3604*4882a593Smuzhiyun 		printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev));
3605*4882a593Smuzhiyun 		return err;
3606*4882a593Smuzhiyun 	}
3607*4882a593Smuzhiyun 
3608*4882a593Smuzhiyun 	if ((err = dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(32)))) {
3609*4882a593Smuzhiyun 		printk("idt77252: can't enable DMA for PCI device at %s\n", pci_name(pcidev));
3610*4882a593Smuzhiyun 		goto err_out_disable_pdev;
3611*4882a593Smuzhiyun 	}
3612*4882a593Smuzhiyun 
3613*4882a593Smuzhiyun 	card = kzalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
3614*4882a593Smuzhiyun 	if (!card) {
3615*4882a593Smuzhiyun 		printk("idt77252-%d: can't allocate private data\n", index);
3616*4882a593Smuzhiyun 		err = -ENOMEM;
3617*4882a593Smuzhiyun 		goto err_out_disable_pdev;
3618*4882a593Smuzhiyun 	}
3619*4882a593Smuzhiyun 	card->revision = pcidev->revision;
3620*4882a593Smuzhiyun 	card->index = index;
3621*4882a593Smuzhiyun 	card->pcidev = pcidev;
3622*4882a593Smuzhiyun 	sprintf(card->name, "idt77252-%d", card->index);
3623*4882a593Smuzhiyun 
3624*4882a593Smuzhiyun 	INIT_WORK(&card->tqueue, idt77252_softint);
3625*4882a593Smuzhiyun 
3626*4882a593Smuzhiyun 	membase = pci_resource_start(pcidev, 1);
3627*4882a593Smuzhiyun 	srambase = pci_resource_start(pcidev, 2);
3628*4882a593Smuzhiyun 
3629*4882a593Smuzhiyun 	mutex_init(&card->mutex);
3630*4882a593Smuzhiyun 	spin_lock_init(&card->cmd_lock);
3631*4882a593Smuzhiyun 	spin_lock_init(&card->tst_lock);
3632*4882a593Smuzhiyun 
3633*4882a593Smuzhiyun 	timer_setup(&card->tst_timer, tst_timer, 0);
3634*4882a593Smuzhiyun 
3635*4882a593Smuzhiyun 	/* Do the I/O remapping... */
3636*4882a593Smuzhiyun 	card->membase = ioremap(membase, 1024);
3637*4882a593Smuzhiyun 	if (!card->membase) {
3638*4882a593Smuzhiyun 		printk("%s: can't ioremap() membase\n", card->name);
3639*4882a593Smuzhiyun 		err = -EIO;
3640*4882a593Smuzhiyun 		goto err_out_free_card;
3641*4882a593Smuzhiyun 	}
3642*4882a593Smuzhiyun 
3643*4882a593Smuzhiyun 	if (idt77252_preset(card)) {
3644*4882a593Smuzhiyun 		printk("%s: preset failed\n", card->name);
3645*4882a593Smuzhiyun 		err = -EIO;
3646*4882a593Smuzhiyun 		goto err_out_iounmap;
3647*4882a593Smuzhiyun 	}
3648*4882a593Smuzhiyun 
3649*4882a593Smuzhiyun 	dev = atm_dev_register("idt77252", &pcidev->dev, &idt77252_ops, -1,
3650*4882a593Smuzhiyun 			       NULL);
3651*4882a593Smuzhiyun 	if (!dev) {
3652*4882a593Smuzhiyun 		printk("%s: can't register atm device\n", card->name);
3653*4882a593Smuzhiyun 		err = -EIO;
3654*4882a593Smuzhiyun 		goto err_out_iounmap;
3655*4882a593Smuzhiyun 	}
3656*4882a593Smuzhiyun 	dev->dev_data = card;
3657*4882a593Smuzhiyun 	card->atmdev = dev;
3658*4882a593Smuzhiyun 
3659*4882a593Smuzhiyun #ifdef	CONFIG_ATM_IDT77252_USE_SUNI
3660*4882a593Smuzhiyun 	suni_init(dev);
3661*4882a593Smuzhiyun 	if (!dev->phy) {
3662*4882a593Smuzhiyun 		printk("%s: can't init SUNI\n", card->name);
3663*4882a593Smuzhiyun 		err = -EIO;
3664*4882a593Smuzhiyun 		goto err_out_deinit_card;
3665*4882a593Smuzhiyun 	}
3666*4882a593Smuzhiyun #endif	/* CONFIG_ATM_IDT77252_USE_SUNI */
3667*4882a593Smuzhiyun 
3668*4882a593Smuzhiyun 	card->sramsize = probe_sram(card);
3669*4882a593Smuzhiyun 
3670*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
3671*4882a593Smuzhiyun 		card->fbq[i] = ioremap(srambase | 0x200000 | (i << 18), 4);
3672*4882a593Smuzhiyun 		if (!card->fbq[i]) {
3673*4882a593Smuzhiyun 			printk("%s: can't ioremap() FBQ%d\n", card->name, i);
3674*4882a593Smuzhiyun 			err = -EIO;
3675*4882a593Smuzhiyun 			goto err_out_deinit_card;
3676*4882a593Smuzhiyun 		}
3677*4882a593Smuzhiyun 	}
3678*4882a593Smuzhiyun 
3679*4882a593Smuzhiyun 	printk("%s: ABR SAR (Rev %c): MEM %08lx SRAM %08lx [%u KB]\n",
3680*4882a593Smuzhiyun 	       card->name, ((card->revision > 1) && (card->revision < 25)) ?
3681*4882a593Smuzhiyun 	       'A' + card->revision - 1 : '?', membase, srambase,
3682*4882a593Smuzhiyun 	       card->sramsize / 1024);
3683*4882a593Smuzhiyun 
3684*4882a593Smuzhiyun 	if (init_card(dev)) {
3685*4882a593Smuzhiyun 		printk("%s: init_card failed\n", card->name);
3686*4882a593Smuzhiyun 		err = -EIO;
3687*4882a593Smuzhiyun 		goto err_out_deinit_card;
3688*4882a593Smuzhiyun 	}
3689*4882a593Smuzhiyun 
3690*4882a593Smuzhiyun 	dev->ci_range.vpi_bits = card->vpibits;
3691*4882a593Smuzhiyun 	dev->ci_range.vci_bits = card->vcibits;
3692*4882a593Smuzhiyun 	dev->link_rate = card->link_pcr;
3693*4882a593Smuzhiyun 
3694*4882a593Smuzhiyun 	if (dev->phy->start)
3695*4882a593Smuzhiyun 		dev->phy->start(dev);
3696*4882a593Smuzhiyun 
3697*4882a593Smuzhiyun 	if (idt77252_dev_open(card)) {
3698*4882a593Smuzhiyun 		printk("%s: dev_open failed\n", card->name);
3699*4882a593Smuzhiyun 		err = -EIO;
3700*4882a593Smuzhiyun 		goto err_out_stop;
3701*4882a593Smuzhiyun 	}
3702*4882a593Smuzhiyun 
3703*4882a593Smuzhiyun 	*last = card;
3704*4882a593Smuzhiyun 	last = &card->next;
3705*4882a593Smuzhiyun 	index++;
3706*4882a593Smuzhiyun 
3707*4882a593Smuzhiyun 	return 0;
3708*4882a593Smuzhiyun 
3709*4882a593Smuzhiyun err_out_stop:
3710*4882a593Smuzhiyun 	if (dev->phy->stop)
3711*4882a593Smuzhiyun 		dev->phy->stop(dev);
3712*4882a593Smuzhiyun 
3713*4882a593Smuzhiyun err_out_deinit_card:
3714*4882a593Smuzhiyun 	deinit_card(card);
3715*4882a593Smuzhiyun 
3716*4882a593Smuzhiyun err_out_iounmap:
3717*4882a593Smuzhiyun 	iounmap(card->membase);
3718*4882a593Smuzhiyun 
3719*4882a593Smuzhiyun err_out_free_card:
3720*4882a593Smuzhiyun 	kfree(card);
3721*4882a593Smuzhiyun 
3722*4882a593Smuzhiyun err_out_disable_pdev:
3723*4882a593Smuzhiyun 	pci_disable_device(pcidev);
3724*4882a593Smuzhiyun 	return err;
3725*4882a593Smuzhiyun }
3726*4882a593Smuzhiyun 
3727*4882a593Smuzhiyun static const struct pci_device_id idt77252_pci_tbl[] =
3728*4882a593Smuzhiyun {
3729*4882a593Smuzhiyun 	{ PCI_VDEVICE(IDT, PCI_DEVICE_ID_IDT_IDT77252), 0 },
3730*4882a593Smuzhiyun 	{ 0, }
3731*4882a593Smuzhiyun };
3732*4882a593Smuzhiyun 
3733*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, idt77252_pci_tbl);
3734*4882a593Smuzhiyun 
3735*4882a593Smuzhiyun static struct pci_driver idt77252_driver = {
3736*4882a593Smuzhiyun 	.name		= "idt77252",
3737*4882a593Smuzhiyun 	.id_table	= idt77252_pci_tbl,
3738*4882a593Smuzhiyun 	.probe		= idt77252_init_one,
3739*4882a593Smuzhiyun };
3740*4882a593Smuzhiyun 
idt77252_init(void)3741*4882a593Smuzhiyun static int __init idt77252_init(void)
3742*4882a593Smuzhiyun {
3743*4882a593Smuzhiyun 	struct sk_buff *skb;
3744*4882a593Smuzhiyun 
3745*4882a593Smuzhiyun 	printk("%s: at %p\n", __func__, idt77252_init);
3746*4882a593Smuzhiyun 
3747*4882a593Smuzhiyun 	if (sizeof(skb->cb) < sizeof(struct atm_skb_data) +
3748*4882a593Smuzhiyun 			      sizeof(struct idt77252_skb_prv)) {
3749*4882a593Smuzhiyun 		printk(KERN_ERR "%s: skb->cb is too small (%lu < %lu)\n",
3750*4882a593Smuzhiyun 		       __func__, (unsigned long) sizeof(skb->cb),
3751*4882a593Smuzhiyun 		       (unsigned long) sizeof(struct atm_skb_data) +
3752*4882a593Smuzhiyun 				       sizeof(struct idt77252_skb_prv));
3753*4882a593Smuzhiyun 		return -EIO;
3754*4882a593Smuzhiyun 	}
3755*4882a593Smuzhiyun 
3756*4882a593Smuzhiyun 	return pci_register_driver(&idt77252_driver);
3757*4882a593Smuzhiyun }
3758*4882a593Smuzhiyun 
idt77252_exit(void)3759*4882a593Smuzhiyun static void __exit idt77252_exit(void)
3760*4882a593Smuzhiyun {
3761*4882a593Smuzhiyun 	struct idt77252_dev *card;
3762*4882a593Smuzhiyun 	struct atm_dev *dev;
3763*4882a593Smuzhiyun 
3764*4882a593Smuzhiyun 	pci_unregister_driver(&idt77252_driver);
3765*4882a593Smuzhiyun 
3766*4882a593Smuzhiyun 	while (idt77252_chain) {
3767*4882a593Smuzhiyun 		card = idt77252_chain;
3768*4882a593Smuzhiyun 		dev = card->atmdev;
3769*4882a593Smuzhiyun 		idt77252_chain = card->next;
3770*4882a593Smuzhiyun 		del_timer_sync(&card->tst_timer);
3771*4882a593Smuzhiyun 
3772*4882a593Smuzhiyun 		if (dev->phy->stop)
3773*4882a593Smuzhiyun 			dev->phy->stop(dev);
3774*4882a593Smuzhiyun 		deinit_card(card);
3775*4882a593Smuzhiyun 		pci_disable_device(card->pcidev);
3776*4882a593Smuzhiyun 		kfree(card);
3777*4882a593Smuzhiyun 	}
3778*4882a593Smuzhiyun 
3779*4882a593Smuzhiyun 	DIPRINTK("idt77252: finished cleanup-module().\n");
3780*4882a593Smuzhiyun }
3781*4882a593Smuzhiyun 
3782*4882a593Smuzhiyun module_init(idt77252_init);
3783*4882a593Smuzhiyun module_exit(idt77252_exit);
3784*4882a593Smuzhiyun 
3785*4882a593Smuzhiyun MODULE_LICENSE("GPL");
3786*4882a593Smuzhiyun 
3787*4882a593Smuzhiyun module_param(vpibits, uint, 0);
3788*4882a593Smuzhiyun MODULE_PARM_DESC(vpibits, "number of VPI bits supported (0, 1, or 2)");
3789*4882a593Smuzhiyun #ifdef CONFIG_ATM_IDT77252_DEBUG
3790*4882a593Smuzhiyun module_param(debug, ulong, 0644);
3791*4882a593Smuzhiyun MODULE_PARM_DESC(debug,   "debug bitmap, see drivers/atm/idt77252.h");
3792*4882a593Smuzhiyun #endif
3793*4882a593Smuzhiyun 
3794*4882a593Smuzhiyun MODULE_AUTHOR("Eddie C. Dost <ecd@atecom.com>");
3795*4882a593Smuzhiyun MODULE_DESCRIPTION("IDT77252 ABR SAR Driver");
3796