blob: 9e373ba203082f8bc0cb5757a011a3efccf7b291 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/******************************************************************************
2 iphase.c: Device driver for Interphase ATM PCI adapter cards
3 Author: Peter Wang <pwang@iphase.com>
4 Some fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
5 Interphase Corporation <www.iphase.com>
6 Version: 1.0
7*******************************************************************************
8
9 This software may be used and distributed according to the terms
10 of the GNU General Public License (GPL), incorporated herein by reference.
11 Drivers based on this skeleton fall under the GPL and must retain
12 the authorship (implicit copyright) notice.
13
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
18
19 Modified from an incomplete driver for Interphase 5575 1KVC 1M card which
20 was originally written by Monalisa Agrawal at UNH. Now this driver
21 supports a variety of varients of Interphase ATM PCI (i)Chip adapter
22 card family (See www.iphase.com/products/ClassSheet.cfm?ClassID=ATM)
23 in terms of PHY type, the size of control memory and the size of
24 packet memory. The followings are the change log and history:
25
26 Bugfix the Mona's UBR driver.
27 Modify the basic memory allocation and dma logic.
28 Port the driver to the latest kernel from 2.0.46.
29 Complete the ABR logic of the driver, and added the ABR work-
30 around for the hardware anormalies.
31 Add the CBR support.
32 Add the flow control logic to the driver to allow rate-limit VC.
33 Add 4K VC support to the board with 512K control memory.
34 Add the support of all the variants of the Interphase ATM PCI
35 (i)Chip adapter cards including x575 (155M OC3 and UTP155), x525
36 (25M UTP25) and x531 (DS3 and E3).
37 Add SMP support.
38
39 Support and updates available at: ftp://ftp.iphase.com/pub/atm
40
41*******************************************************************************/
42
43#include <linux/module.h>
44#include <linux/kernel.h>
45#include <linux/mm.h>
46#include <linux/pci.h>
47#include <linux/errno.h>
48#include <linux/atm.h>
49#include <linux/atmdev.h>
50#include <linux/sonet.h>
51#include <linux/skbuff.h>
52#include <linux/time.h>
53#include <linux/delay.h>
54#include <linux/uio.h>
55#include <linux/init.h>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000056#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090058#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <asm/system.h>
60#include <asm/io.h>
Arun Sharma600634972011-07-26 16:09:06 -070061#include <linux/atomic.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#include <asm/uaccess.h>
63#include <asm/string.h>
64#include <asm/byteorder.h>
Julia Lawall420635f2008-04-19 18:14:50 -070065#include <linux/vmalloc.h>
66#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#include "iphase.h"
68#include "suni.h"
Wu Fengguangb67445fc2009-01-07 18:09:10 -080069#define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
Jorge Boncompte [DTI2]2be63b82008-06-17 16:18:49 -070070
Linus Torvalds1da177e2005-04-16 15:20:36 -070071#define PRIV(dev) ((struct suni_priv *) dev->phy_data)
72
73static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr);
74static void desc_dbg(IADEV *iadev);
75
76static IADEV *ia_dev[8];
77static struct atm_dev *_ia_dev[8];
78static int iadev_count;
79static void ia_led_timer(unsigned long arg);
Ingo Molnar8d06afa2005-09-09 13:10:40 -070080static DEFINE_TIMER(ia_timer, ia_led_timer, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070081static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
82static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;
83static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER
84 |IF_IADBG_ABR | IF_IADBG_EVENT*/ 0;
85
86module_param(IA_TX_BUF, int, 0);
87module_param(IA_TX_BUF_SZ, int, 0);
88module_param(IA_RX_BUF, int, 0);
89module_param(IA_RX_BUF_SZ, int, 0);
90module_param(IADebugFlag, uint, 0644);
91
92MODULE_LICENSE("GPL");
93
Linus Torvalds1da177e2005-04-16 15:20:36 -070094/**************************** IA_LIB **********************************/
95
96static void ia_init_rtn_q (IARTN_Q *que)
97{
98 que->next = NULL;
99 que->tail = NULL;
100}
101
102static void ia_enque_head_rtn_q (IARTN_Q *que, IARTN_Q * data)
103{
104 data->next = NULL;
105 if (que->next == NULL)
106 que->next = que->tail = data;
107 else {
108 data->next = que->next;
109 que->next = data;
110 }
111 return;
112}
113
114static int ia_enque_rtn_q (IARTN_Q *que, struct desc_tbl_t data) {
115 IARTN_Q *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
116 if (!entry) return -1;
117 entry->data = data;
118 entry->next = NULL;
119 if (que->next == NULL)
120 que->next = que->tail = entry;
121 else {
122 que->tail->next = entry;
123 que->tail = que->tail->next;
124 }
125 return 1;
126}
127
128static IARTN_Q * ia_deque_rtn_q (IARTN_Q *que) {
129 IARTN_Q *tmpdata;
130 if (que->next == NULL)
131 return NULL;
132 tmpdata = que->next;
133 if ( que->next == que->tail)
134 que->next = que->tail = NULL;
135 else
136 que->next = que->next->next;
137 return tmpdata;
138}
139
140static void ia_hack_tcq(IADEV *dev) {
141
142 u_short desc1;
143 u_short tcq_wr;
144 struct ia_vcc *iavcc_r = NULL;
145
146 tcq_wr = readl(dev->seg_reg+TCQ_WR_PTR) & 0xffff;
147 while (dev->host_tcq_wr != tcq_wr) {
148 desc1 = *(u_short *)(dev->seg_ram + dev->host_tcq_wr);
149 if (!desc1) ;
150 else if (!dev->desc_tbl[desc1 -1].timestamp) {
151 IF_ABR(printk(" Desc %d is reset at %ld\n", desc1 -1, jiffies);)
152 *(u_short *) (dev->seg_ram + dev->host_tcq_wr) = 0;
153 }
154 else if (dev->desc_tbl[desc1 -1].timestamp) {
155 if (!(iavcc_r = dev->desc_tbl[desc1 -1].iavcc)) {
156 printk("IA: Fatal err in get_desc\n");
157 continue;
158 }
159 iavcc_r->vc_desc_cnt--;
160 dev->desc_tbl[desc1 -1].timestamp = 0;
David Howells849e8ca2008-07-30 16:33:05 -0700161 IF_EVENT(printk("ia_hack: return_q skb = 0x%p desc = %d\n",
162 dev->desc_tbl[desc1 -1].txskb, desc1);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 if (iavcc_r->pcr < dev->rate_limit) {
164 IA_SKB_STATE (dev->desc_tbl[desc1-1].txskb) |= IA_TX_DONE;
165 if (ia_enque_rtn_q(&dev->tx_return_q, dev->desc_tbl[desc1 -1]) < 0)
166 printk("ia_hack_tcq: No memory available\n");
167 }
168 dev->desc_tbl[desc1 -1].iavcc = NULL;
169 dev->desc_tbl[desc1 -1].txskb = NULL;
170 }
171 dev->host_tcq_wr += 2;
172 if (dev->host_tcq_wr > dev->ffL.tcq_ed)
173 dev->host_tcq_wr = dev->ffL.tcq_st;
174 }
175} /* ia_hack_tcq */
176
177static u16 get_desc (IADEV *dev, struct ia_vcc *iavcc) {
178 u_short desc_num, i;
179 struct sk_buff *skb;
180 struct ia_vcc *iavcc_r = NULL;
181 unsigned long delta;
182 static unsigned long timer = 0;
183 int ltimeout;
184
185 ia_hack_tcq (dev);
Julia Lawall420635f2008-04-19 18:14:50 -0700186 if((time_after(jiffies,timer+50)) || ((dev->ffL.tcq_rd==dev->host_tcq_wr))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 timer = jiffies;
188 i=0;
189 while (i < dev->num_tx_desc) {
190 if (!dev->desc_tbl[i].timestamp) {
191 i++;
192 continue;
193 }
194 ltimeout = dev->desc_tbl[i].iavcc->ltimeout;
195 delta = jiffies - dev->desc_tbl[i].timestamp;
196 if (delta >= ltimeout) {
197 IF_ABR(printk("RECOVER run!! desc_tbl %d = %d delta = %ld, time = %ld\n", i,dev->desc_tbl[i].timestamp, delta, jiffies);)
198 if (dev->ffL.tcq_rd == dev->ffL.tcq_st)
199 dev->ffL.tcq_rd = dev->ffL.tcq_ed;
200 else
201 dev->ffL.tcq_rd -= 2;
202 *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd) = i+1;
203 if (!(skb = dev->desc_tbl[i].txskb) ||
204 !(iavcc_r = dev->desc_tbl[i].iavcc))
205 printk("Fatal err, desc table vcc or skb is NULL\n");
206 else
207 iavcc_r->vc_desc_cnt--;
208 dev->desc_tbl[i].timestamp = 0;
209 dev->desc_tbl[i].iavcc = NULL;
210 dev->desc_tbl[i].txskb = NULL;
211 }
212 i++;
213 } /* while */
214 }
215 if (dev->ffL.tcq_rd == dev->host_tcq_wr)
216 return 0xFFFF;
217
218 /* Get the next available descriptor number from TCQ */
219 desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
220
221 while (!desc_num || (dev->desc_tbl[desc_num -1]).timestamp) {
222 dev->ffL.tcq_rd += 2;
223 if (dev->ffL.tcq_rd > dev->ffL.tcq_ed)
Julia Lawall6f74dbb2010-08-05 10:25:24 +0000224 dev->ffL.tcq_rd = dev->ffL.tcq_st;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 if (dev->ffL.tcq_rd == dev->host_tcq_wr)
226 return 0xFFFF;
227 desc_num = *(u_short *)(dev->seg_ram + dev->ffL.tcq_rd);
228 }
229
230 /* get system time */
231 dev->desc_tbl[desc_num -1].timestamp = jiffies;
232 return desc_num;
233}
234
235static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) {
236 u_char foundLockUp;
237 vcstatus_t *vcstatus;
238 u_short *shd_tbl;
239 u_short tempCellSlot, tempFract;
240 struct main_vc *abr_vc = (struct main_vc *)dev->MAIN_VC_TABLE_ADDR;
241 struct ext_vc *eabr_vc = (struct ext_vc *)dev->EXT_VC_TABLE_ADDR;
242 u_int i;
243
244 if (vcc->qos.txtp.traffic_class == ATM_ABR) {
245 vcstatus = (vcstatus_t *) &(dev->testTable[vcc->vci]->vc_status);
246 vcstatus->cnt++;
247 foundLockUp = 0;
248 if( vcstatus->cnt == 0x05 ) {
249 abr_vc += vcc->vci;
250 eabr_vc += vcc->vci;
251 if( eabr_vc->last_desc ) {
252 if( (abr_vc->status & 0x07) == ABR_STATE /* 0x2 */ ) {
253 /* Wait for 10 Micro sec */
254 udelay(10);
255 if ((eabr_vc->last_desc)&&((abr_vc->status & 0x07)==ABR_STATE))
256 foundLockUp = 1;
257 }
258 else {
259 tempCellSlot = abr_vc->last_cell_slot;
260 tempFract = abr_vc->fraction;
261 if((tempCellSlot == dev->testTable[vcc->vci]->lastTime)
262 && (tempFract == dev->testTable[vcc->vci]->fract))
263 foundLockUp = 1;
264 dev->testTable[vcc->vci]->lastTime = tempCellSlot;
265 dev->testTable[vcc->vci]->fract = tempFract;
266 }
267 } /* last descriptor */
268 vcstatus->cnt = 0;
269 } /* vcstatus->cnt */
270
271 if (foundLockUp) {
272 IF_ABR(printk("LOCK UP found\n");)
273 writew(0xFFFD, dev->seg_reg+MODE_REG_0);
274 /* Wait for 10 Micro sec */
275 udelay(10);
276 abr_vc->status &= 0xFFF8;
277 abr_vc->status |= 0x0001; /* state is idle */
278 shd_tbl = (u_short *)dev->ABR_SCHED_TABLE_ADDR;
279 for( i = 0; ((i < dev->num_vc) && (shd_tbl[i])); i++ );
280 if (i < dev->num_vc)
281 shd_tbl[i] = vcc->vci;
282 else
283 IF_ERR(printk("ABR Seg. may not continue on VC %x\n",vcc->vci);)
284 writew(T_ONLINE, dev->seg_reg+MODE_REG_0);
285 writew(~(TRANSMIT_DONE|TCQ_NOT_EMPTY), dev->seg_reg+SEG_MASK_REG);
286 writew(TRANSMIT_DONE, dev->seg_reg+SEG_INTR_STATUS_REG);
287 vcstatus->cnt = 0;
288 } /* foundLockUp */
289
290 } /* if an ABR VC */
291
292
293}
294
295/*
296** Conversion of 24-bit cellrate (cells/sec) to 16-bit floating point format.
297**
298** +----+----+------------------+-------------------------------+
299** | R | NZ | 5-bit exponent | 9-bit mantissa |
300** +----+----+------------------+-------------------------------+
301**
Matt LaPlante0779bf22006-11-30 05:24:39 +0100302** R = reserved (written as 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303** NZ = 0 if 0 cells/sec; 1 otherwise
304**
305** if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec
306*/
307static u16
308cellrate_to_float(u32 cr)
309{
310
311#define NZ 0x4000
312#define M_BITS 9 /* Number of bits in mantissa */
313#define E_BITS 5 /* Number of bits in exponent */
314#define M_MASK 0x1ff
315#define E_MASK 0x1f
316 u16 flot;
317 u32 tmp = cr & 0x00ffffff;
318 int i = 0;
319 if (cr == 0)
320 return 0;
321 while (tmp != 1) {
322 tmp >>= 1;
323 i++;
324 }
325 if (i == M_BITS)
326 flot = NZ | (i << M_BITS) | (cr & M_MASK);
327 else if (i < M_BITS)
328 flot = NZ | (i << M_BITS) | ((cr << (M_BITS - i)) & M_MASK);
329 else
330 flot = NZ | (i << M_BITS) | ((cr >> (i - M_BITS)) & M_MASK);
331 return flot;
332}
333
334#if 0
335/*
336** Conversion of 16-bit floating point format to 24-bit cellrate (cells/sec).
337*/
338static u32
339float_to_cellrate(u16 rate)
340{
341 u32 exp, mantissa, cps;
342 if ((rate & NZ) == 0)
343 return 0;
344 exp = (rate >> M_BITS) & E_MASK;
345 mantissa = rate & M_MASK;
346 if (exp == 0)
347 return 1;
348 cps = (1 << M_BITS) | mantissa;
349 if (exp == M_BITS)
350 cps = cps;
351 else if (exp > M_BITS)
352 cps <<= (exp - M_BITS);
353 else
354 cps >>= (M_BITS - exp);
355 return cps;
356}
357#endif
358
359static void init_abr_vc (IADEV *dev, srv_cls_param_t *srv_p) {
360 srv_p->class_type = ATM_ABR;
361 srv_p->pcr = dev->LineRate;
362 srv_p->mcr = 0;
363 srv_p->icr = 0x055cb7;
364 srv_p->tbe = 0xffffff;
365 srv_p->frtt = 0x3a;
366 srv_p->rif = 0xf;
367 srv_p->rdf = 0xb;
368 srv_p->nrm = 0x4;
369 srv_p->trm = 0x7;
370 srv_p->cdf = 0x3;
371 srv_p->adtf = 50;
372}
373
374static int
375ia_open_abr_vc(IADEV *dev, srv_cls_param_t *srv_p,
376 struct atm_vcc *vcc, u8 flag)
377{
378 f_vc_abr_entry *f_abr_vc;
379 r_vc_abr_entry *r_abr_vc;
380 u32 icr;
381 u8 trm, nrm, crm;
382 u16 adtf, air, *ptr16;
383 f_abr_vc =(f_vc_abr_entry *)dev->MAIN_VC_TABLE_ADDR;
384 f_abr_vc += vcc->vci;
385 switch (flag) {
386 case 1: /* FFRED initialization */
387#if 0 /* sanity check */
388 if (srv_p->pcr == 0)
389 return INVALID_PCR;
390 if (srv_p->pcr > dev->LineRate)
391 srv_p->pcr = dev->LineRate;
392 if ((srv_p->mcr + dev->sum_mcr) > dev->LineRate)
393 return MCR_UNAVAILABLE;
394 if (srv_p->mcr > srv_p->pcr)
395 return INVALID_MCR;
396 if (!(srv_p->icr))
397 srv_p->icr = srv_p->pcr;
398 if ((srv_p->icr < srv_p->mcr) || (srv_p->icr > srv_p->pcr))
399 return INVALID_ICR;
400 if ((srv_p->tbe < MIN_TBE) || (srv_p->tbe > MAX_TBE))
401 return INVALID_TBE;
402 if ((srv_p->frtt < MIN_FRTT) || (srv_p->frtt > MAX_FRTT))
403 return INVALID_FRTT;
404 if (srv_p->nrm > MAX_NRM)
405 return INVALID_NRM;
406 if (srv_p->trm > MAX_TRM)
407 return INVALID_TRM;
408 if (srv_p->adtf > MAX_ADTF)
409 return INVALID_ADTF;
410 else if (srv_p->adtf == 0)
411 srv_p->adtf = 1;
412 if (srv_p->cdf > MAX_CDF)
413 return INVALID_CDF;
414 if (srv_p->rif > MAX_RIF)
415 return INVALID_RIF;
416 if (srv_p->rdf > MAX_RDF)
417 return INVALID_RDF;
418#endif
419 memset ((caddr_t)f_abr_vc, 0, sizeof(*f_abr_vc));
420 f_abr_vc->f_vc_type = ABR;
421 nrm = 2 << srv_p->nrm; /* (2 ** (srv_p->nrm +1)) */
422 /* i.e 2**n = 2 << (n-1) */
423 f_abr_vc->f_nrm = nrm << 8 | nrm;
424 trm = 100000/(2 << (16 - srv_p->trm));
425 if ( trm == 0) trm = 1;
426 f_abr_vc->f_nrmexp =(((srv_p->nrm +1) & 0x0f) << 12)|(MRM << 8) | trm;
427 crm = srv_p->tbe / nrm;
428 if (crm == 0) crm = 1;
429 f_abr_vc->f_crm = crm & 0xff;
430 f_abr_vc->f_pcr = cellrate_to_float(srv_p->pcr);
431 icr = min( srv_p->icr, (srv_p->tbe > srv_p->frtt) ?
432 ((srv_p->tbe/srv_p->frtt)*1000000) :
433 (1000000/(srv_p->frtt/srv_p->tbe)));
434 f_abr_vc->f_icr = cellrate_to_float(icr);
435 adtf = (10000 * srv_p->adtf)/8192;
436 if (adtf == 0) adtf = 1;
437 f_abr_vc->f_cdf = ((7 - srv_p->cdf) << 12 | adtf) & 0xfff;
438 f_abr_vc->f_mcr = cellrate_to_float(srv_p->mcr);
439 f_abr_vc->f_acr = f_abr_vc->f_icr;
440 f_abr_vc->f_status = 0x0042;
441 break;
442 case 0: /* RFRED initialization */
443 ptr16 = (u_short *)(dev->reass_ram + REASS_TABLE*dev->memSize);
444 *(ptr16 + vcc->vci) = NO_AAL5_PKT | REASS_ABR;
445 r_abr_vc = (r_vc_abr_entry*)(dev->reass_ram+ABR_VC_TABLE*dev->memSize);
446 r_abr_vc += vcc->vci;
447 r_abr_vc->r_status_rdf = (15 - srv_p->rdf) & 0x000f;
448 air = srv_p->pcr << (15 - srv_p->rif);
449 if (air == 0) air = 1;
450 r_abr_vc->r_air = cellrate_to_float(air);
451 dev->testTable[vcc->vci]->vc_status = VC_ACTIVE | VC_ABR;
452 dev->sum_mcr += srv_p->mcr;
453 dev->n_abr++;
454 break;
455 default:
456 break;
457 }
458 return 0;
459}
460static int ia_cbr_setup (IADEV *dev, struct atm_vcc *vcc) {
461 u32 rateLow=0, rateHigh, rate;
462 int entries;
463 struct ia_vcc *ia_vcc;
464
465 int idealSlot =0, testSlot, toBeAssigned, inc;
466 u32 spacing;
467 u16 *SchedTbl, *TstSchedTbl;
468 u16 cbrVC, vcIndex;
469 u32 fracSlot = 0;
470 u32 sp_mod = 0;
471 u32 sp_mod2 = 0;
472
473 /* IpAdjustTrafficParams */
474 if (vcc->qos.txtp.max_pcr <= 0) {
475 IF_ERR(printk("PCR for CBR not defined\n");)
476 return -1;
477 }
478 rate = vcc->qos.txtp.max_pcr;
479 entries = rate / dev->Granularity;
480 IF_CBR(printk("CBR: CBR entries=0x%x for rate=0x%x & Gran=0x%x\n",
481 entries, rate, dev->Granularity);)
482 if (entries < 1)
483 IF_CBR(printk("CBR: Bandwidth smaller than granularity of CBR table\n");)
484 rateLow = entries * dev->Granularity;
485 rateHigh = (entries + 1) * dev->Granularity;
486 if (3*(rate - rateLow) > (rateHigh - rate))
487 entries++;
488 if (entries > dev->CbrRemEntries) {
489 IF_CBR(printk("CBR: Not enough bandwidth to support this PCR.\n");)
490 IF_CBR(printk("Entries = 0x%x, CbrRemEntries = 0x%x.\n",
491 entries, dev->CbrRemEntries);)
492 return -EBUSY;
493 }
494
495 ia_vcc = INPH_IA_VCC(vcc);
496 ia_vcc->NumCbrEntry = entries;
497 dev->sum_mcr += entries * dev->Granularity;
498 /* IaFFrednInsertCbrSched */
499 // Starting at an arbitrary location, place the entries into the table
500 // as smoothly as possible
501 cbrVC = 0;
502 spacing = dev->CbrTotEntries / entries;
503 sp_mod = dev->CbrTotEntries % entries; // get modulo
504 toBeAssigned = entries;
505 fracSlot = 0;
506 vcIndex = vcc->vci;
507 IF_CBR(printk("Vci=0x%x,Spacing=0x%x,Sp_mod=0x%x\n",vcIndex,spacing,sp_mod);)
508 while (toBeAssigned)
509 {
510 // If this is the first time, start the table loading for this connection
511 // as close to entryPoint as possible.
512 if (toBeAssigned == entries)
513 {
514 idealSlot = dev->CbrEntryPt;
515 dev->CbrEntryPt += 2; // Adding 2 helps to prevent clumping
516 if (dev->CbrEntryPt >= dev->CbrTotEntries)
517 dev->CbrEntryPt -= dev->CbrTotEntries;// Wrap if necessary
518 } else {
519 idealSlot += (u32)(spacing + fracSlot); // Point to the next location
520 // in the table that would be smoothest
521 fracSlot = ((sp_mod + sp_mod2) / entries); // get new integer part
522 sp_mod2 = ((sp_mod + sp_mod2) % entries); // calc new fractional part
523 }
524 if (idealSlot >= (int)dev->CbrTotEntries)
525 idealSlot -= dev->CbrTotEntries;
526 // Continuously check around this ideal value until a null
527 // location is encountered.
528 SchedTbl = (u16*)(dev->seg_ram+CBR_SCHED_TABLE*dev->memSize);
529 inc = 0;
530 testSlot = idealSlot;
531 TstSchedTbl = (u16*)(SchedTbl+testSlot); //set index and read in value
David Howells849e8ca2008-07-30 16:33:05 -0700532 IF_CBR(printk("CBR Testslot 0x%x AT Location 0x%p, NumToAssign=%d\n",
533 testSlot, TstSchedTbl,toBeAssigned);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
535 while (cbrVC) // If another VC at this location, we have to keep looking
536 {
537 inc++;
538 testSlot = idealSlot - inc;
539 if (testSlot < 0) { // Wrap if necessary
540 testSlot += dev->CbrTotEntries;
David Howells849e8ca2008-07-30 16:33:05 -0700541 IF_CBR(printk("Testslot Wrap. STable Start=0x%p,Testslot=%d\n",
542 SchedTbl,testSlot);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
544 TstSchedTbl = (u16 *)(SchedTbl + testSlot); // set table index
545 memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
546 if (!cbrVC)
547 break;
548 testSlot = idealSlot + inc;
549 if (testSlot >= (int)dev->CbrTotEntries) { // Wrap if necessary
550 testSlot -= dev->CbrTotEntries;
551 IF_CBR(printk("TotCbrEntries=%d",dev->CbrTotEntries);)
552 IF_CBR(printk(" Testslot=0x%x ToBeAssgned=%d\n",
553 testSlot, toBeAssigned);)
554 }
555 // set table index and read in value
556 TstSchedTbl = (u16*)(SchedTbl + testSlot);
David Howells849e8ca2008-07-30 16:33:05 -0700557 IF_CBR(printk("Reading CBR Tbl from 0x%p, CbrVal=0x%x Iteration %d\n",
558 TstSchedTbl,cbrVC,inc);)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
560 } /* while */
561 // Move this VCI number into this location of the CBR Sched table.
Julia Lawall710708e82009-12-13 01:40:55 +0000562 memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex, sizeof(*TstSchedTbl));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 dev->CbrRemEntries--;
564 toBeAssigned--;
565 } /* while */
566
567 /* IaFFrednCbrEnable */
568 dev->NumEnabledCBR++;
569 if (dev->NumEnabledCBR == 1) {
570 writew((CBR_EN | UBR_EN | ABR_EN | (0x23 << 2)), dev->seg_reg+STPARMS);
571 IF_CBR(printk("CBR is enabled\n");)
572 }
573 return 0;
574}
575static void ia_cbrVc_close (struct atm_vcc *vcc) {
576 IADEV *iadev;
577 u16 *SchedTbl, NullVci = 0;
578 u32 i, NumFound;
579
580 iadev = INPH_IA_DEV(vcc->dev);
581 iadev->NumEnabledCBR--;
582 SchedTbl = (u16*)(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize);
583 if (iadev->NumEnabledCBR == 0) {
584 writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);
585 IF_CBR (printk("CBR support disabled\n");)
586 }
587 NumFound = 0;
588 for (i=0; i < iadev->CbrTotEntries; i++)
589 {
590 if (*SchedTbl == vcc->vci) {
591 iadev->CbrRemEntries++;
592 *SchedTbl = NullVci;
593 IF_CBR(NumFound++;)
594 }
595 SchedTbl++;
596 }
597 IF_CBR(printk("Exit ia_cbrVc_close, NumRemoved=%d\n",NumFound);)
598}
599
600static int ia_avail_descs(IADEV *iadev) {
601 int tmp = 0;
602 ia_hack_tcq(iadev);
603 if (iadev->host_tcq_wr >= iadev->ffL.tcq_rd)
604 tmp = (iadev->host_tcq_wr - iadev->ffL.tcq_rd) / 2;
605 else
606 tmp = (iadev->ffL.tcq_ed - iadev->ffL.tcq_rd + 2 + iadev->host_tcq_wr -
607 iadev->ffL.tcq_st) / 2;
608 return tmp;
609}
610
611static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb);
612
613static int ia_que_tx (IADEV *iadev) {
614 struct sk_buff *skb;
615 int num_desc;
616 struct atm_vcc *vcc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 num_desc = ia_avail_descs(iadev);
618
619 while (num_desc && (skb = skb_dequeue(&iadev->tx_backlog))) {
620 if (!(vcc = ATM_SKB(skb)->vcc)) {
621 dev_kfree_skb_any(skb);
622 printk("ia_que_tx: Null vcc\n");
623 break;
624 }
625 if (!test_bit(ATM_VF_READY,&vcc->flags)) {
626 dev_kfree_skb_any(skb);
627 printk("Free the SKB on closed vci %d \n", vcc->vci);
628 break;
629 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 if (ia_pkt_tx (vcc, skb)) {
631 skb_queue_head(&iadev->tx_backlog, skb);
632 }
633 num_desc--;
634 }
635 return 0;
636}
637
638static void ia_tx_poll (IADEV *iadev) {
639 struct atm_vcc *vcc = NULL;
640 struct sk_buff *skb = NULL, *skb1 = NULL;
641 struct ia_vcc *iavcc;
642 IARTN_Q * rtne;
643
644 ia_hack_tcq(iadev);
645 while ( (rtne = ia_deque_rtn_q(&iadev->tx_return_q))) {
646 skb = rtne->data.txskb;
647 if (!skb) {
648 printk("ia_tx_poll: skb is null\n");
649 goto out;
650 }
651 vcc = ATM_SKB(skb)->vcc;
652 if (!vcc) {
653 printk("ia_tx_poll: vcc is null\n");
654 dev_kfree_skb_any(skb);
655 goto out;
656 }
657
658 iavcc = INPH_IA_VCC(vcc);
659 if (!iavcc) {
660 printk("ia_tx_poll: iavcc is null\n");
661 dev_kfree_skb_any(skb);
662 goto out;
663 }
664
665 skb1 = skb_dequeue(&iavcc->txing_skb);
666 while (skb1 && (skb1 != skb)) {
667 if (!(IA_SKB_STATE(skb1) & IA_TX_DONE)) {
668 printk("IA_tx_intr: Vci %d lost pkt!!!\n", vcc->vci);
669 }
670 IF_ERR(printk("Release the SKB not match\n");)
671 if ((vcc->pop) && (skb1->len != 0))
672 {
673 vcc->pop(vcc, skb1);
674 IF_EVENT(printk("Tansmit Done - skb 0x%lx return\n",
675 (long)skb1);)
676 }
677 else
678 dev_kfree_skb_any(skb1);
679 skb1 = skb_dequeue(&iavcc->txing_skb);
680 }
681 if (!skb1) {
682 IF_EVENT(printk("IA: Vci %d - skb not found requed\n",vcc->vci);)
683 ia_enque_head_rtn_q (&iadev->tx_return_q, rtne);
684 break;
685 }
686 if ((vcc->pop) && (skb->len != 0))
687 {
688 vcc->pop(vcc, skb);
689 IF_EVENT(printk("Tx Done - skb 0x%lx return\n",(long)skb);)
690 }
691 else
692 dev_kfree_skb_any(skb);
693 kfree(rtne);
694 }
695 ia_que_tx(iadev);
696out:
697 return;
698}
699#if 0
700static void ia_eeprom_put (IADEV *iadev, u32 addr, u_short val)
701{
702 u32 t;
703 int i;
704 /*
705 * Issue a command to enable writes to the NOVRAM
706 */
707 NVRAM_CMD (EXTEND + EWEN);
708 NVRAM_CLR_CE;
709 /*
710 * issue the write command
711 */
712 NVRAM_CMD(IAWRITE + addr);
713 /*
714 * Send the data, starting with D15, then D14, and so on for 16 bits
715 */
716 for (i=15; i>=0; i--) {
717 NVRAM_CLKOUT (val & 0x8000);
718 val <<= 1;
719 }
720 NVRAM_CLR_CE;
721 CFG_OR(NVCE);
722 t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS);
723 while (!(t & NVDO))
724 t = readl(iadev->reg+IPHASE5575_EEPROM_ACCESS);
725
726 NVRAM_CLR_CE;
727 /*
728 * disable writes again
729 */
730 NVRAM_CMD(EXTEND + EWDS)
731 NVRAM_CLR_CE;
732 CFG_AND(~NVDI);
733}
734#endif
735
736static u16 ia_eeprom_get (IADEV *iadev, u32 addr)
737{
738 u_short val;
739 u32 t;
740 int i;
741 /*
742 * Read the first bit that was clocked with the falling edge of the
743 * the last command data clock
744 */
745 NVRAM_CMD(IAREAD + addr);
746 /*
747 * Now read the rest of the bits, the next bit read is D14, then D13,
748 * and so on.
749 */
750 val = 0;
751 for (i=15; i>=0; i--) {
752 NVRAM_CLKIN(t);
753 val |= (t << i);
754 }
755 NVRAM_CLR_CE;
756 CFG_AND(~NVDI);
757 return val;
758}
759
760static void ia_hw_type(IADEV *iadev) {
761 u_short memType = ia_eeprom_get(iadev, 25);
762 iadev->memType = memType;
763 if ((memType & MEM_SIZE_MASK) == MEM_SIZE_1M) {
764 iadev->num_tx_desc = IA_TX_BUF;
765 iadev->tx_buf_sz = IA_TX_BUF_SZ;
766 iadev->num_rx_desc = IA_RX_BUF;
767 iadev->rx_buf_sz = IA_RX_BUF_SZ;
768 } else if ((memType & MEM_SIZE_MASK) == MEM_SIZE_512K) {
769 if (IA_TX_BUF == DFL_TX_BUFFERS)
770 iadev->num_tx_desc = IA_TX_BUF / 2;
771 else
772 iadev->num_tx_desc = IA_TX_BUF;
773 iadev->tx_buf_sz = IA_TX_BUF_SZ;
774 if (IA_RX_BUF == DFL_RX_BUFFERS)
775 iadev->num_rx_desc = IA_RX_BUF / 2;
776 else
777 iadev->num_rx_desc = IA_RX_BUF;
778 iadev->rx_buf_sz = IA_RX_BUF_SZ;
779 }
780 else {
781 if (IA_TX_BUF == DFL_TX_BUFFERS)
782 iadev->num_tx_desc = IA_TX_BUF / 8;
783 else
784 iadev->num_tx_desc = IA_TX_BUF;
785 iadev->tx_buf_sz = IA_TX_BUF_SZ;
786 if (IA_RX_BUF == DFL_RX_BUFFERS)
787 iadev->num_rx_desc = IA_RX_BUF / 8;
788 else
789 iadev->num_rx_desc = IA_RX_BUF;
790 iadev->rx_buf_sz = IA_RX_BUF_SZ;
791 }
792 iadev->rx_pkt_ram = TX_PACKET_RAM + (iadev->num_tx_desc * iadev->tx_buf_sz);
793 IF_INIT(printk("BUF: tx=%d,sz=%d rx=%d sz= %d rx_pkt_ram=%d\n",
794 iadev->num_tx_desc, iadev->tx_buf_sz, iadev->num_rx_desc,
795 iadev->rx_buf_sz, iadev->rx_pkt_ram);)
796
797#if 0
798 if ((memType & FE_MASK) == FE_SINGLE_MODE) {
799 iadev->phy_type = PHY_OC3C_S;
800 else if ((memType & FE_MASK) == FE_UTP_OPTION)
801 iadev->phy_type = PHY_UTP155;
802 else
803 iadev->phy_type = PHY_OC3C_M;
804#endif
805
806 iadev->phy_type = memType & FE_MASK;
807 IF_INIT(printk("memType = 0x%x iadev->phy_type = 0x%x\n",
808 memType,iadev->phy_type);)
809 if (iadev->phy_type == FE_25MBIT_PHY)
810 iadev->LineRate = (u32)(((25600000/8)*26)/(27*53));
811 else if (iadev->phy_type == FE_DS3_PHY)
812 iadev->LineRate = (u32)(((44736000/8)*26)/(27*53));
813 else if (iadev->phy_type == FE_E3_PHY)
814 iadev->LineRate = (u32)(((34368000/8)*26)/(27*53));
815 else
816 iadev->LineRate = (u32)(ATM_OC3_PCR);
817 IF_INIT(printk("iadev->LineRate = %d \n", iadev->LineRate);)
818
819}
820
françois romieu26c5c442011-09-30 00:37:43 +0000821static u32 ia_phy_read32(struct iadev_priv *ia, unsigned int reg)
822{
823 return readl(ia->phy + (reg >> 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824}
825
françois romieu26c5c442011-09-30 00:37:43 +0000826static void ia_phy_write32(struct iadev_priv *ia, unsigned int reg, u32 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
françois romieu26c5c442011-09-30 00:37:43 +0000828 writel(val, ia->phy + (reg >> 2));
829}
830
831static void ia_frontend_intr(struct iadev_priv *iadev)
832{
833 u32 status;
834
835 if (iadev->phy_type & FE_25MBIT_PHY) {
836 status = ia_phy_read32(iadev, MB25_INTR_STATUS);
837 iadev->carrier_detect = (status & MB25_IS_GSB) ? 1 : 0;
838 } else if (iadev->phy_type & FE_DS3_PHY) {
839 ia_phy_read32(iadev, SUNI_DS3_FRM_INTR_STAT);
840 status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
841 iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
842 } else if (iadev->phy_type & FE_E3_PHY) {
843 ia_phy_read32(iadev, SUNI_E3_FRM_MAINT_INTR_IND);
844 status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
845 iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
846 } else {
847 status = ia_phy_read32(iadev, SUNI_RSOP_STATUS);
848 iadev->carrier_detect = (status & SUNI_LOSV) ? 0 : 1;
849 }
850
851 printk(KERN_INFO "IA: SUNI carrier %s\n",
852 iadev->carrier_detect ? "detected" : "lost signal");
853}
854
855static void ia_mb25_init(struct iadev_priv *iadev)
856{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857#if 0
858 mb25->mb25_master_ctrl = MB25_MC_DRIC | MB25_MC_DREC | MB25_MC_ENABLED;
859#endif
françois romieu26c5c442011-09-30 00:37:43 +0000860 ia_phy_write32(iadev, MB25_MASTER_CTRL, MB25_MC_DRIC | MB25_MC_DREC);
861 ia_phy_write32(iadev, MB25_DIAG_CONTROL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
françois romieu26c5c442011-09-30 00:37:43 +0000863 iadev->carrier_detect =
864 (ia_phy_read32(iadev, MB25_INTR_STATUS) & MB25_IS_GSB) ? 1 : 0;
865}
866
867struct ia_reg {
868 u16 reg;
869 u16 val;
870};
871
872static void ia_phy_write(struct iadev_priv *iadev,
873 const struct ia_reg *regs, int len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874{
françois romieu26c5c442011-09-30 00:37:43 +0000875 while (len--) {
876 ia_phy_write32(iadev, regs->reg, regs->val);
877 regs++;
878 }
879}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
françois romieu26c5c442011-09-30 00:37:43 +0000881static void ia_suni_pm7345_init_ds3(struct iadev_priv *iadev)
882{
883 static const struct ia_reg suni_ds3_init [] = {
884 { SUNI_DS3_FRM_INTR_ENBL, 0x17 },
885 { SUNI_DS3_FRM_CFG, 0x01 },
886 { SUNI_DS3_TRAN_CFG, 0x01 },
887 { SUNI_CONFIG, 0 },
888 { SUNI_SPLR_CFG, 0 },
889 { SUNI_SPLT_CFG, 0 }
890 };
891 u32 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
françois romieu26c5c442011-09-30 00:37:43 +0000893 status = ia_phy_read32(iadev, SUNI_DS3_FRM_STAT);
894 iadev->carrier_detect = (status & SUNI_DS3_LOSV) ? 0 : 1;
895
896 ia_phy_write(iadev, suni_ds3_init, ARRAY_SIZE(suni_ds3_init));
897}
898
899static void ia_suni_pm7345_init_e3(struct iadev_priv *iadev)
900{
901 static const struct ia_reg suni_e3_init [] = {
902 { SUNI_E3_FRM_FRAM_OPTIONS, 0x04 },
903 { SUNI_E3_FRM_MAINT_OPTIONS, 0x20 },
904 { SUNI_E3_FRM_FRAM_INTR_ENBL, 0x1d },
905 { SUNI_E3_FRM_MAINT_INTR_ENBL, 0x30 },
906 { SUNI_E3_TRAN_STAT_DIAG_OPTIONS, 0 },
907 { SUNI_E3_TRAN_FRAM_OPTIONS, 0x01 },
908 { SUNI_CONFIG, SUNI_PM7345_E3ENBL },
909 { SUNI_SPLR_CFG, 0x41 },
910 { SUNI_SPLT_CFG, 0x41 }
911 };
912 u32 status;
913
914 status = ia_phy_read32(iadev, SUNI_E3_FRM_FRAM_INTR_IND_STAT);
915 iadev->carrier_detect = (status & SUNI_E3_LOS) ? 0 : 1;
916 ia_phy_write(iadev, suni_e3_init, ARRAY_SIZE(suni_e3_init));
917}
918
919static void ia_suni_pm7345_init(struct iadev_priv *iadev)
920{
921 static const struct ia_reg suni_init [] = {
922 /* Enable RSOP loss of signal interrupt. */
923 { SUNI_INTR_ENBL, 0x28 },
924 /* Clear error counters. */
925 { SUNI_ID_RESET, 0 },
926 /* Clear "PMCTST" in master test register. */
927 { SUNI_MASTER_TEST, 0 },
928
929 { SUNI_RXCP_CTRL, 0x2c },
930 { SUNI_RXCP_FCTRL, 0x81 },
931
932 { SUNI_RXCP_IDLE_PAT_H1, 0 },
933 { SUNI_RXCP_IDLE_PAT_H2, 0 },
934 { SUNI_RXCP_IDLE_PAT_H3, 0 },
935 { SUNI_RXCP_IDLE_PAT_H4, 0x01 },
936
937 { SUNI_RXCP_IDLE_MASK_H1, 0xff },
938 { SUNI_RXCP_IDLE_MASK_H2, 0xff },
939 { SUNI_RXCP_IDLE_MASK_H3, 0xff },
940 { SUNI_RXCP_IDLE_MASK_H4, 0xfe },
941
942 { SUNI_RXCP_CELL_PAT_H1, 0 },
943 { SUNI_RXCP_CELL_PAT_H2, 0 },
944 { SUNI_RXCP_CELL_PAT_H3, 0 },
945 { SUNI_RXCP_CELL_PAT_H4, 0x01 },
946
947 { SUNI_RXCP_CELL_MASK_H1, 0xff },
948 { SUNI_RXCP_CELL_MASK_H2, 0xff },
949 { SUNI_RXCP_CELL_MASK_H3, 0xff },
950 { SUNI_RXCP_CELL_MASK_H4, 0xff },
951
952 { SUNI_TXCP_CTRL, 0xa4 },
953 { SUNI_TXCP_INTR_EN_STS, 0x10 },
954 { SUNI_TXCP_IDLE_PAT_H5, 0x55 }
955 };
956
957 if (iadev->phy_type & FE_DS3_PHY)
958 ia_suni_pm7345_init_ds3(iadev);
959 else
960 ia_suni_pm7345_init_e3(iadev);
961
962 ia_phy_write(iadev, suni_init, ARRAY_SIZE(suni_init));
963
964 ia_phy_write32(iadev, SUNI_CONFIG, ia_phy_read32(iadev, SUNI_CONFIG) &
965 ~(SUNI_PM7345_LLB | SUNI_PM7345_CLB |
966 SUNI_PM7345_DLB | SUNI_PM7345_PLB));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967#ifdef __SNMP__
968 suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE;
969#endif /* __SNMP__ */
970 return;
971}
972
973
974/***************************** IA_LIB END *****************************/
975
Leonardo Potenzaa22eb6f2008-04-02 00:03:00 -0700976#ifdef CONFIG_ATM_IA_DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977static int tcnter = 0;
978static void xdump( u_char* cp, int length, char* prefix )
979{
980 int col, count;
981 u_char prntBuf[120];
982 u_char* pBuf = prntBuf;
983 count = 0;
984 while(count < length){
985 pBuf += sprintf( pBuf, "%s", prefix );
986 for(col = 0;count + col < length && col < 16; col++){
987 if (col != 0 && (col % 4) == 0)
988 pBuf += sprintf( pBuf, " " );
989 pBuf += sprintf( pBuf, "%02X ", cp[count + col] );
990 }
991 while(col++ < 16){ /* pad end of buffer with blanks */
992 if ((col % 4) == 0)
993 sprintf( pBuf, " " );
994 pBuf += sprintf( pBuf, " " );
995 }
996 pBuf += sprintf( pBuf, " " );
997 for(col = 0;count + col < length && col < 16; col++){
998 if (isprint((int)cp[count + col]))
999 pBuf += sprintf( pBuf, "%c", cp[count + col] );
1000 else
1001 pBuf += sprintf( pBuf, "." );
1002 }
Stephen Hemminger32f3dde2009-03-20 06:44:02 +00001003 printk("%s\n", prntBuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 count += col;
1005 pBuf = prntBuf;
1006 }
1007
1008} /* close xdump(... */
Leonardo Potenzaa22eb6f2008-04-02 00:03:00 -07001009#endif /* CONFIG_ATM_IA_DEBUG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
1011
1012static struct atm_dev *ia_boards = NULL;
1013
1014#define ACTUAL_RAM_BASE \
1015 RAM_BASE*((iadev->mem)/(128 * 1024))
1016#define ACTUAL_SEG_RAM_BASE \
1017 IPHASE5575_FRAG_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024))
1018#define ACTUAL_REASS_RAM_BASE \
1019 IPHASE5575_REASS_CONTROL_RAM_BASE*((iadev->mem)/(128 * 1024))
1020
1021
1022/*-- some utilities and memory allocation stuff will come here -------------*/
1023
1024static void desc_dbg(IADEV *iadev) {
1025
1026 u_short tcq_wr_ptr, tcq_st_ptr, tcq_ed_ptr;
1027 u32 i;
1028 void __iomem *tmp;
1029 // regval = readl((u32)ia_cmds->maddr);
1030 tcq_wr_ptr = readw(iadev->seg_reg+TCQ_WR_PTR);
1031 printk("B_tcq_wr = 0x%x desc = %d last desc = %d\n",
1032 tcq_wr_ptr, readw(iadev->seg_ram+tcq_wr_ptr),
1033 readw(iadev->seg_ram+tcq_wr_ptr-2));
1034 printk(" host_tcq_wr = 0x%x host_tcq_rd = 0x%x \n", iadev->host_tcq_wr,
1035 iadev->ffL.tcq_rd);
1036 tcq_st_ptr = readw(iadev->seg_reg+TCQ_ST_ADR);
1037 tcq_ed_ptr = readw(iadev->seg_reg+TCQ_ED_ADR);
1038 printk("tcq_st_ptr = 0x%x tcq_ed_ptr = 0x%x \n", tcq_st_ptr, tcq_ed_ptr);
1039 i = 0;
1040 while (tcq_st_ptr != tcq_ed_ptr) {
1041 tmp = iadev->seg_ram+tcq_st_ptr;
1042 printk("TCQ slot %d desc = %d Addr = %p\n", i++, readw(tmp), tmp);
1043 tcq_st_ptr += 2;
1044 }
1045 for(i=0; i <iadev->num_tx_desc; i++)
1046 printk("Desc_tbl[%d] = %d \n", i, iadev->desc_tbl[i].timestamp);
1047}
1048
1049
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001050/*----------------------------- Receiving side stuff --------------------------*/
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
1052static void rx_excp_rcvd(struct atm_dev *dev)
1053{
1054#if 0 /* closing the receiving size will cause too many excp int */
1055 IADEV *iadev;
1056 u_short state;
1057 u_short excpq_rd_ptr;
1058 //u_short *ptr;
1059 int vci, error = 1;
1060 iadev = INPH_IA_DEV(dev);
1061 state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
1062 while((state & EXCPQ_EMPTY) != EXCPQ_EMPTY)
1063 { printk("state = %x \n", state);
1064 excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_RD_PTR) & 0xffff;
1065 printk("state = %x excpq_rd_ptr = %x \n", state, excpq_rd_ptr);
1066 if (excpq_rd_ptr == *(u16*)(iadev->reass_reg + EXCP_Q_WR_PTR))
1067 IF_ERR(printk("excpq_rd_ptr is wrong!!!\n");)
1068 // TODO: update exception stat
1069 vci = readw(iadev->reass_ram+excpq_rd_ptr);
1070 error = readw(iadev->reass_ram+excpq_rd_ptr+2) & 0x0007;
1071 // pwang_test
1072 excpq_rd_ptr += 4;
1073 if (excpq_rd_ptr > (readw(iadev->reass_reg + EXCP_Q_ED_ADR)& 0xffff))
1074 excpq_rd_ptr = readw(iadev->reass_reg + EXCP_Q_ST_ADR)& 0xffff;
1075 writew( excpq_rd_ptr, iadev->reass_reg + EXCP_Q_RD_PTR);
1076 state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
1077 }
1078#endif
1079}
1080
1081static void free_desc(struct atm_dev *dev, int desc)
1082{
1083 IADEV *iadev;
1084 iadev = INPH_IA_DEV(dev);
1085 writew(desc, iadev->reass_ram+iadev->rfL.fdq_wr);
1086 iadev->rfL.fdq_wr +=2;
1087 if (iadev->rfL.fdq_wr > iadev->rfL.fdq_ed)
1088 iadev->rfL.fdq_wr = iadev->rfL.fdq_st;
1089 writew(iadev->rfL.fdq_wr, iadev->reass_reg+FREEQ_WR_PTR);
1090}
1091
1092
1093static int rx_pkt(struct atm_dev *dev)
1094{
1095 IADEV *iadev;
1096 struct atm_vcc *vcc;
1097 unsigned short status;
1098 struct rx_buf_desc __iomem *buf_desc_ptr;
1099 int desc;
1100 struct dle* wr_ptr;
1101 int len;
1102 struct sk_buff *skb;
1103 u_int buf_addr, dma_addr;
1104
1105 iadev = INPH_IA_DEV(dev);
1106 if (iadev->rfL.pcq_rd == (readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff))
1107 {
1108 printk(KERN_ERR DEV_LABEL "(itf %d) Receive queue empty\n", dev->number);
1109 return -EINVAL;
1110 }
1111 /* mask 1st 3 bits to get the actual descno. */
1112 desc = readw(iadev->reass_ram+iadev->rfL.pcq_rd) & 0x1fff;
1113 IF_RX(printk("reass_ram = %p iadev->rfL.pcq_rd = 0x%x desc = %d\n",
1114 iadev->reass_ram, iadev->rfL.pcq_rd, desc);
1115 printk(" pcq_wr_ptr = 0x%x\n",
1116 readw(iadev->reass_reg+PCQ_WR_PTR)&0xffff);)
1117 /* update the read pointer - maybe we shud do this in the end*/
1118 if ( iadev->rfL.pcq_rd== iadev->rfL.pcq_ed)
1119 iadev->rfL.pcq_rd = iadev->rfL.pcq_st;
1120 else
1121 iadev->rfL.pcq_rd += 2;
1122 writew(iadev->rfL.pcq_rd, iadev->reass_reg+PCQ_RD_PTR);
1123
1124 /* get the buffer desc entry.
1125 update stuff. - doesn't seem to be any update necessary
1126 */
1127 buf_desc_ptr = iadev->RX_DESC_BASE_ADDR;
1128 /* make the ptr point to the corresponding buffer desc entry */
1129 buf_desc_ptr += desc;
1130 if (!desc || (desc > iadev->num_rx_desc) ||
1131 ((buf_desc_ptr->vc_index & 0xffff) > iadev->num_vc)) {
1132 free_desc(dev, desc);
1133 IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
1134 return -1;
1135 }
1136 vcc = iadev->rx_open[buf_desc_ptr->vc_index & 0xffff];
1137 if (!vcc)
1138 {
1139 free_desc(dev, desc);
1140 printk("IA: null vcc, drop PDU\n");
1141 return -1;
1142 }
1143
1144
1145 /* might want to check the status bits for errors */
1146 status = (u_short) (buf_desc_ptr->desc_mode);
1147 if (status & (RX_CER | RX_PTE | RX_OFL))
1148 {
1149 atomic_inc(&vcc->stats->rx_err);
1150 IF_ERR(printk("IA: bad packet, dropping it");)
1151 if (status & RX_CER) {
1152 IF_ERR(printk(" cause: packet CRC error\n");)
1153 }
1154 else if (status & RX_PTE) {
1155 IF_ERR(printk(" cause: packet time out\n");)
1156 }
1157 else {
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02001158 IF_ERR(printk(" cause: buffer overflow\n");)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 }
1160 goto out_free_desc;
1161 }
1162
1163 /*
1164 build DLE.
1165 */
1166
1167 buf_addr = (buf_desc_ptr->buf_start_hi << 16) | buf_desc_ptr->buf_start_lo;
1168 dma_addr = (buf_desc_ptr->dma_start_hi << 16) | buf_desc_ptr->dma_start_lo;
1169 len = dma_addr - buf_addr;
1170 if (len > iadev->rx_buf_sz) {
1171 printk("Over %d bytes sdu received, dropped!!!\n", iadev->rx_buf_sz);
1172 atomic_inc(&vcc->stats->rx_err);
1173 goto out_free_desc;
1174 }
1175
1176 if (!(skb = atm_alloc_charge(vcc, len, GFP_ATOMIC))) {
1177 if (vcc->vci < 32)
1178 printk("Drop control packets\n");
1179 goto out_free_desc;
1180 }
1181 skb_put(skb,len);
1182 // pwang_test
1183 ATM_SKB(skb)->vcc = vcc;
1184 ATM_DESC(skb) = desc;
1185 skb_queue_tail(&iadev->rx_dma_q, skb);
1186
1187 /* Build the DLE structure */
1188 wr_ptr = iadev->rx_dle_q.write;
1189 wr_ptr->sys_pkt_addr = pci_map_single(iadev->pci, skb->data,
1190 len, PCI_DMA_FROMDEVICE);
1191 wr_ptr->local_pkt_addr = buf_addr;
1192 wr_ptr->bytes = len; /* We don't know this do we ?? */
1193 wr_ptr->mode = DMA_INT_ENABLE;
1194
1195 /* shud take care of wrap around here too. */
1196 if(++wr_ptr == iadev->rx_dle_q.end)
1197 wr_ptr = iadev->rx_dle_q.start;
1198 iadev->rx_dle_q.write = wr_ptr;
1199 udelay(1);
1200 /* Increment transaction counter */
1201 writel(1, iadev->dma+IPHASE5575_RX_COUNTER);
1202out: return 0;
1203out_free_desc:
1204 free_desc(dev, desc);
1205 goto out;
1206}
1207
1208static void rx_intr(struct atm_dev *dev)
1209{
1210 IADEV *iadev;
1211 u_short status;
1212 u_short state, i;
1213
1214 iadev = INPH_IA_DEV(dev);
1215 status = readl(iadev->reass_reg+REASS_INTR_STATUS_REG) & 0xffff;
1216 IF_EVENT(printk("rx_intr: status = 0x%x\n", status);)
1217 if (status & RX_PKT_RCVD)
1218 {
1219 /* do something */
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001220 /* Basically recvd an interrupt for receiving a packet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 A descriptor would have been written to the packet complete
1222 queue. Get all the descriptors and set up dma to move the
1223 packets till the packet complete queue is empty..
1224 */
1225 state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
1226 IF_EVENT(printk("Rx intr status: RX_PKT_RCVD %08x\n", status);)
1227 while(!(state & PCQ_EMPTY))
1228 {
1229 rx_pkt(dev);
1230 state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
1231 }
1232 iadev->rxing = 1;
1233 }
1234 if (status & RX_FREEQ_EMPT)
1235 {
1236 if (iadev->rxing) {
1237 iadev->rx_tmp_cnt = iadev->rx_pkt_cnt;
1238 iadev->rx_tmp_jif = jiffies;
1239 iadev->rxing = 0;
1240 }
Julia Lawall420635f2008-04-19 18:14:50 -07001241 else if ((time_after(jiffies, iadev->rx_tmp_jif + 50)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 ((iadev->rx_pkt_cnt - iadev->rx_tmp_cnt) == 0)) {
1243 for (i = 1; i <= iadev->num_rx_desc; i++)
1244 free_desc(dev, i);
1245printk("Test logic RUN!!!!\n");
1246 writew( ~(RX_FREEQ_EMPT|RX_EXCP_RCVD),iadev->reass_reg+REASS_MASK_REG);
1247 iadev->rxing = 1;
1248 }
1249 IF_EVENT(printk("Rx intr status: RX_FREEQ_EMPT %08x\n", status);)
1250 }
1251
1252 if (status & RX_EXCP_RCVD)
1253 {
1254 /* probably need to handle the exception queue also. */
1255 IF_EVENT(printk("Rx intr status: RX_EXCP_RCVD %08x\n", status);)
1256 rx_excp_rcvd(dev);
1257 }
1258
1259
1260 if (status & RX_RAW_RCVD)
1261 {
1262 /* need to handle the raw incoming cells. This deepnds on
1263 whether we have programmed to receive the raw cells or not.
1264 Else ignore. */
1265 IF_EVENT(printk("Rx intr status: RX_RAW_RCVD %08x\n", status);)
1266 }
1267}
1268
1269
1270static void rx_dle_intr(struct atm_dev *dev)
1271{
1272 IADEV *iadev;
1273 struct atm_vcc *vcc;
1274 struct sk_buff *skb;
1275 int desc;
1276 u_short state;
1277 struct dle *dle, *cur_dle;
1278 u_int dle_lp;
1279 int len;
1280 iadev = INPH_IA_DEV(dev);
1281
1282 /* free all the dles done, that is just update our own dle read pointer
1283 - do we really need to do this. Think not. */
1284 /* DMA is done, just get all the recevie buffers from the rx dma queue
1285 and push them up to the higher layer protocol. Also free the desc
1286 associated with the buffer. */
1287 dle = iadev->rx_dle_q.read;
1288 dle_lp = readl(iadev->dma+IPHASE5575_RX_LIST_ADDR) & (sizeof(struct dle)*DLE_ENTRIES - 1);
1289 cur_dle = (struct dle*)(iadev->rx_dle_q.start + (dle_lp >> 4));
1290 while(dle != cur_dle)
1291 {
1292 /* free the DMAed skb */
1293 skb = skb_dequeue(&iadev->rx_dma_q);
1294 if (!skb)
1295 goto INCR_DLE;
1296 desc = ATM_DESC(skb);
1297 free_desc(dev, desc);
1298
1299 if (!(len = skb->len))
1300 {
1301 printk("rx_dle_intr: skb len 0\n");
1302 dev_kfree_skb_any(skb);
1303 }
1304 else
1305 {
1306 struct cpcs_trailer *trailer;
1307 u_short length;
1308 struct ia_vcc *ia_vcc;
1309
1310 pci_unmap_single(iadev->pci, iadev->rx_dle_q.write->sys_pkt_addr,
1311 len, PCI_DMA_FROMDEVICE);
1312 /* no VCC related housekeeping done as yet. lets see */
1313 vcc = ATM_SKB(skb)->vcc;
1314 if (!vcc) {
1315 printk("IA: null vcc\n");
1316 dev_kfree_skb_any(skb);
1317 goto INCR_DLE;
1318 }
1319 ia_vcc = INPH_IA_VCC(vcc);
1320 if (ia_vcc == NULL)
1321 {
1322 atomic_inc(&vcc->stats->rx_err);
chas williams - CONTRACTOR49f5ed42011-11-22 12:51:56 +00001323 atm_return(vcc, skb->truesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 dev_kfree_skb_any(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 goto INCR_DLE;
1326 }
1327 // get real pkt length pwang_test
1328 trailer = (struct cpcs_trailer*)((u_char *)skb->data +
1329 skb->len - sizeof(*trailer));
Wu Fengguangb67445fc2009-01-07 18:09:10 -08001330 length = swap_byte_order(trailer->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 if ((length > iadev->rx_buf_sz) || (length >
1332 (skb->len - sizeof(struct cpcs_trailer))))
1333 {
1334 atomic_inc(&vcc->stats->rx_err);
1335 IF_ERR(printk("rx_dle_intr: Bad AAL5 trailer %d (skb len %d)",
1336 length, skb->len);)
chas williams - CONTRACTOR49f5ed42011-11-22 12:51:56 +00001337 atm_return(vcc, skb->truesize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 dev_kfree_skb_any(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 goto INCR_DLE;
1340 }
1341 skb_trim(skb, length);
1342
1343 /* Display the packet */
1344 IF_RXPKT(printk("\nDmad Recvd data: len = %d \n", skb->len);
1345 xdump(skb->data, skb->len, "RX: ");
1346 printk("\n");)
1347
1348 IF_RX(printk("rx_dle_intr: skb push");)
1349 vcc->push(vcc,skb);
1350 atomic_inc(&vcc->stats->rx);
1351 iadev->rx_pkt_cnt++;
1352 }
1353INCR_DLE:
1354 if (++dle == iadev->rx_dle_q.end)
1355 dle = iadev->rx_dle_q.start;
1356 }
1357 iadev->rx_dle_q.read = dle;
1358
1359 /* if the interrupts are masked because there were no free desc available,
1360 unmask them now. */
1361 if (!iadev->rxing) {
1362 state = readl(iadev->reass_reg + STATE_REG) & 0xffff;
1363 if (!(state & FREEQ_EMPTY)) {
1364 state = readl(iadev->reass_reg + REASS_MASK_REG) & 0xffff;
1365 writel(state & ~(RX_FREEQ_EMPT |/* RX_EXCP_RCVD |*/ RX_PKT_RCVD),
1366 iadev->reass_reg+REASS_MASK_REG);
1367 iadev->rxing++;
1368 }
1369 }
1370}
1371
1372
1373static int open_rx(struct atm_vcc *vcc)
1374{
1375 IADEV *iadev;
1376 u_short __iomem *vc_table;
1377 u_short __iomem *reass_ptr;
1378 IF_EVENT(printk("iadev: open_rx %d.%d\n", vcc->vpi, vcc->vci);)
1379
1380 if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0;
1381 iadev = INPH_IA_DEV(vcc->dev);
1382 if (vcc->qos.rxtp.traffic_class == ATM_ABR) {
1383 if (iadev->phy_type & FE_25MBIT_PHY) {
1384 printk("IA: ABR not support\n");
1385 return -EINVAL;
1386 }
1387 }
1388 /* Make only this VCI in the vc table valid and let all
1389 others be invalid entries */
1390 vc_table = iadev->reass_ram+RX_VC_TABLE*iadev->memSize;
1391 vc_table += vcc->vci;
1392 /* mask the last 6 bits and OR it with 3 for 1K VCs */
1393
1394 *vc_table = vcc->vci << 6;
1395 /* Also keep a list of open rx vcs so that we can attach them with
1396 incoming PDUs later. */
1397 if ((vcc->qos.rxtp.traffic_class == ATM_ABR) ||
1398 (vcc->qos.txtp.traffic_class == ATM_ABR))
1399 {
1400 srv_cls_param_t srv_p;
1401 init_abr_vc(iadev, &srv_p);
1402 ia_open_abr_vc(iadev, &srv_p, vcc, 0);
1403 }
1404 else { /* for UBR later may need to add CBR logic */
1405 reass_ptr = iadev->reass_ram+REASS_TABLE*iadev->memSize;
1406 reass_ptr += vcc->vci;
1407 *reass_ptr = NO_AAL5_PKT;
1408 }
1409
1410 if (iadev->rx_open[vcc->vci])
1411 printk(KERN_CRIT DEV_LABEL "(itf %d): VCI %d already open\n",
1412 vcc->dev->number, vcc->vci);
1413 iadev->rx_open[vcc->vci] = vcc;
1414 return 0;
1415}
1416
1417static int rx_init(struct atm_dev *dev)
1418{
1419 IADEV *iadev;
1420 struct rx_buf_desc __iomem *buf_desc_ptr;
1421 unsigned long rx_pkt_start = 0;
1422 void *dle_addr;
1423 struct abr_vc_table *abr_vc_table;
1424 u16 *vc_table;
1425 u16 *reass_table;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 int i,j, vcsize_sel;
1427 u_short freeq_st_adr;
1428 u_short *freeq_start;
1429
1430 iadev = INPH_IA_DEV(dev);
1431 // spin_lock_init(&iadev->rx_lock);
1432
1433 /* Allocate 4k bytes - more aligned than needed (4k boundary) */
1434 dle_addr = pci_alloc_consistent(iadev->pci, DLE_TOTAL_SIZE,
1435 &iadev->rx_dle_dma);
1436 if (!dle_addr) {
1437 printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");
1438 goto err_out;
1439 }
Alan Cox97928f72008-06-17 16:21:18 -07001440 iadev->rx_dle_q.start = (struct dle *)dle_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 iadev->rx_dle_q.read = iadev->rx_dle_q.start;
1442 iadev->rx_dle_q.write = iadev->rx_dle_q.start;
Alan Cox97928f72008-06-17 16:21:18 -07001443 iadev->rx_dle_q.end = (struct dle*)((unsigned long)dle_addr+sizeof(struct dle)*DLE_ENTRIES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 /* the end of the dle q points to the entry after the last
1445 DLE that can be used. */
1446
1447 /* write the upper 20 bits of the start address to rx list address register */
Alan Cox97928f72008-06-17 16:21:18 -07001448 /* We know this is 32bit bus addressed so the following is safe */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 writel(iadev->rx_dle_dma & 0xfffff000,
1450 iadev->dma + IPHASE5575_RX_LIST_ADDR);
David Howells849e8ca2008-07-30 16:33:05 -07001451 IF_INIT(printk("Tx Dle list addr: 0x%p value: 0x%0x\n",
1452 iadev->dma+IPHASE5575_TX_LIST_ADDR,
françois romieu26c5c442011-09-30 00:37:43 +00001453 readl(iadev->dma + IPHASE5575_TX_LIST_ADDR));
David Howells849e8ca2008-07-30 16:33:05 -07001454 printk("Rx Dle list addr: 0x%p value: 0x%0x\n",
1455 iadev->dma+IPHASE5575_RX_LIST_ADDR,
françois romieu26c5c442011-09-30 00:37:43 +00001456 readl(iadev->dma + IPHASE5575_RX_LIST_ADDR));)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
1458 writew(0xffff, iadev->reass_reg+REASS_MASK_REG);
1459 writew(0, iadev->reass_reg+MODE_REG);
1460 writew(RESET_REASS, iadev->reass_reg+REASS_COMMAND_REG);
1461
1462 /* Receive side control memory map
1463 -------------------------------
1464
1465 Buffer descr 0x0000 (736 - 23K)
1466 VP Table 0x5c00 (256 - 512)
1467 Except q 0x5e00 (128 - 512)
1468 Free buffer q 0x6000 (1K - 2K)
1469 Packet comp q 0x6800 (1K - 2K)
1470 Reass Table 0x7000 (1K - 2K)
1471 VC Table 0x7800 (1K - 2K)
1472 ABR VC Table 0x8000 (1K - 32K)
1473 */
1474
1475 /* Base address for Buffer Descriptor Table */
1476 writew(RX_DESC_BASE >> 16, iadev->reass_reg+REASS_DESC_BASE);
1477 /* Set the buffer size register */
1478 writew(iadev->rx_buf_sz, iadev->reass_reg+BUF_SIZE);
1479
1480 /* Initialize each entry in the Buffer Descriptor Table */
1481 iadev->RX_DESC_BASE_ADDR = iadev->reass_ram+RX_DESC_BASE*iadev->memSize;
1482 buf_desc_ptr = iadev->RX_DESC_BASE_ADDR;
1483 memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
1484 buf_desc_ptr++;
1485 rx_pkt_start = iadev->rx_pkt_ram;
1486 for(i=1; i<=iadev->num_rx_desc; i++)
1487 {
1488 memset_io(buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
1489 buf_desc_ptr->buf_start_hi = rx_pkt_start >> 16;
1490 buf_desc_ptr->buf_start_lo = rx_pkt_start & 0x0000ffff;
1491 buf_desc_ptr++;
1492 rx_pkt_start += iadev->rx_buf_sz;
1493 }
David Howells849e8ca2008-07-30 16:33:05 -07001494 IF_INIT(printk("Rx Buffer desc ptr: 0x%p\n", buf_desc_ptr);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 i = FREE_BUF_DESC_Q*iadev->memSize;
1496 writew(i >> 16, iadev->reass_reg+REASS_QUEUE_BASE);
1497 writew(i, iadev->reass_reg+FREEQ_ST_ADR);
1498 writew(i+iadev->num_rx_desc*sizeof(u_short),
1499 iadev->reass_reg+FREEQ_ED_ADR);
1500 writew(i, iadev->reass_reg+FREEQ_RD_PTR);
1501 writew(i+iadev->num_rx_desc*sizeof(u_short),
1502 iadev->reass_reg+FREEQ_WR_PTR);
1503 /* Fill the FREEQ with all the free descriptors. */
1504 freeq_st_adr = readw(iadev->reass_reg+FREEQ_ST_ADR);
1505 freeq_start = (u_short *)(iadev->reass_ram+freeq_st_adr);
1506 for(i=1; i<=iadev->num_rx_desc; i++)
1507 {
1508 *freeq_start = (u_short)i;
1509 freeq_start++;
1510 }
David Howells849e8ca2008-07-30 16:33:05 -07001511 IF_INIT(printk("freeq_start: 0x%p\n", freeq_start);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 /* Packet Complete Queue */
1513 i = (PKT_COMP_Q * iadev->memSize) & 0xffff;
1514 writew(i, iadev->reass_reg+PCQ_ST_ADR);
1515 writew(i+iadev->num_vc*sizeof(u_short), iadev->reass_reg+PCQ_ED_ADR);
1516 writew(i, iadev->reass_reg+PCQ_RD_PTR);
1517 writew(i, iadev->reass_reg+PCQ_WR_PTR);
1518
1519 /* Exception Queue */
1520 i = (EXCEPTION_Q * iadev->memSize) & 0xffff;
1521 writew(i, iadev->reass_reg+EXCP_Q_ST_ADR);
1522 writew(i + NUM_RX_EXCP * sizeof(RX_ERROR_Q),
1523 iadev->reass_reg+EXCP_Q_ED_ADR);
1524 writew(i, iadev->reass_reg+EXCP_Q_RD_PTR);
1525 writew(i, iadev->reass_reg+EXCP_Q_WR_PTR);
1526
1527 /* Load local copy of FREEQ and PCQ ptrs */
1528 iadev->rfL.fdq_st = readw(iadev->reass_reg+FREEQ_ST_ADR) & 0xffff;
1529 iadev->rfL.fdq_ed = readw(iadev->reass_reg+FREEQ_ED_ADR) & 0xffff ;
1530 iadev->rfL.fdq_rd = readw(iadev->reass_reg+FREEQ_RD_PTR) & 0xffff;
1531 iadev->rfL.fdq_wr = readw(iadev->reass_reg+FREEQ_WR_PTR) & 0xffff;
1532 iadev->rfL.pcq_st = readw(iadev->reass_reg+PCQ_ST_ADR) & 0xffff;
1533 iadev->rfL.pcq_ed = readw(iadev->reass_reg+PCQ_ED_ADR) & 0xffff;
1534 iadev->rfL.pcq_rd = readw(iadev->reass_reg+PCQ_RD_PTR) & 0xffff;
1535 iadev->rfL.pcq_wr = readw(iadev->reass_reg+PCQ_WR_PTR) & 0xffff;
1536
1537 IF_INIT(printk("INIT:pcq_st:0x%x pcq_ed:0x%x pcq_rd:0x%x pcq_wr:0x%x",
1538 iadev->rfL.pcq_st, iadev->rfL.pcq_ed, iadev->rfL.pcq_rd,
1539 iadev->rfL.pcq_wr);)
1540 /* just for check - no VP TBL */
1541 /* VP Table */
1542 /* writew(0x0b80, iadev->reass_reg+VP_LKUP_BASE); */
1543 /* initialize VP Table for invalid VPIs
1544 - I guess we can write all 1s or 0x000f in the entire memory
1545 space or something similar.
1546 */
1547
1548 /* This seems to work and looks right to me too !!! */
1549 i = REASS_TABLE * iadev->memSize;
1550 writew((i >> 3), iadev->reass_reg+REASS_TABLE_BASE);
1551 /* initialize Reassembly table to I don't know what ???? */
1552 reass_table = (u16 *)(iadev->reass_ram+i);
1553 j = REASS_TABLE_SZ * iadev->memSize;
1554 for(i=0; i < j; i++)
1555 *reass_table++ = NO_AAL5_PKT;
1556 i = 8*1024;
1557 vcsize_sel = 0;
1558 while (i != iadev->num_vc) {
1559 i /= 2;
1560 vcsize_sel++;
1561 }
1562 i = RX_VC_TABLE * iadev->memSize;
1563 writew(((i>>3) & 0xfff8) | vcsize_sel, iadev->reass_reg+VC_LKUP_BASE);
1564 vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);
1565 j = RX_VC_TABLE_SZ * iadev->memSize;
1566 for(i = 0; i < j; i++)
1567 {
1568 /* shift the reassembly pointer by 3 + lower 3 bits of
1569 vc_lkup_base register (=3 for 1K VCs) and the last byte
1570 is those low 3 bits.
1571 Shall program this later.
1572 */
1573 *vc_table = (i << 6) | 15; /* for invalid VCI */
1574 vc_table++;
1575 }
1576 /* ABR VC table */
1577 i = ABR_VC_TABLE * iadev->memSize;
1578 writew(i >> 3, iadev->reass_reg+ABR_LKUP_BASE);
1579
1580 i = ABR_VC_TABLE * iadev->memSize;
1581 abr_vc_table = (struct abr_vc_table *)(iadev->reass_ram+i);
1582 j = REASS_TABLE_SZ * iadev->memSize;
1583 memset ((char*)abr_vc_table, 0, j * sizeof(*abr_vc_table));
1584 for(i = 0; i < j; i++) {
1585 abr_vc_table->rdf = 0x0003;
1586 abr_vc_table->air = 0x5eb1;
1587 abr_vc_table++;
1588 }
1589
1590 /* Initialize other registers */
1591
1592 /* VP Filter Register set for VC Reassembly only */
1593 writew(0xff00, iadev->reass_reg+VP_FILTER);
1594 writew(0, iadev->reass_reg+XTRA_RM_OFFSET);
1595 writew(0x1, iadev->reass_reg+PROTOCOL_ID);
1596
1597 /* Packet Timeout Count related Registers :
1598 Set packet timeout to occur in about 3 seconds
1599 Set Packet Aging Interval count register to overflow in about 4 us
1600 */
1601 writew(0xF6F8, iadev->reass_reg+PKT_TM_CNT );
Alan Cox97928f72008-06-17 16:21:18 -07001602
1603 i = (j >> 6) & 0xFF;
1604 j += 2 * (j - 1);
1605 i |= ((j << 2) & 0xFF00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 writew(i, iadev->reass_reg+TMOUT_RANGE);
Alan Cox97928f72008-06-17 16:21:18 -07001607
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 /* initiate the desc_tble */
1609 for(i=0; i<iadev->num_tx_desc;i++)
1610 iadev->desc_tbl[i].timestamp = 0;
1611
1612 /* to clear the interrupt status register - read it */
1613 readw(iadev->reass_reg+REASS_INTR_STATUS_REG);
1614
1615 /* Mask Register - clear it */
1616 writew(~(RX_FREEQ_EMPT|RX_PKT_RCVD), iadev->reass_reg+REASS_MASK_REG);
1617
1618 skb_queue_head_init(&iadev->rx_dma_q);
1619 iadev->rx_free_desc_qhead = NULL;
Mariusz Kozlowskif7141762007-08-10 15:26:18 -07001620
1621 iadev->rx_open = kzalloc(4 * iadev->num_vc, GFP_KERNEL);
1622 if (!iadev->rx_open) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n",
1624 dev->number);
1625 goto err_free_dle;
1626 }
Mariusz Kozlowskif7141762007-08-10 15:26:18 -07001627
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 iadev->rxing = 1;
1629 iadev->rx_pkt_cnt = 0;
1630 /* Mode Register */
1631 writew(R_ONLINE, iadev->reass_reg+MODE_REG);
1632 return 0;
1633
1634err_free_dle:
1635 pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->rx_dle_q.start,
1636 iadev->rx_dle_dma);
1637err_out:
1638 return -ENOMEM;
1639}
1640
1641
1642/*
1643 The memory map suggested in appendix A and the coding for it.
1644 Keeping it around just in case we change our mind later.
1645
1646 Buffer descr 0x0000 (128 - 4K)
1647 UBR sched 0x1000 (1K - 4K)
1648 UBR Wait q 0x2000 (1K - 4K)
1649 Commn queues 0x3000 Packet Ready, Trasmit comp(0x3100)
1650 (128 - 256) each
1651 extended VC 0x4000 (1K - 8K)
1652 ABR sched 0x6000 and ABR wait queue (1K - 2K) each
1653 CBR sched 0x7000 (as needed)
1654 VC table 0x8000 (1K - 32K)
1655*/
1656
1657static void tx_intr(struct atm_dev *dev)
1658{
1659 IADEV *iadev;
1660 unsigned short status;
1661 unsigned long flags;
1662
1663 iadev = INPH_IA_DEV(dev);
1664
1665 status = readl(iadev->seg_reg+SEG_INTR_STATUS_REG);
1666 if (status & TRANSMIT_DONE){
1667
1668 IF_EVENT(printk("Tansmit Done Intr logic run\n");)
1669 spin_lock_irqsave(&iadev->tx_lock, flags);
1670 ia_tx_poll(iadev);
1671 spin_unlock_irqrestore(&iadev->tx_lock, flags);
1672 writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
1673 if (iadev->close_pending)
1674 wake_up(&iadev->close_wait);
1675 }
1676 if (status & TCQ_NOT_EMPTY)
1677 {
1678 IF_EVENT(printk("TCQ_NOT_EMPTY int received\n");)
1679 }
1680}
1681
1682static void tx_dle_intr(struct atm_dev *dev)
1683{
1684 IADEV *iadev;
1685 struct dle *dle, *cur_dle;
1686 struct sk_buff *skb;
1687 struct atm_vcc *vcc;
1688 struct ia_vcc *iavcc;
1689 u_int dle_lp;
1690 unsigned long flags;
1691
1692 iadev = INPH_IA_DEV(dev);
1693 spin_lock_irqsave(&iadev->tx_lock, flags);
1694 dle = iadev->tx_dle_q.read;
1695 dle_lp = readl(iadev->dma+IPHASE5575_TX_LIST_ADDR) &
1696 (sizeof(struct dle)*DLE_ENTRIES - 1);
1697 cur_dle = (struct dle*)(iadev->tx_dle_q.start + (dle_lp >> 4));
1698 while (dle != cur_dle)
1699 {
1700 /* free the DMAed skb */
1701 skb = skb_dequeue(&iadev->tx_dma_q);
1702 if (!skb) break;
1703
1704 /* Revenge of the 2 dle (skb + trailer) used in ia_pkt_tx() */
1705 if (!((dle - iadev->tx_dle_q.start)%(2*sizeof(struct dle)))) {
1706 pci_unmap_single(iadev->pci, dle->sys_pkt_addr, skb->len,
1707 PCI_DMA_TODEVICE);
1708 }
1709 vcc = ATM_SKB(skb)->vcc;
1710 if (!vcc) {
1711 printk("tx_dle_intr: vcc is null\n");
1712 spin_unlock_irqrestore(&iadev->tx_lock, flags);
1713 dev_kfree_skb_any(skb);
1714
1715 return;
1716 }
1717 iavcc = INPH_IA_VCC(vcc);
1718 if (!iavcc) {
1719 printk("tx_dle_intr: iavcc is null\n");
1720 spin_unlock_irqrestore(&iadev->tx_lock, flags);
1721 dev_kfree_skb_any(skb);
1722 return;
1723 }
1724 if (vcc->qos.txtp.pcr >= iadev->rate_limit) {
1725 if ((vcc->pop) && (skb->len != 0))
1726 {
1727 vcc->pop(vcc, skb);
1728 }
1729 else {
1730 dev_kfree_skb_any(skb);
1731 }
1732 }
1733 else { /* Hold the rate-limited skb for flow control */
1734 IA_SKB_STATE(skb) |= IA_DLED;
1735 skb_queue_tail(&iavcc->txing_skb, skb);
1736 }
David Howells849e8ca2008-07-30 16:33:05 -07001737 IF_EVENT(printk("tx_dle_intr: enque skb = 0x%p \n", skb);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 if (++dle == iadev->tx_dle_q.end)
1739 dle = iadev->tx_dle_q.start;
1740 }
1741 iadev->tx_dle_q.read = dle;
1742 spin_unlock_irqrestore(&iadev->tx_lock, flags);
1743}
1744
1745static int open_tx(struct atm_vcc *vcc)
1746{
1747 struct ia_vcc *ia_vcc;
1748 IADEV *iadev;
1749 struct main_vc *vc;
1750 struct ext_vc *evc;
1751 int ret;
1752 IF_EVENT(printk("iadev: open_tx entered vcc->vci = %d\n", vcc->vci);)
1753 if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0;
1754 iadev = INPH_IA_DEV(vcc->dev);
1755
1756 if (iadev->phy_type & FE_25MBIT_PHY) {
1757 if (vcc->qos.txtp.traffic_class == ATM_ABR) {
1758 printk("IA: ABR not support\n");
1759 return -EINVAL;
1760 }
1761 if (vcc->qos.txtp.traffic_class == ATM_CBR) {
1762 printk("IA: CBR not support\n");
1763 return -EINVAL;
1764 }
1765 }
1766 ia_vcc = INPH_IA_VCC(vcc);
1767 memset((caddr_t)ia_vcc, 0, sizeof(*ia_vcc));
1768 if (vcc->qos.txtp.max_sdu >
1769 (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){
1770 printk("IA: SDU size over (%d) the configured SDU size %d\n",
1771 vcc->qos.txtp.max_sdu,iadev->tx_buf_sz);
1772 vcc->dev_data = NULL;
1773 kfree(ia_vcc);
1774 return -EINVAL;
1775 }
1776 ia_vcc->vc_desc_cnt = 0;
1777 ia_vcc->txing = 1;
1778
1779 /* find pcr */
1780 if (vcc->qos.txtp.max_pcr == ATM_MAX_PCR)
1781 vcc->qos.txtp.pcr = iadev->LineRate;
1782 else if ((vcc->qos.txtp.max_pcr == 0)&&( vcc->qos.txtp.pcr <= 0))
1783 vcc->qos.txtp.pcr = iadev->LineRate;
1784 else if ((vcc->qos.txtp.max_pcr > vcc->qos.txtp.pcr) && (vcc->qos.txtp.max_pcr> 0))
1785 vcc->qos.txtp.pcr = vcc->qos.txtp.max_pcr;
1786 if (vcc->qos.txtp.pcr > iadev->LineRate)
1787 vcc->qos.txtp.pcr = iadev->LineRate;
1788 ia_vcc->pcr = vcc->qos.txtp.pcr;
1789
1790 if (ia_vcc->pcr > (iadev->LineRate / 6) ) ia_vcc->ltimeout = HZ / 10;
1791 else if (ia_vcc->pcr > (iadev->LineRate / 130)) ia_vcc->ltimeout = HZ;
1792 else if (ia_vcc->pcr <= 170) ia_vcc->ltimeout = 16 * HZ;
1793 else ia_vcc->ltimeout = 2700 * HZ / ia_vcc->pcr;
1794 if (ia_vcc->pcr < iadev->rate_limit)
1795 skb_queue_head_init (&ia_vcc->txing_skb);
1796 if (ia_vcc->pcr < iadev->rate_limit) {
1797 struct sock *sk = sk_atm(vcc);
1798
1799 if (vcc->qos.txtp.max_sdu != 0) {
1800 if (ia_vcc->pcr > 60000)
1801 sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5;
1802 else if (ia_vcc->pcr > 2000)
1803 sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4;
1804 else
1805 sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3;
1806 }
1807 else
1808 sk->sk_sndbuf = 24576;
1809 }
1810
1811 vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;
1812 evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR;
1813 vc += vcc->vci;
1814 evc += vcc->vci;
1815 memset((caddr_t)vc, 0, sizeof(*vc));
1816 memset((caddr_t)evc, 0, sizeof(*evc));
1817
1818 /* store the most significant 4 bits of vci as the last 4 bits
1819 of first part of atm header.
1820 store the last 12 bits of vci as first 12 bits of the second
1821 part of the atm header.
1822 */
1823 evc->atm_hdr1 = (vcc->vci >> 12) & 0x000f;
1824 evc->atm_hdr2 = (vcc->vci & 0x0fff) << 4;
1825
1826 /* check the following for different traffic classes */
1827 if (vcc->qos.txtp.traffic_class == ATM_UBR)
1828 {
1829 vc->type = UBR;
1830 vc->status = CRC_APPEND;
1831 vc->acr = cellrate_to_float(iadev->LineRate);
1832 if (vcc->qos.txtp.pcr > 0)
1833 vc->acr = cellrate_to_float(vcc->qos.txtp.pcr);
1834 IF_UBR(printk("UBR: txtp.pcr = 0x%x f_rate = 0x%x\n",
1835 vcc->qos.txtp.max_pcr,vc->acr);)
1836 }
1837 else if (vcc->qos.txtp.traffic_class == ATM_ABR)
1838 { srv_cls_param_t srv_p;
1839 IF_ABR(printk("Tx ABR VCC\n");)
1840 init_abr_vc(iadev, &srv_p);
1841 if (vcc->qos.txtp.pcr > 0)
1842 srv_p.pcr = vcc->qos.txtp.pcr;
1843 if (vcc->qos.txtp.min_pcr > 0) {
1844 int tmpsum = iadev->sum_mcr+iadev->sum_cbr+vcc->qos.txtp.min_pcr;
1845 if (tmpsum > iadev->LineRate)
1846 return -EBUSY;
1847 srv_p.mcr = vcc->qos.txtp.min_pcr;
1848 iadev->sum_mcr += vcc->qos.txtp.min_pcr;
1849 }
1850 else srv_p.mcr = 0;
1851 if (vcc->qos.txtp.icr)
1852 srv_p.icr = vcc->qos.txtp.icr;
1853 if (vcc->qos.txtp.tbe)
1854 srv_p.tbe = vcc->qos.txtp.tbe;
1855 if (vcc->qos.txtp.frtt)
1856 srv_p.frtt = vcc->qos.txtp.frtt;
1857 if (vcc->qos.txtp.rif)
1858 srv_p.rif = vcc->qos.txtp.rif;
1859 if (vcc->qos.txtp.rdf)
1860 srv_p.rdf = vcc->qos.txtp.rdf;
1861 if (vcc->qos.txtp.nrm_pres)
1862 srv_p.nrm = vcc->qos.txtp.nrm;
1863 if (vcc->qos.txtp.trm_pres)
1864 srv_p.trm = vcc->qos.txtp.trm;
1865 if (vcc->qos.txtp.adtf_pres)
1866 srv_p.adtf = vcc->qos.txtp.adtf;
1867 if (vcc->qos.txtp.cdf_pres)
1868 srv_p.cdf = vcc->qos.txtp.cdf;
1869 if (srv_p.icr > srv_p.pcr)
1870 srv_p.icr = srv_p.pcr;
1871 IF_ABR(printk("ABR:vcc->qos.txtp.max_pcr = %d mcr = %d\n",
1872 srv_p.pcr, srv_p.mcr);)
1873 ia_open_abr_vc(iadev, &srv_p, vcc, 1);
1874 } else if (vcc->qos.txtp.traffic_class == ATM_CBR) {
1875 if (iadev->phy_type & FE_25MBIT_PHY) {
1876 printk("IA: CBR not support\n");
1877 return -EINVAL;
1878 }
1879 if (vcc->qos.txtp.max_pcr > iadev->LineRate) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001880 IF_CBR(printk("PCR is not available\n");)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 return -1;
1882 }
1883 vc->type = CBR;
1884 vc->status = CRC_APPEND;
1885 if ((ret = ia_cbr_setup (iadev, vcc)) < 0) {
1886 return ret;
1887 }
1888 }
1889 else
1890 printk("iadev: Non UBR, ABR and CBR traffic not supportedn");
1891
1892 iadev->testTable[vcc->vci]->vc_status |= VC_ACTIVE;
1893 IF_EVENT(printk("ia open_tx returning \n");)
1894 return 0;
1895}
1896
1897
1898static int tx_init(struct atm_dev *dev)
1899{
1900 IADEV *iadev;
1901 struct tx_buf_desc *buf_desc_ptr;
1902 unsigned int tx_pkt_start;
1903 void *dle_addr;
1904 int i;
1905 u_short tcq_st_adr;
1906 u_short *tcq_start;
1907 u_short prq_st_adr;
1908 u_short *prq_start;
1909 struct main_vc *vc;
1910 struct ext_vc *evc;
1911 u_short tmp16;
1912 u32 vcsize_sel;
1913
1914 iadev = INPH_IA_DEV(dev);
1915 spin_lock_init(&iadev->tx_lock);
1916
1917 IF_INIT(printk("Tx MASK REG: 0x%0x\n",
1918 readw(iadev->seg_reg+SEG_MASK_REG));)
1919
1920 /* Allocate 4k (boundary aligned) bytes */
1921 dle_addr = pci_alloc_consistent(iadev->pci, DLE_TOTAL_SIZE,
1922 &iadev->tx_dle_dma);
1923 if (!dle_addr) {
1924 printk(KERN_ERR DEV_LABEL "can't allocate DLEs\n");
1925 goto err_out;
1926 }
1927 iadev->tx_dle_q.start = (struct dle*)dle_addr;
1928 iadev->tx_dle_q.read = iadev->tx_dle_q.start;
1929 iadev->tx_dle_q.write = iadev->tx_dle_q.start;
Alan Cox97928f72008-06-17 16:21:18 -07001930 iadev->tx_dle_q.end = (struct dle*)((unsigned long)dle_addr+sizeof(struct dle)*DLE_ENTRIES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931
1932 /* write the upper 20 bits of the start address to tx list address register */
1933 writel(iadev->tx_dle_dma & 0xfffff000,
1934 iadev->dma + IPHASE5575_TX_LIST_ADDR);
1935 writew(0xffff, iadev->seg_reg+SEG_MASK_REG);
1936 writew(0, iadev->seg_reg+MODE_REG_0);
1937 writew(RESET_SEG, iadev->seg_reg+SEG_COMMAND_REG);
1938 iadev->MAIN_VC_TABLE_ADDR = iadev->seg_ram+MAIN_VC_TABLE*iadev->memSize;
1939 iadev->EXT_VC_TABLE_ADDR = iadev->seg_ram+EXT_VC_TABLE*iadev->memSize;
1940 iadev->ABR_SCHED_TABLE_ADDR=iadev->seg_ram+ABR_SCHED_TABLE*iadev->memSize;
1941
1942 /*
1943 Transmit side control memory map
1944 --------------------------------
1945 Buffer descr 0x0000 (128 - 4K)
1946 Commn queues 0x1000 Transmit comp, Packet ready(0x1400)
1947 (512 - 1K) each
1948 TCQ - 4K, PRQ - 5K
1949 CBR Table 0x1800 (as needed) - 6K
1950 UBR Table 0x3000 (1K - 4K) - 12K
1951 UBR Wait queue 0x4000 (1K - 4K) - 16K
1952 ABR sched 0x5000 and ABR wait queue (1K - 2K) each
1953 ABR Tbl - 20K, ABR Wq - 22K
1954 extended VC 0x6000 (1K - 8K) - 24K
1955 VC Table 0x8000 (1K - 32K) - 32K
1956
1957 Between 0x2000 (8K) and 0x3000 (12K) there is 4K space left for VBR Tbl
1958 and Wait q, which can be allotted later.
1959 */
1960
1961 /* Buffer Descriptor Table Base address */
1962 writew(TX_DESC_BASE, iadev->seg_reg+SEG_DESC_BASE);
1963
1964 /* initialize each entry in the buffer descriptor table */
1965 buf_desc_ptr =(struct tx_buf_desc *)(iadev->seg_ram+TX_DESC_BASE);
1966 memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
1967 buf_desc_ptr++;
1968 tx_pkt_start = TX_PACKET_RAM;
1969 for(i=1; i<=iadev->num_tx_desc; i++)
1970 {
1971 memset((caddr_t)buf_desc_ptr, 0, sizeof(*buf_desc_ptr));
1972 buf_desc_ptr->desc_mode = AAL5;
1973 buf_desc_ptr->buf_start_hi = tx_pkt_start >> 16;
1974 buf_desc_ptr->buf_start_lo = tx_pkt_start & 0x0000ffff;
1975 buf_desc_ptr++;
1976 tx_pkt_start += iadev->tx_buf_sz;
1977 }
1978 iadev->tx_buf = kmalloc(iadev->num_tx_desc*sizeof(struct cpcs_trailer_desc), GFP_KERNEL);
1979 if (!iadev->tx_buf) {
1980 printk(KERN_ERR DEV_LABEL " couldn't get mem\n");
1981 goto err_free_dle;
1982 }
1983 for (i= 0; i< iadev->num_tx_desc; i++)
1984 {
1985 struct cpcs_trailer *cpcs;
1986
1987 cpcs = kmalloc(sizeof(*cpcs), GFP_KERNEL|GFP_DMA);
1988 if(!cpcs) {
1989 printk(KERN_ERR DEV_LABEL " couldn't get freepage\n");
1990 goto err_free_tx_bufs;
1991 }
1992 iadev->tx_buf[i].cpcs = cpcs;
1993 iadev->tx_buf[i].dma_addr = pci_map_single(iadev->pci,
1994 cpcs, sizeof(*cpcs), PCI_DMA_TODEVICE);
1995 }
1996 iadev->desc_tbl = kmalloc(iadev->num_tx_desc *
1997 sizeof(struct desc_tbl_t), GFP_KERNEL);
1998 if (!iadev->desc_tbl) {
1999 printk(KERN_ERR DEV_LABEL " couldn't get mem\n");
2000 goto err_free_all_tx_bufs;
2001 }
2002
2003 /* Communication Queues base address */
2004 i = TX_COMP_Q * iadev->memSize;
2005 writew(i >> 16, iadev->seg_reg+SEG_QUEUE_BASE);
2006
2007 /* Transmit Complete Queue */
2008 writew(i, iadev->seg_reg+TCQ_ST_ADR);
2009 writew(i, iadev->seg_reg+TCQ_RD_PTR);
2010 writew(i+iadev->num_tx_desc*sizeof(u_short),iadev->seg_reg+TCQ_WR_PTR);
2011 iadev->host_tcq_wr = i + iadev->num_tx_desc*sizeof(u_short);
2012 writew(i+2 * iadev->num_tx_desc * sizeof(u_short),
2013 iadev->seg_reg+TCQ_ED_ADR);
2014 /* Fill the TCQ with all the free descriptors. */
2015 tcq_st_adr = readw(iadev->seg_reg+TCQ_ST_ADR);
2016 tcq_start = (u_short *)(iadev->seg_ram+tcq_st_adr);
2017 for(i=1; i<=iadev->num_tx_desc; i++)
2018 {
2019 *tcq_start = (u_short)i;
2020 tcq_start++;
2021 }
2022
2023 /* Packet Ready Queue */
2024 i = PKT_RDY_Q * iadev->memSize;
2025 writew(i, iadev->seg_reg+PRQ_ST_ADR);
2026 writew(i+2 * iadev->num_tx_desc * sizeof(u_short),
2027 iadev->seg_reg+PRQ_ED_ADR);
2028 writew(i, iadev->seg_reg+PRQ_RD_PTR);
2029 writew(i, iadev->seg_reg+PRQ_WR_PTR);
2030
2031 /* Load local copy of PRQ and TCQ ptrs */
2032 iadev->ffL.prq_st = readw(iadev->seg_reg+PRQ_ST_ADR) & 0xffff;
2033 iadev->ffL.prq_ed = readw(iadev->seg_reg+PRQ_ED_ADR) & 0xffff;
2034 iadev->ffL.prq_wr = readw(iadev->seg_reg+PRQ_WR_PTR) & 0xffff;
2035
2036 iadev->ffL.tcq_st = readw(iadev->seg_reg+TCQ_ST_ADR) & 0xffff;
2037 iadev->ffL.tcq_ed = readw(iadev->seg_reg+TCQ_ED_ADR) & 0xffff;
2038 iadev->ffL.tcq_rd = readw(iadev->seg_reg+TCQ_RD_PTR) & 0xffff;
2039
2040 /* Just for safety initializing the queue to have desc 1 always */
2041 /* Fill the PRQ with all the free descriptors. */
2042 prq_st_adr = readw(iadev->seg_reg+PRQ_ST_ADR);
2043 prq_start = (u_short *)(iadev->seg_ram+prq_st_adr);
2044 for(i=1; i<=iadev->num_tx_desc; i++)
2045 {
2046 *prq_start = (u_short)0; /* desc 1 in all entries */
2047 prq_start++;
2048 }
2049 /* CBR Table */
2050 IF_INIT(printk("Start CBR Init\n");)
2051#if 1 /* for 1K VC board, CBR_PTR_BASE is 0 */
2052 writew(0,iadev->seg_reg+CBR_PTR_BASE);
2053#else /* Charlie's logic is wrong ? */
2054 tmp16 = (iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize)>>17;
2055 IF_INIT(printk("cbr_ptr_base = 0x%x ", tmp16);)
2056 writew(tmp16,iadev->seg_reg+CBR_PTR_BASE);
2057#endif
2058
2059 IF_INIT(printk("value in register = 0x%x\n",
2060 readw(iadev->seg_reg+CBR_PTR_BASE));)
2061 tmp16 = (CBR_SCHED_TABLE*iadev->memSize) >> 1;
2062 writew(tmp16, iadev->seg_reg+CBR_TAB_BEG);
2063 IF_INIT(printk("cbr_tab_beg = 0x%x in reg = 0x%x \n", tmp16,
2064 readw(iadev->seg_reg+CBR_TAB_BEG));)
2065 writew(tmp16, iadev->seg_reg+CBR_TAB_END+1); // CBR_PTR;
2066 tmp16 = (CBR_SCHED_TABLE*iadev->memSize + iadev->num_vc*6 - 2) >> 1;
2067 writew(tmp16, iadev->seg_reg+CBR_TAB_END);
David Howells849e8ca2008-07-30 16:33:05 -07002068 IF_INIT(printk("iadev->seg_reg = 0x%p CBR_PTR_BASE = 0x%x\n",
2069 iadev->seg_reg, readw(iadev->seg_reg+CBR_PTR_BASE));)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070 IF_INIT(printk("CBR_TAB_BEG = 0x%x, CBR_TAB_END = 0x%x, CBR_PTR = 0x%x\n",
2071 readw(iadev->seg_reg+CBR_TAB_BEG), readw(iadev->seg_reg+CBR_TAB_END),
2072 readw(iadev->seg_reg+CBR_TAB_END+1));)
2073
2074 /* Initialize the CBR Schedualing Table */
2075 memset_io(iadev->seg_ram+CBR_SCHED_TABLE*iadev->memSize,
2076 0, iadev->num_vc*6);
2077 iadev->CbrRemEntries = iadev->CbrTotEntries = iadev->num_vc*3;
2078 iadev->CbrEntryPt = 0;
2079 iadev->Granularity = MAX_ATM_155 / iadev->CbrTotEntries;
2080 iadev->NumEnabledCBR = 0;
2081
2082 /* UBR scheduling Table and wait queue */
2083 /* initialize all bytes of UBR scheduler table and wait queue to 0
2084 - SCHEDSZ is 1K (# of entries).
2085 - UBR Table size is 4K
2086 - UBR wait queue is 4K
2087 since the table and wait queues are contiguous, all the bytes
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04002088 can be initialized by one memeset.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 */
2090
2091 vcsize_sel = 0;
2092 i = 8*1024;
2093 while (i != iadev->num_vc) {
2094 i /= 2;
2095 vcsize_sel++;
2096 }
2097
2098 i = MAIN_VC_TABLE * iadev->memSize;
2099 writew(vcsize_sel | ((i >> 8) & 0xfff8),iadev->seg_reg+VCT_BASE);
2100 i = EXT_VC_TABLE * iadev->memSize;
2101 writew((i >> 8) & 0xfffe, iadev->seg_reg+VCTE_BASE);
2102 i = UBR_SCHED_TABLE * iadev->memSize;
2103 writew((i & 0xffff) >> 11, iadev->seg_reg+UBR_SBPTR_BASE);
2104 i = UBR_WAIT_Q * iadev->memSize;
2105 writew((i >> 7) & 0xffff, iadev->seg_reg+UBRWQ_BASE);
2106 memset((caddr_t)(iadev->seg_ram+UBR_SCHED_TABLE*iadev->memSize),
2107 0, iadev->num_vc*8);
2108 /* ABR scheduling Table(0x5000-0x57ff) and wait queue(0x5800-0x5fff)*/
2109 /* initialize all bytes of ABR scheduler table and wait queue to 0
2110 - SCHEDSZ is 1K (# of entries).
2111 - ABR Table size is 2K
2112 - ABR wait queue is 2K
2113 since the table and wait queues are contiguous, all the bytes
Uwe Kleine-Königb5950762010-11-01 15:38:34 -04002114 can be initialized by one memeset.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 */
2116 i = ABR_SCHED_TABLE * iadev->memSize;
2117 writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE);
2118 i = ABR_WAIT_Q * iadev->memSize;
2119 writew((i >> 7) & 0xffff, iadev->seg_reg+ABRWQ_BASE);
2120
2121 i = ABR_SCHED_TABLE*iadev->memSize;
2122 memset((caddr_t)(iadev->seg_ram+i), 0, iadev->num_vc*4);
2123 vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;
2124 evc = (struct ext_vc *)iadev->EXT_VC_TABLE_ADDR;
2125 iadev->testTable = kmalloc(sizeof(long)*iadev->num_vc, GFP_KERNEL);
2126 if (!iadev->testTable) {
2127 printk("Get freepage failed\n");
2128 goto err_free_desc_tbl;
2129 }
2130 for(i=0; i<iadev->num_vc; i++)
2131 {
2132 memset((caddr_t)vc, 0, sizeof(*vc));
2133 memset((caddr_t)evc, 0, sizeof(*evc));
2134 iadev->testTable[i] = kmalloc(sizeof(struct testTable_t),
2135 GFP_KERNEL);
2136 if (!iadev->testTable[i])
2137 goto err_free_test_tables;
2138 iadev->testTable[i]->lastTime = 0;
2139 iadev->testTable[i]->fract = 0;
2140 iadev->testTable[i]->vc_status = VC_UBR;
2141 vc++;
2142 evc++;
2143 }
2144
2145 /* Other Initialization */
2146
2147 /* Max Rate Register */
2148 if (iadev->phy_type & FE_25MBIT_PHY) {
2149 writew(RATE25, iadev->seg_reg+MAXRATE);
2150 writew((UBR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);
2151 }
2152 else {
2153 writew(cellrate_to_float(iadev->LineRate),iadev->seg_reg+MAXRATE);
2154 writew((UBR_EN | ABR_EN | (0x23 << 2)), iadev->seg_reg+STPARMS);
2155 }
2156 /* Set Idle Header Reigisters to be sure */
2157 writew(0, iadev->seg_reg+IDLEHEADHI);
2158 writew(0, iadev->seg_reg+IDLEHEADLO);
2159
2160 /* Program ABR UBR Priority Register as PRI_ABR_UBR_EQUAL */
2161 writew(0xaa00, iadev->seg_reg+ABRUBR_ARB);
2162
2163 iadev->close_pending = 0;
2164 init_waitqueue_head(&iadev->close_wait);
2165 init_waitqueue_head(&iadev->timeout_wait);
2166 skb_queue_head_init(&iadev->tx_dma_q);
2167 ia_init_rtn_q(&iadev->tx_return_q);
2168
2169 /* RM Cell Protocol ID and Message Type */
2170 writew(RM_TYPE_4_0, iadev->seg_reg+RM_TYPE);
2171 skb_queue_head_init (&iadev->tx_backlog);
2172
2173 /* Mode Register 1 */
2174 writew(MODE_REG_1_VAL, iadev->seg_reg+MODE_REG_1);
2175
2176 /* Mode Register 0 */
2177 writew(T_ONLINE, iadev->seg_reg+MODE_REG_0);
2178
2179 /* Interrupt Status Register - read to clear */
2180 readw(iadev->seg_reg+SEG_INTR_STATUS_REG);
2181
2182 /* Interrupt Mask Reg- don't mask TCQ_NOT_EMPTY interrupt generation */
2183 writew(~(TRANSMIT_DONE | TCQ_NOT_EMPTY), iadev->seg_reg+SEG_MASK_REG);
2184 writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
2185 iadev->tx_pkt_cnt = 0;
2186 iadev->rate_limit = iadev->LineRate / 3;
2187
2188 return 0;
2189
2190err_free_test_tables:
2191 while (--i >= 0)
2192 kfree(iadev->testTable[i]);
2193 kfree(iadev->testTable);
2194err_free_desc_tbl:
2195 kfree(iadev->desc_tbl);
2196err_free_all_tx_bufs:
2197 i = iadev->num_tx_desc;
2198err_free_tx_bufs:
2199 while (--i >= 0) {
2200 struct cpcs_trailer_desc *desc = iadev->tx_buf + i;
2201
2202 pci_unmap_single(iadev->pci, desc->dma_addr,
2203 sizeof(*desc->cpcs), PCI_DMA_TODEVICE);
2204 kfree(desc->cpcs);
2205 }
2206 kfree(iadev->tx_buf);
2207err_free_dle:
2208 pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->tx_dle_q.start,
2209 iadev->tx_dle_dma);
2210err_out:
2211 return -ENOMEM;
2212}
2213
David Howells7d12e782006-10-05 14:55:46 +01002214static irqreturn_t ia_int(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215{
2216 struct atm_dev *dev;
2217 IADEV *iadev;
2218 unsigned int status;
2219 int handled = 0;
2220
2221 dev = dev_id;
2222 iadev = INPH_IA_DEV(dev);
2223 while( (status = readl(iadev->reg+IPHASE5575_BUS_STATUS_REG) & 0x7f))
2224 {
2225 handled = 1;
2226 IF_EVENT(printk("ia_int: status = 0x%x\n", status);)
2227 if (status & STAT_REASSINT)
2228 {
2229 /* do something */
2230 IF_EVENT(printk("REASSINT Bus status reg: %08x\n", status);)
2231 rx_intr(dev);
2232 }
2233 if (status & STAT_DLERINT)
2234 {
2235 /* Clear this bit by writing a 1 to it. */
françois romieu26c5c442011-09-30 00:37:43 +00002236 writel(STAT_DLERINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 rx_dle_intr(dev);
2238 }
2239 if (status & STAT_SEGINT)
2240 {
2241 /* do something */
2242 IF_EVENT(printk("IA: tx_intr \n");)
2243 tx_intr(dev);
2244 }
2245 if (status & STAT_DLETINT)
2246 {
françois romieu26c5c442011-09-30 00:37:43 +00002247 writel(STAT_DLETINT, iadev->reg + IPHASE5575_BUS_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 tx_dle_intr(dev);
2249 }
2250 if (status & (STAT_FEINT | STAT_ERRINT | STAT_MARKINT))
2251 {
2252 if (status & STAT_FEINT)
françois romieu26c5c442011-09-30 00:37:43 +00002253 ia_frontend_intr(iadev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 }
2255 }
2256 return IRQ_RETVAL(handled);
2257}
2258
2259
2260
2261/*----------------------------- entries --------------------------------*/
2262static int get_esi(struct atm_dev *dev)
2263{
2264 IADEV *iadev;
2265 int i;
2266 u32 mac1;
2267 u16 mac2;
2268
2269 iadev = INPH_IA_DEV(dev);
2270 mac1 = cpu_to_be32(le32_to_cpu(readl(
2271 iadev->reg+IPHASE5575_MAC1)));
2272 mac2 = cpu_to_be16(le16_to_cpu(readl(iadev->reg+IPHASE5575_MAC2)));
2273 IF_INIT(printk("ESI: 0x%08x%04x\n", mac1, mac2);)
2274 for (i=0; i<MAC1_LEN; i++)
2275 dev->esi[i] = mac1 >>(8*(MAC1_LEN-1-i));
2276
2277 for (i=0; i<MAC2_LEN; i++)
2278 dev->esi[i+MAC1_LEN] = mac2 >>(8*(MAC2_LEN - 1 -i));
2279 return 0;
2280}
2281
2282static int reset_sar(struct atm_dev *dev)
2283{
2284 IADEV *iadev;
2285 int i, error = 1;
2286 unsigned int pci[64];
2287
2288 iadev = INPH_IA_DEV(dev);
2289 for(i=0; i<64; i++)
2290 if ((error = pci_read_config_dword(iadev->pci,
2291 i*4, &pci[i])) != PCIBIOS_SUCCESSFUL)
2292 return error;
2293 writel(0, iadev->reg+IPHASE5575_EXT_RESET);
2294 for(i=0; i<64; i++)
2295 if ((error = pci_write_config_dword(iadev->pci,
2296 i*4, pci[i])) != PCIBIOS_SUCCESSFUL)
2297 return error;
2298 udelay(5);
2299 return 0;
2300}
2301
2302
Chas Williams249c14b2006-06-29 12:35:32 -07002303static int __devinit ia_init(struct atm_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304{
2305 IADEV *iadev;
2306 unsigned long real_base;
2307 void __iomem *base;
2308 unsigned short command;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 int error, i;
2310
2311 /* The device has been identified and registered. Now we read
2312 necessary configuration info like memory base address,
2313 interrupt number etc */
2314
2315 IF_INIT(printk(">ia_init\n");)
2316 dev->ci_range.vpi_bits = 0;
2317 dev->ci_range.vci_bits = NR_VCI_LD;
2318
2319 iadev = INPH_IA_DEV(dev);
2320 real_base = pci_resource_start (iadev->pci, 0);
2321 iadev->irq = iadev->pci->irq;
2322
Auke Kok44c10132007-06-08 15:46:36 -07002323 error = pci_read_config_word(iadev->pci, PCI_COMMAND, &command);
2324 if (error) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%x\n",
2326 dev->number,error);
2327 return -EINVAL;
2328 }
2329 IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n",
Auke Kok44c10132007-06-08 15:46:36 -07002330 dev->number, iadev->pci->revision, real_base, iadev->irq);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
2332 /* find mapping size of board */
2333
2334 iadev->pci_map_size = pci_resource_len(iadev->pci, 0);
2335
2336 if (iadev->pci_map_size == 0x100000){
2337 iadev->num_vc = 4096;
2338 dev->ci_range.vci_bits = NR_VCI_4K_LD;
2339 iadev->memSize = 4;
2340 }
2341 else if (iadev->pci_map_size == 0x40000) {
2342 iadev->num_vc = 1024;
2343 iadev->memSize = 1;
2344 }
2345 else {
2346 printk("Unknown pci_map_size = 0x%x\n", iadev->pci_map_size);
2347 return -EINVAL;
2348 }
2349 IF_INIT(printk (DEV_LABEL "map size: %i\n", iadev->pci_map_size);)
2350
2351 /* enable bus mastering */
2352 pci_set_master(iadev->pci);
2353
2354 /*
2355 * Delay at least 1us before doing any mem accesses (how 'bout 10?)
2356 */
2357 udelay(10);
2358
2359 /* mapping the physical address to a virtual address in address space */
2360 base = ioremap(real_base,iadev->pci_map_size); /* ioremap is not resolved ??? */
2361
2362 if (!base)
2363 {
2364 printk(DEV_LABEL " (itf %d): can't set up page mapping\n",
2365 dev->number);
2366 return error;
2367 }
2368 IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n",
Auke Kok44c10132007-06-08 15:46:36 -07002369 dev->number, iadev->pci->revision, base, iadev->irq);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
2371 /* filling the iphase dev structure */
2372 iadev->mem = iadev->pci_map_size /2;
2373 iadev->real_base = real_base;
2374 iadev->base = base;
2375
2376 /* Bus Interface Control Registers */
2377 iadev->reg = base + REG_BASE;
2378 /* Segmentation Control Registers */
2379 iadev->seg_reg = base + SEG_BASE;
2380 /* Reassembly Control Registers */
2381 iadev->reass_reg = base + REASS_BASE;
2382 /* Front end/ DMA control registers */
2383 iadev->phy = base + PHY_BASE;
2384 iadev->dma = base + PHY_BASE;
2385 /* RAM - Segmentation RAm and Reassembly RAM */
2386 iadev->ram = base + ACTUAL_RAM_BASE;
2387 iadev->seg_ram = base + ACTUAL_SEG_RAM_BASE;
2388 iadev->reass_ram = base + ACTUAL_REASS_RAM_BASE;
2389
2390 /* lets print out the above */
2391 IF_INIT(printk("Base addrs: %p %p %p \n %p %p %p %p\n",
2392 iadev->reg,iadev->seg_reg,iadev->reass_reg,
2393 iadev->phy, iadev->ram, iadev->seg_ram,
2394 iadev->reass_ram);)
2395
2396 /* lets try reading the MAC address */
2397 error = get_esi(dev);
2398 if (error) {
2399 iounmap(iadev->base);
2400 return error;
2401 }
2402 printk("IA: ");
2403 for (i=0; i < ESI_LEN; i++)
2404 printk("%s%02X",i ? "-" : "",dev->esi[i]);
2405 printk("\n");
2406
2407 /* reset SAR */
2408 if (reset_sar(dev)) {
2409 iounmap(iadev->base);
2410 printk("IA: reset SAR fail, please try again\n");
2411 return 1;
2412 }
2413 return 0;
2414}
2415
2416static void ia_update_stats(IADEV *iadev) {
2417 if (!iadev->carrier_detect)
2418 return;
2419 iadev->rx_cell_cnt += readw(iadev->reass_reg+CELL_CTR0)&0xffff;
2420 iadev->rx_cell_cnt += (readw(iadev->reass_reg+CELL_CTR1) & 0xffff) << 16;
2421 iadev->drop_rxpkt += readw(iadev->reass_reg + DRP_PKT_CNTR ) & 0xffff;
2422 iadev->drop_rxcell += readw(iadev->reass_reg + ERR_CNTR) & 0xffff;
2423 iadev->tx_cell_cnt += readw(iadev->seg_reg + CELL_CTR_LO_AUTO)&0xffff;
2424 iadev->tx_cell_cnt += (readw(iadev->seg_reg+CELL_CTR_HIGH_AUTO)&0xffff)<<16;
2425 return;
2426}
2427
2428static void ia_led_timer(unsigned long arg) {
2429 unsigned long flags;
2430 static u_char blinking[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2431 u_char i;
2432 static u32 ctrl_reg;
2433 for (i = 0; i < iadev_count; i++) {
2434 if (ia_dev[i]) {
2435 ctrl_reg = readl(ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
2436 if (blinking[i] == 0) {
2437 blinking[i]++;
2438 ctrl_reg &= (~CTRL_LED);
2439 writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
2440 ia_update_stats(ia_dev[i]);
2441 }
2442 else {
2443 blinking[i] = 0;
2444 ctrl_reg |= CTRL_LED;
2445 writel(ctrl_reg, ia_dev[i]->reg+IPHASE5575_BUS_CONTROL_REG);
2446 spin_lock_irqsave(&ia_dev[i]->tx_lock, flags);
2447 if (ia_dev[i]->close_pending)
2448 wake_up(&ia_dev[i]->close_wait);
2449 ia_tx_poll(ia_dev[i]);
2450 spin_unlock_irqrestore(&ia_dev[i]->tx_lock, flags);
2451 }
2452 }
2453 }
2454 mod_timer(&ia_timer, jiffies + HZ / 4);
2455 return;
2456}
2457
2458static void ia_phy_put(struct atm_dev *dev, unsigned char value,
2459 unsigned long addr)
2460{
2461 writel(value, INPH_IA_DEV(dev)->phy+addr);
2462}
2463
2464static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr)
2465{
2466 return readl(INPH_IA_DEV(dev)->phy+addr);
2467}
2468
2469static void ia_free_tx(IADEV *iadev)
2470{
2471 int i;
2472
2473 kfree(iadev->desc_tbl);
2474 for (i = 0; i < iadev->num_vc; i++)
2475 kfree(iadev->testTable[i]);
2476 kfree(iadev->testTable);
2477 for (i = 0; i < iadev->num_tx_desc; i++) {
2478 struct cpcs_trailer_desc *desc = iadev->tx_buf + i;
2479
2480 pci_unmap_single(iadev->pci, desc->dma_addr,
2481 sizeof(*desc->cpcs), PCI_DMA_TODEVICE);
2482 kfree(desc->cpcs);
2483 }
2484 kfree(iadev->tx_buf);
2485 pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->tx_dle_q.start,
2486 iadev->tx_dle_dma);
2487}
2488
2489static void ia_free_rx(IADEV *iadev)
2490{
2491 kfree(iadev->rx_open);
2492 pci_free_consistent(iadev->pci, DLE_TOTAL_SIZE, iadev->rx_dle_q.start,
2493 iadev->rx_dle_dma);
2494}
2495
Chas Williams249c14b2006-06-29 12:35:32 -07002496static int __devinit ia_start(struct atm_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497{
2498 IADEV *iadev;
2499 int error;
2500 unsigned char phy;
2501 u32 ctrl_reg;
2502 IF_EVENT(printk(">ia_start\n");)
2503 iadev = INPH_IA_DEV(dev);
Thomas Gleixnerdace1452006-07-01 19:29:38 -07002504 if (request_irq(iadev->irq, &ia_int, IRQF_SHARED, DEV_LABEL, dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
2506 dev->number, iadev->irq);
2507 error = -EAGAIN;
2508 goto err_out;
2509 }
2510 /* @@@ should release IRQ on error */
2511 /* enabling memory + master */
2512 if ((error = pci_write_config_word(iadev->pci,
2513 PCI_COMMAND,
2514 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER )))
2515 {
2516 printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
2517 "master (0x%x)\n",dev->number, error);
2518 error = -EIO;
2519 goto err_free_irq;
2520 }
2521 udelay(10);
2522
2523 /* Maybe we should reset the front end, initialize Bus Interface Control
2524 Registers and see. */
2525
2526 IF_INIT(printk("Bus ctrl reg: %08x\n",
2527 readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));)
2528 ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG);
2529 ctrl_reg = (ctrl_reg & (CTRL_LED | CTRL_FE_RST))
2530 | CTRL_B8
2531 | CTRL_B16
2532 | CTRL_B32
2533 | CTRL_B48
2534 | CTRL_B64
2535 | CTRL_B128
2536 | CTRL_ERRMASK
2537 | CTRL_DLETMASK /* shud be removed l8r */
2538 | CTRL_DLERMASK
2539 | CTRL_SEGMASK
2540 | CTRL_REASSMASK
2541 | CTRL_FEMASK
2542 | CTRL_CSPREEMPT;
2543
2544 writel(ctrl_reg, iadev->reg+IPHASE5575_BUS_CONTROL_REG);
2545
2546 IF_INIT(printk("Bus ctrl reg after initializing: %08x\n",
2547 readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));
2548 printk("Bus status reg after init: %08x\n",
2549 readl(iadev->reg+IPHASE5575_BUS_STATUS_REG));)
2550
2551 ia_hw_type(iadev);
2552 error = tx_init(dev);
2553 if (error)
2554 goto err_free_irq;
2555 error = rx_init(dev);
2556 if (error)
2557 goto err_free_tx;
2558
2559 ctrl_reg = readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG);
2560 writel(ctrl_reg | CTRL_FE_RST, iadev->reg+IPHASE5575_BUS_CONTROL_REG);
2561 IF_INIT(printk("Bus ctrl reg after initializing: %08x\n",
2562 readl(iadev->reg+IPHASE5575_BUS_CONTROL_REG));)
2563 phy = 0; /* resolve compiler complaint */
2564 IF_INIT (
2565 if ((phy=ia_phy_get(dev,0)) == 0x30)
2566 printk("IA: pm5346,rev.%d\n",phy&0x0f);
2567 else
2568 printk("IA: utopia,rev.%0x\n",phy);)
2569
2570 if (iadev->phy_type & FE_25MBIT_PHY)
2571 ia_mb25_init(iadev);
2572 else if (iadev->phy_type & (FE_DS3_PHY | FE_E3_PHY))
2573 ia_suni_pm7345_init(iadev);
2574 else {
2575 error = suni_init(dev);
2576 if (error)
2577 goto err_free_rx;
Jorge Boncompte [DTI2]d6c1d702008-06-16 17:16:35 -07002578 if (dev->phy->start) {
2579 error = dev->phy->start(dev);
2580 if (error)
2581 goto err_free_rx;
2582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 /* Get iadev->carrier_detect status */
françois romieu26c5c442011-09-30 00:37:43 +00002584 ia_frontend_intr(iadev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 }
2586 return 0;
2587
2588err_free_rx:
2589 ia_free_rx(iadev);
2590err_free_tx:
2591 ia_free_tx(iadev);
2592err_free_irq:
2593 free_irq(iadev->irq, dev);
2594err_out:
2595 return error;
2596}
2597
2598static void ia_close(struct atm_vcc *vcc)
2599{
2600 DEFINE_WAIT(wait);
2601 u16 *vc_table;
2602 IADEV *iadev;
2603 struct ia_vcc *ia_vcc;
2604 struct sk_buff *skb = NULL;
2605 struct sk_buff_head tmp_tx_backlog, tmp_vcc_backlog;
2606 unsigned long closetime, flags;
2607
2608 iadev = INPH_IA_DEV(vcc->dev);
2609 ia_vcc = INPH_IA_VCC(vcc);
2610 if (!ia_vcc) return;
2611
2612 IF_EVENT(printk("ia_close: ia_vcc->vc_desc_cnt = %d vci = %d\n",
2613 ia_vcc->vc_desc_cnt,vcc->vci);)
2614 clear_bit(ATM_VF_READY,&vcc->flags);
2615 skb_queue_head_init (&tmp_tx_backlog);
2616 skb_queue_head_init (&tmp_vcc_backlog);
2617 if (vcc->qos.txtp.traffic_class != ATM_NONE) {
2618 iadev->close_pending++;
2619 prepare_to_wait(&iadev->timeout_wait, &wait, TASK_UNINTERRUPTIBLE);
2620 schedule_timeout(50);
2621 finish_wait(&iadev->timeout_wait, &wait);
2622 spin_lock_irqsave(&iadev->tx_lock, flags);
2623 while((skb = skb_dequeue(&iadev->tx_backlog))) {
2624 if (ATM_SKB(skb)->vcc == vcc){
2625 if (vcc->pop) vcc->pop(vcc, skb);
2626 else dev_kfree_skb_any(skb);
2627 }
2628 else
2629 skb_queue_tail(&tmp_tx_backlog, skb);
2630 }
2631 while((skb = skb_dequeue(&tmp_tx_backlog)))
2632 skb_queue_tail(&iadev->tx_backlog, skb);
2633 IF_EVENT(printk("IA TX Done decs_cnt = %d\n", ia_vcc->vc_desc_cnt);)
2634 closetime = 300000 / ia_vcc->pcr;
2635 if (closetime == 0)
2636 closetime = 1;
2637 spin_unlock_irqrestore(&iadev->tx_lock, flags);
2638 wait_event_timeout(iadev->close_wait, (ia_vcc->vc_desc_cnt <= 0), closetime);
2639 spin_lock_irqsave(&iadev->tx_lock, flags);
2640 iadev->close_pending--;
2641 iadev->testTable[vcc->vci]->lastTime = 0;
2642 iadev->testTable[vcc->vci]->fract = 0;
2643 iadev->testTable[vcc->vci]->vc_status = VC_UBR;
2644 if (vcc->qos.txtp.traffic_class == ATM_ABR) {
2645 if (vcc->qos.txtp.min_pcr > 0)
2646 iadev->sum_mcr -= vcc->qos.txtp.min_pcr;
2647 }
2648 if (vcc->qos.txtp.traffic_class == ATM_CBR) {
2649 ia_vcc = INPH_IA_VCC(vcc);
2650 iadev->sum_mcr -= ia_vcc->NumCbrEntry*iadev->Granularity;
2651 ia_cbrVc_close (vcc);
2652 }
2653 spin_unlock_irqrestore(&iadev->tx_lock, flags);
2654 }
2655
2656 if (vcc->qos.rxtp.traffic_class != ATM_NONE) {
2657 // reset reass table
2658 vc_table = (u16 *)(iadev->reass_ram+REASS_TABLE*iadev->memSize);
2659 vc_table += vcc->vci;
2660 *vc_table = NO_AAL5_PKT;
2661 // reset vc table
2662 vc_table = (u16 *)(iadev->reass_ram+RX_VC_TABLE*iadev->memSize);
2663 vc_table += vcc->vci;
2664 *vc_table = (vcc->vci << 6) | 15;
2665 if (vcc->qos.rxtp.traffic_class == ATM_ABR) {
2666 struct abr_vc_table __iomem *abr_vc_table =
2667 (iadev->reass_ram+ABR_VC_TABLE*iadev->memSize);
2668 abr_vc_table += vcc->vci;
2669 abr_vc_table->rdf = 0x0003;
2670 abr_vc_table->air = 0x5eb1;
2671 }
2672 // Drain the packets
2673 rx_dle_intr(vcc->dev);
2674 iadev->rx_open[vcc->vci] = NULL;
2675 }
2676 kfree(INPH_IA_VCC(vcc));
2677 ia_vcc = NULL;
2678 vcc->dev_data = NULL;
2679 clear_bit(ATM_VF_ADDR,&vcc->flags);
2680 return;
2681}
2682
2683static int ia_open(struct atm_vcc *vcc)
2684{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 struct ia_vcc *ia_vcc;
2686 int error;
2687 if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))
2688 {
2689 IF_EVENT(printk("ia: not partially allocated resources\n");)
2690 vcc->dev_data = NULL;
2691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692 if (vcc->vci != ATM_VPI_UNSPEC && vcc->vpi != ATM_VCI_UNSPEC)
2693 {
2694 IF_EVENT(printk("iphase open: unspec part\n");)
2695 set_bit(ATM_VF_ADDR,&vcc->flags);
2696 }
2697 if (vcc->qos.aal != ATM_AAL5)
2698 return -EINVAL;
2699 IF_EVENT(printk(DEV_LABEL "(itf %d): open %d.%d\n",
2700 vcc->dev->number, vcc->vpi, vcc->vci);)
2701
2702 /* Device dependent initialization */
2703 ia_vcc = kmalloc(sizeof(*ia_vcc), GFP_KERNEL);
2704 if (!ia_vcc) return -ENOMEM;
2705 vcc->dev_data = ia_vcc;
2706
2707 if ((error = open_rx(vcc)))
2708 {
2709 IF_EVENT(printk("iadev: error in open_rx, closing\n");)
2710 ia_close(vcc);
2711 return error;
2712 }
2713
2714 if ((error = open_tx(vcc)))
2715 {
2716 IF_EVENT(printk("iadev: error in open_tx, closing\n");)
2717 ia_close(vcc);
2718 return error;
2719 }
2720
2721 set_bit(ATM_VF_READY,&vcc->flags);
2722
2723#if 0
2724 {
2725 static u8 first = 1;
2726 if (first) {
2727 ia_timer.expires = jiffies + 3*HZ;
2728 add_timer(&ia_timer);
2729 first = 0;
2730 }
2731 }
2732#endif
2733 IF_EVENT(printk("ia open returning\n");)
2734 return 0;
2735}
2736
2737static int ia_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
2738{
2739 IF_EVENT(printk(">ia_change_qos\n");)
2740 return 0;
2741}
2742
2743static int ia_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg)
2744{
2745 IA_CMDBUF ia_cmds;
2746 IADEV *iadev;
2747 int i, board;
2748 u16 __user *tmps;
2749 IF_EVENT(printk(">ia_ioctl\n");)
2750 if (cmd != IA_CMD) {
2751 if (!dev->phy->ioctl) return -EINVAL;
2752 return dev->phy->ioctl(dev,cmd,arg);
2753 }
2754 if (copy_from_user(&ia_cmds, arg, sizeof ia_cmds)) return -EFAULT;
2755 board = ia_cmds.status;
2756 if ((board < 0) || (board > iadev_count))
2757 board = 0;
2758 iadev = ia_dev[board];
2759 switch (ia_cmds.cmd) {
2760 case MEMDUMP:
2761 {
2762 switch (ia_cmds.sub_cmd) {
2763 case MEMDUMP_DEV:
2764 if (!capable(CAP_NET_ADMIN)) return -EPERM;
2765 if (copy_to_user(ia_cmds.buf, iadev, sizeof(IADEV)))
2766 return -EFAULT;
2767 ia_cmds.status = 0;
2768 break;
2769 case MEMDUMP_SEGREG:
2770 if (!capable(CAP_NET_ADMIN)) return -EPERM;
2771 tmps = (u16 __user *)ia_cmds.buf;
2772 for(i=0; i<0x80; i+=2, tmps++)
2773 if(put_user((u16)(readl(iadev->seg_reg+i) & 0xffff), tmps)) return -EFAULT;
2774 ia_cmds.status = 0;
2775 ia_cmds.len = 0x80;
2776 break;
2777 case MEMDUMP_REASSREG:
2778 if (!capable(CAP_NET_ADMIN)) return -EPERM;
2779 tmps = (u16 __user *)ia_cmds.buf;
2780 for(i=0; i<0x80; i+=2, tmps++)
2781 if(put_user((u16)(readl(iadev->reass_reg+i) & 0xffff), tmps)) return -EFAULT;
2782 ia_cmds.status = 0;
2783 ia_cmds.len = 0x80;
2784 break;
2785 case MEMDUMP_FFL:
2786 {
2787 ia_regs_t *regs_local;
2788 ffredn_t *ffL;
2789 rfredn_t *rfL;
2790
2791 if (!capable(CAP_NET_ADMIN)) return -EPERM;
2792 regs_local = kmalloc(sizeof(*regs_local), GFP_KERNEL);
2793 if (!regs_local) return -ENOMEM;
2794 ffL = &regs_local->ffredn;
2795 rfL = &regs_local->rfredn;
2796 /* Copy real rfred registers into the local copy */
2797 for (i=0; i<(sizeof (rfredn_t))/4; i++)
2798 ((u_int *)rfL)[i] = readl(iadev->reass_reg + i) & 0xffff;
2799 /* Copy real ffred registers into the local copy */
2800 for (i=0; i<(sizeof (ffredn_t))/4; i++)
2801 ((u_int *)ffL)[i] = readl(iadev->seg_reg + i) & 0xffff;
2802
2803 if (copy_to_user(ia_cmds.buf, regs_local,sizeof(ia_regs_t))) {
2804 kfree(regs_local);
2805 return -EFAULT;
2806 }
2807 kfree(regs_local);
2808 printk("Board %d registers dumped\n", board);
2809 ia_cmds.status = 0;
2810 }
2811 break;
2812 case READ_REG:
2813 {
2814 if (!capable(CAP_NET_ADMIN)) return -EPERM;
2815 desc_dbg(iadev);
2816 ia_cmds.status = 0;
2817 }
2818 break;
2819 case 0x6:
2820 {
2821 ia_cmds.status = 0;
2822 printk("skb = 0x%lx\n", (long)skb_peek(&iadev->tx_backlog));
2823 printk("rtn_q: 0x%lx\n",(long)ia_deque_rtn_q(&iadev->tx_return_q));
2824 }
2825 break;
2826 case 0x8:
2827 {
2828 struct k_sonet_stats *stats;
2829 stats = &PRIV(_ia_dev[board])->sonet_stats;
2830 printk("section_bip: %d\n", atomic_read(&stats->section_bip));
2831 printk("line_bip : %d\n", atomic_read(&stats->line_bip));
2832 printk("path_bip : %d\n", atomic_read(&stats->path_bip));
2833 printk("line_febe : %d\n", atomic_read(&stats->line_febe));
2834 printk("path_febe : %d\n", atomic_read(&stats->path_febe));
2835 printk("corr_hcs : %d\n", atomic_read(&stats->corr_hcs));
2836 printk("uncorr_hcs : %d\n", atomic_read(&stats->uncorr_hcs));
2837 printk("tx_cells : %d\n", atomic_read(&stats->tx_cells));
2838 printk("rx_cells : %d\n", atomic_read(&stats->rx_cells));
2839 }
2840 ia_cmds.status = 0;
2841 break;
2842 case 0x9:
2843 if (!capable(CAP_NET_ADMIN)) return -EPERM;
2844 for (i = 1; i <= iadev->num_rx_desc; i++)
2845 free_desc(_ia_dev[board], i);
2846 writew( ~(RX_FREEQ_EMPT | RX_EXCP_RCVD),
2847 iadev->reass_reg+REASS_MASK_REG);
2848 iadev->rxing = 1;
2849
2850 ia_cmds.status = 0;
2851 break;
2852
2853 case 0xb:
2854 if (!capable(CAP_NET_ADMIN)) return -EPERM;
françois romieu26c5c442011-09-30 00:37:43 +00002855 ia_frontend_intr(iadev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 break;
2857 case 0xa:
2858 if (!capable(CAP_NET_ADMIN)) return -EPERM;
2859 {
2860 ia_cmds.status = 0;
2861 IADebugFlag = ia_cmds.maddr;
2862 printk("New debug option loaded\n");
2863 }
2864 break;
2865 default:
2866 ia_cmds.status = 0;
2867 break;
2868 }
2869 }
2870 break;
2871 default:
2872 break;
2873
2874 }
2875 return 0;
2876}
2877
2878static int ia_getsockopt(struct atm_vcc *vcc, int level, int optname,
2879 void __user *optval, int optlen)
2880{
2881 IF_EVENT(printk(">ia_getsockopt\n");)
2882 return -EINVAL;
2883}
2884
2885static int ia_setsockopt(struct atm_vcc *vcc, int level, int optname,
David S. Millerb7058842009-09-30 16:12:20 -07002886 void __user *optval, unsigned int optlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887{
2888 IF_EVENT(printk(">ia_setsockopt\n");)
2889 return -EINVAL;
2890}
2891
2892static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
2893 IADEV *iadev;
2894 struct dle *wr_ptr;
2895 struct tx_buf_desc __iomem *buf_desc_ptr;
2896 int desc;
2897 int comp_code;
2898 int total_len;
2899 struct cpcs_trailer *trailer;
2900 struct ia_vcc *iavcc;
2901
2902 iadev = INPH_IA_DEV(vcc->dev);
2903 iavcc = INPH_IA_VCC(vcc);
2904 if (!iavcc->txing) {
2905 printk("discard packet on closed VC\n");
2906 if (vcc->pop)
2907 vcc->pop(vcc, skb);
2908 else
2909 dev_kfree_skb_any(skb);
2910 return 0;
2911 }
2912
2913 if (skb->len > iadev->tx_buf_sz - 8) {
2914 printk("Transmit size over tx buffer size\n");
2915 if (vcc->pop)
2916 vcc->pop(vcc, skb);
2917 else
2918 dev_kfree_skb_any(skb);
2919 return 0;
2920 }
Alan Cox97928f72008-06-17 16:21:18 -07002921 if ((unsigned long)skb->data & 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922 printk("Misaligned SKB\n");
2923 if (vcc->pop)
2924 vcc->pop(vcc, skb);
2925 else
2926 dev_kfree_skb_any(skb);
2927 return 0;
2928 }
2929 /* Get a descriptor number from our free descriptor queue
2930 We get the descr number from the TCQ now, since I am using
2931 the TCQ as a free buffer queue. Initially TCQ will be
2932 initialized with all the descriptors and is hence, full.
2933 */
2934 desc = get_desc (iadev, iavcc);
2935 if (desc == 0xffff)
2936 return 1;
2937 comp_code = desc >> 13;
2938 desc &= 0x1fff;
2939
2940 if ((desc == 0) || (desc > iadev->num_tx_desc))
2941 {
2942 IF_ERR(printk(DEV_LABEL "invalid desc for send: %d\n", desc);)
2943 atomic_inc(&vcc->stats->tx);
2944 if (vcc->pop)
2945 vcc->pop(vcc, skb);
2946 else
2947 dev_kfree_skb_any(skb);
2948 return 0; /* return SUCCESS */
2949 }
2950
2951 if (comp_code)
2952 {
2953 IF_ERR(printk(DEV_LABEL "send desc:%d completion code %d error\n",
2954 desc, comp_code);)
2955 }
2956
2957 /* remember the desc and vcc mapping */
2958 iavcc->vc_desc_cnt++;
2959 iadev->desc_tbl[desc-1].iavcc = iavcc;
2960 iadev->desc_tbl[desc-1].txskb = skb;
2961 IA_SKB_STATE(skb) = 0;
2962
2963 iadev->ffL.tcq_rd += 2;
2964 if (iadev->ffL.tcq_rd > iadev->ffL.tcq_ed)
2965 iadev->ffL.tcq_rd = iadev->ffL.tcq_st;
2966 writew(iadev->ffL.tcq_rd, iadev->seg_reg+TCQ_RD_PTR);
2967
2968 /* Put the descriptor number in the packet ready queue
2969 and put the updated write pointer in the DLE field
2970 */
2971 *(u16*)(iadev->seg_ram+iadev->ffL.prq_wr) = desc;
2972
2973 iadev->ffL.prq_wr += 2;
2974 if (iadev->ffL.prq_wr > iadev->ffL.prq_ed)
2975 iadev->ffL.prq_wr = iadev->ffL.prq_st;
2976
2977 /* Figure out the exact length of the packet and padding required to
2978 make it aligned on a 48 byte boundary. */
2979 total_len = skb->len + sizeof(struct cpcs_trailer);
2980 total_len = ((total_len + 47) / 48) * 48;
2981 IF_TX(printk("ia packet len:%d padding:%d\n", total_len, total_len - skb->len);)
2982
2983 /* Put the packet in a tx buffer */
2984 trailer = iadev->tx_buf[desc-1].cpcs;
David Howells849e8ca2008-07-30 16:33:05 -07002985 IF_TX(printk("Sent: skb = 0x%p skb->data: 0x%p len: %d, desc: %d\n",
2986 skb, skb->data, skb->len, desc);)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 trailer->control = 0;
2988 /*big endian*/
2989 trailer->length = ((skb->len & 0xff) << 8) | ((skb->len & 0xff00) >> 8);
2990 trailer->crc32 = 0; /* not needed - dummy bytes */
2991
2992 /* Display the packet */
2993 IF_TXPKT(printk("Sent data: len = %d MsgNum = %d\n",
2994 skb->len, tcnter++);
2995 xdump(skb->data, skb->len, "TX: ");
2996 printk("\n");)
2997
2998 /* Build the buffer descriptor */
2999 buf_desc_ptr = iadev->seg_ram+TX_DESC_BASE;
3000 buf_desc_ptr += desc; /* points to the corresponding entry */
3001 buf_desc_ptr->desc_mode = AAL5 | EOM_EN | APP_CRC32 | CMPL_INT;
3002 /* Huh ? p.115 of users guide describes this as a read-only register */
3003 writew(TRANSMIT_DONE, iadev->seg_reg+SEG_INTR_STATUS_REG);
3004 buf_desc_ptr->vc_index = vcc->vci;
3005 buf_desc_ptr->bytes = total_len;
3006
3007 if (vcc->qos.txtp.traffic_class == ATM_ABR)
3008 clear_lockup (vcc, iadev);
3009
3010 /* Build the DLE structure */
3011 wr_ptr = iadev->tx_dle_q.write;
3012 memset((caddr_t)wr_ptr, 0, sizeof(*wr_ptr));
3013 wr_ptr->sys_pkt_addr = pci_map_single(iadev->pci, skb->data,
3014 skb->len, PCI_DMA_TODEVICE);
3015 wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) |
3016 buf_desc_ptr->buf_start_lo;
Wu Fengguangb67445fc2009-01-07 18:09:10 -08003017 /* wr_ptr->bytes = swap_byte_order(total_len); didn't seem to affect?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 wr_ptr->bytes = skb->len;
3019
3020 /* hw bug - DLEs of 0x2d, 0x2e, 0x2f cause DMA lockup */
3021 if ((wr_ptr->bytes >> 2) == 0xb)
3022 wr_ptr->bytes = 0x30;
3023
3024 wr_ptr->mode = TX_DLE_PSI;
3025 wr_ptr->prq_wr_ptr_data = 0;
3026
3027 /* end is not to be used for the DLE q */
3028 if (++wr_ptr == iadev->tx_dle_q.end)
3029 wr_ptr = iadev->tx_dle_q.start;
3030
3031 /* Build trailer dle */
3032 wr_ptr->sys_pkt_addr = iadev->tx_buf[desc-1].dma_addr;
3033 wr_ptr->local_pkt_addr = ((buf_desc_ptr->buf_start_hi << 16) |
3034 buf_desc_ptr->buf_start_lo) + total_len - sizeof(struct cpcs_trailer);
3035
3036 wr_ptr->bytes = sizeof(struct cpcs_trailer);
3037 wr_ptr->mode = DMA_INT_ENABLE;
3038 wr_ptr->prq_wr_ptr_data = iadev->ffL.prq_wr;
3039
3040 /* end is not to be used for the DLE q */
3041 if (++wr_ptr == iadev->tx_dle_q.end)
3042 wr_ptr = iadev->tx_dle_q.start;
3043
3044 iadev->tx_dle_q.write = wr_ptr;
3045 ATM_DESC(skb) = vcc->vci;
3046 skb_queue_tail(&iadev->tx_dma_q, skb);
3047
3048 atomic_inc(&vcc->stats->tx);
3049 iadev->tx_pkt_cnt++;
3050 /* Increment transaction counter */
3051 writel(2, iadev->dma+IPHASE5575_TX_COUNTER);
3052
3053#if 0
3054 /* add flow control logic */
3055 if (atomic_read(&vcc->stats->tx) % 20 == 0) {
3056 if (iavcc->vc_desc_cnt > 10) {
3057 vcc->tx_quota = vcc->tx_quota * 3 / 4;
3058 printk("Tx1: vcc->tx_quota = %d \n", (u32)vcc->tx_quota );
3059 iavcc->flow_inc = -1;
3060 iavcc->saved_tx_quota = vcc->tx_quota;
3061 } else if ((iavcc->flow_inc < 0) && (iavcc->vc_desc_cnt < 3)) {
3062 // vcc->tx_quota = 3 * iavcc->saved_tx_quota / 4;
3063 printk("Tx2: vcc->tx_quota = %d \n", (u32)vcc->tx_quota );
3064 iavcc->flow_inc = 0;
3065 }
3066 }
3067#endif
3068 IF_TX(printk("ia send done\n");)
3069 return 0;
3070}
3071
3072static int ia_send(struct atm_vcc *vcc, struct sk_buff *skb)
3073{
3074 IADEV *iadev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 unsigned long flags;
3076
3077 iadev = INPH_IA_DEV(vcc->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 if ((!skb)||(skb->len>(iadev->tx_buf_sz-sizeof(struct cpcs_trailer))))
3079 {
3080 if (!skb)
3081 printk(KERN_CRIT "null skb in ia_send\n");
3082 else dev_kfree_skb_any(skb);
3083 return -EINVAL;
3084 }
3085 spin_lock_irqsave(&iadev->tx_lock, flags);
3086 if (!test_bit(ATM_VF_READY,&vcc->flags)){
3087 dev_kfree_skb_any(skb);
3088 spin_unlock_irqrestore(&iadev->tx_lock, flags);
3089 return -EINVAL;
3090 }
3091 ATM_SKB(skb)->vcc = vcc;
3092
3093 if (skb_peek(&iadev->tx_backlog)) {
3094 skb_queue_tail(&iadev->tx_backlog, skb);
3095 }
3096 else {
3097 if (ia_pkt_tx (vcc, skb)) {
3098 skb_queue_tail(&iadev->tx_backlog, skb);
3099 }
3100 }
3101 spin_unlock_irqrestore(&iadev->tx_lock, flags);
3102 return 0;
3103
3104}
3105
3106static int ia_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
3107{
3108 int left = *pos, n;
3109 char *tmpPtr;
3110 IADEV *iadev = INPH_IA_DEV(dev);
3111 if(!left--) {
3112 if (iadev->phy_type == FE_25MBIT_PHY) {
3113 n = sprintf(page, " Board Type : Iphase5525-1KVC-128K\n");
3114 return n;
3115 }
3116 if (iadev->phy_type == FE_DS3_PHY)
3117 n = sprintf(page, " Board Type : Iphase-ATM-DS3");
3118 else if (iadev->phy_type == FE_E3_PHY)
3119 n = sprintf(page, " Board Type : Iphase-ATM-E3");
3120 else if (iadev->phy_type == FE_UTP_OPTION)
3121 n = sprintf(page, " Board Type : Iphase-ATM-UTP155");
3122 else
3123 n = sprintf(page, " Board Type : Iphase-ATM-OC3");
3124 tmpPtr = page + n;
3125 if (iadev->pci_map_size == 0x40000)
3126 n += sprintf(tmpPtr, "-1KVC-");
3127 else
3128 n += sprintf(tmpPtr, "-4KVC-");
3129 tmpPtr = page + n;
3130 if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_1M)
3131 n += sprintf(tmpPtr, "1M \n");
3132 else if ((iadev->memType & MEM_SIZE_MASK) == MEM_SIZE_512K)
3133 n += sprintf(tmpPtr, "512K\n");
3134 else
3135 n += sprintf(tmpPtr, "128K\n");
3136 return n;
3137 }
3138 if (!left) {
3139 return sprintf(page, " Number of Tx Buffer: %u\n"
3140 " Size of Tx Buffer : %u\n"
3141 " Number of Rx Buffer: %u\n"
3142 " Size of Rx Buffer : %u\n"
3143 " Packets Receiverd : %u\n"
3144 " Packets Transmitted: %u\n"
3145 " Cells Received : %u\n"
3146 " Cells Transmitted : %u\n"
3147 " Board Dropped Cells: %u\n"
3148 " Board Dropped Pkts : %u\n",
3149 iadev->num_tx_desc, iadev->tx_buf_sz,
3150 iadev->num_rx_desc, iadev->rx_buf_sz,
3151 iadev->rx_pkt_cnt, iadev->tx_pkt_cnt,
3152 iadev->rx_cell_cnt, iadev->tx_cell_cnt,
3153 iadev->drop_rxcell, iadev->drop_rxpkt);
3154 }
3155 return 0;
3156}
3157
3158static const struct atmdev_ops ops = {
3159 .open = ia_open,
3160 .close = ia_close,
3161 .ioctl = ia_ioctl,
3162 .getsockopt = ia_getsockopt,
3163 .setsockopt = ia_setsockopt,
3164 .send = ia_send,
3165 .phy_put = ia_phy_put,
3166 .phy_get = ia_phy_get,
3167 .change_qos = ia_change_qos,
3168 .proc_read = ia_proc_read,
3169 .owner = THIS_MODULE,
3170};
3171
3172static int __devinit ia_init_one(struct pci_dev *pdev,
3173 const struct pci_device_id *ent)
3174{
3175 struct atm_dev *dev;
3176 IADEV *iadev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 int ret;
3178
Mariusz Kozlowskif7141762007-08-10 15:26:18 -07003179 iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 if (!iadev) {
3181 ret = -ENOMEM;
3182 goto err_out;
3183 }
Mariusz Kozlowskif7141762007-08-10 15:26:18 -07003184
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 iadev->pci = pdev;
3186
3187 IF_INIT(printk("ia detected at bus:%d dev: %d function:%d\n",
3188 pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));)
3189 if (pci_enable_device(pdev)) {
3190 ret = -ENODEV;
3191 goto err_out_free_iadev;
3192 }
Dan Williamsd9ca6762010-12-08 19:40:47 +00003193 dev = atm_dev_register(DEV_LABEL, &pdev->dev, &ops, -1, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 if (!dev) {
3195 ret = -ENOMEM;
3196 goto err_out_disable_dev;
3197 }
3198 dev->dev_data = iadev;
3199 IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", dev->number);)
David Howells849e8ca2008-07-30 16:33:05 -07003200 IF_INIT(printk("dev_id = 0x%p iadev->LineRate = %d \n", dev,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 iadev->LineRate);)
3202
Jorge Boncompte [DTI2]c0ed0b62008-06-16 17:16:04 -07003203 pci_set_drvdata(pdev, dev);
3204
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 ia_dev[iadev_count] = iadev;
3206 _ia_dev[iadev_count] = dev;
3207 iadev_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 if (ia_init(dev) || ia_start(dev)) {
3209 IF_INIT(printk("IA register failed!\n");)
3210 iadev_count--;
3211 ia_dev[iadev_count] = NULL;
3212 _ia_dev[iadev_count] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 ret = -EINVAL;
3214 goto err_out_deregister_dev;
3215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 IF_EVENT(printk("iadev_count = %d\n", iadev_count);)
3217
3218 iadev->next_board = ia_boards;
3219 ia_boards = dev;
3220
Linus Torvalds1da177e2005-04-16 15:20:36 -07003221 return 0;
3222
3223err_out_deregister_dev:
3224 atm_dev_deregister(dev);
3225err_out_disable_dev:
3226 pci_disable_device(pdev);
3227err_out_free_iadev:
3228 kfree(iadev);
3229err_out:
3230 return ret;
3231}
3232
3233static void __devexit ia_remove_one(struct pci_dev *pdev)
3234{
3235 struct atm_dev *dev = pci_get_drvdata(pdev);
3236 IADEV *iadev = INPH_IA_DEV(dev);
3237
Jorge Boncompte [DTI2]d6c1d702008-06-16 17:16:35 -07003238 /* Disable phy interrupts */
3239 ia_phy_put(dev, ia_phy_get(dev, SUNI_RSOP_CIE) & ~(SUNI_RSOP_CIE_LOSE),
3240 SUNI_RSOP_CIE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241 udelay(1);
3242
Jorge Boncompte [DTI2]d6c1d702008-06-16 17:16:35 -07003243 if (dev->phy && dev->phy->stop)
3244 dev->phy->stop(dev);
3245
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246 /* De-register device */
3247 free_irq(iadev->irq, dev);
3248 iadev_count--;
3249 ia_dev[iadev_count] = NULL;
3250 _ia_dev[iadev_count] = NULL;
3251 IF_EVENT(printk("deregistering iav at (itf:%d)\n", dev->number);)
3252 atm_dev_deregister(dev);
3253
3254 iounmap(iadev->base);
3255 pci_disable_device(pdev);
3256
3257 ia_free_rx(iadev);
3258 ia_free_tx(iadev);
3259
3260 kfree(iadev);
3261}
3262
3263static struct pci_device_id ia_pci_tbl[] = {
3264 { PCI_VENDOR_ID_IPHASE, 0x0008, PCI_ANY_ID, PCI_ANY_ID, },
3265 { PCI_VENDOR_ID_IPHASE, 0x0009, PCI_ANY_ID, PCI_ANY_ID, },
3266 { 0,}
3267};
3268MODULE_DEVICE_TABLE(pci, ia_pci_tbl);
3269
3270static struct pci_driver ia_driver = {
3271 .name = DEV_LABEL,
3272 .id_table = ia_pci_tbl,
3273 .probe = ia_init_one,
3274 .remove = __devexit_p(ia_remove_one),
3275};
3276
3277static int __init ia_module_init(void)
3278{
3279 int ret;
3280
3281 ret = pci_register_driver(&ia_driver);
3282 if (ret >= 0) {
3283 ia_timer.expires = jiffies + 3*HZ;
3284 add_timer(&ia_timer);
3285 } else
3286 printk(KERN_ERR DEV_LABEL ": no adapter found\n");
3287 return ret;
3288}
3289
3290static void __exit ia_module_exit(void)
3291{
3292 pci_unregister_driver(&ia_driver);
3293
3294 del_timer(&ia_timer);
3295}
3296
3297module_init(ia_module_init);
3298module_exit(ia_module_exit);