blob: 73e2f278093220e4bd3f8f5094c9ab55a1d190f5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * SDLA An implementation of a driver for the Sangoma S502/S508 series
3 * multi-protocol PC interface card. Initial offering is with
4 * the DLCI driver, providing Frame Relay support for linux.
5 *
6 * Global definitions for the Frame relay interface.
7 *
8 * Version: @(#)sdla.c 0.30 12 Sep 1996
9 *
10 * Credits: Sangoma Technologies, for the use of 2 cards for an extended
11 * period of time.
12 * David Mandelstam <dm@sangoma.com> for getting me started on
13 * this project, and incentive to complete it.
14 * Gene Kozen <74604.152@compuserve.com> for providing me with
15 * important information about the cards.
16 *
17 * Author: Mike McLagan <mike.mclagan@linux.org>
18 *
19 * Changes:
20 * 0.15 Mike McLagan Improved error handling, packet dropping
21 * 0.20 Mike McLagan New transmit/receive flags for config
22 * If in FR mode, don't accept packets from
23 * non DLCI devices.
24 * 0.25 Mike McLagan Fixed problem with rejecting packets
25 * from non DLCI devices.
26 * 0.30 Mike McLagan Fixed kernel panic when used with modified
27 * ifconfig
28 *
29 * This program is free software; you can redistribute it and/or
30 * modify it under the terms of the GNU General Public License
31 * as published by the Free Software Foundation; either version
32 * 2 of the License, or (at your option) any later version.
33 */
34
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/module.h>
36#include <linux/kernel.h>
37#include <linux/types.h>
38#include <linux/fcntl.h>
39#include <linux/interrupt.h>
40#include <linux/ptrace.h>
41#include <linux/ioport.h>
42#include <linux/in.h>
43#include <linux/slab.h>
44#include <linux/string.h>
45#include <linux/timer.h>
46#include <linux/errno.h>
47#include <linux/init.h>
48#include <linux/netdevice.h>
49#include <linux/skbuff.h>
50#include <linux/if_arp.h>
51#include <linux/if_frad.h>
52#include <linux/sdla.h>
53#include <linux/bitops.h>
54
55#include <asm/system.h>
56#include <asm/io.h>
57#include <asm/dma.h>
58#include <asm/uaccess.h>
59
60static const char* version = "SDLA driver v0.30, 12 Sep 1996, mike.mclagan@linux.org";
61
Randy Dunlap96ebb922006-06-25 05:48:37 -070062static unsigned int valid_port[] = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390};
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Randy Dunlap96ebb922006-06-25 05:48:37 -070064static unsigned int valid_mem[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
66 0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
67 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
68 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
69 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000};
70
71static DEFINE_SPINLOCK(sdla_lock);
72
73/*********************************************************
74 *
75 * these are the core routines that access the card itself
76 *
77 *********************************************************/
78
79#define SDLA_WINDOW(dev,addr) outb((((addr) >> 13) & 0x1F), (dev)->base_addr + SDLA_REG_Z80_WINDOW)
80
81static void __sdla_read(struct net_device *dev, int addr, void *buf, short len)
82{
83 char *temp;
84 const void *base;
85 int offset, bytes;
86
87 temp = buf;
88 while(len)
89 {
90 offset = addr & SDLA_ADDR_MASK;
91 bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len;
92 base = (const void *) (dev->mem_start + offset);
93
94 SDLA_WINDOW(dev, addr);
95 memcpy(temp, base, bytes);
96
97 addr += bytes;
98 temp += bytes;
99 len -= bytes;
100 }
101}
102
103static void sdla_read(struct net_device *dev, int addr, void *buf, short len)
104{
105 unsigned long flags;
106 spin_lock_irqsave(&sdla_lock, flags);
107 __sdla_read(dev, addr, buf, len);
108 spin_unlock_irqrestore(&sdla_lock, flags);
109}
110
111static void __sdla_write(struct net_device *dev, int addr,
112 const void *buf, short len)
113{
114 const char *temp;
115 void *base;
116 int offset, bytes;
117
118 temp = buf;
119 while(len)
120 {
121 offset = addr & SDLA_ADDR_MASK;
122 bytes = offset + len > SDLA_WINDOW_SIZE ? SDLA_WINDOW_SIZE - offset : len;
123 base = (void *) (dev->mem_start + offset);
124
125 SDLA_WINDOW(dev, addr);
126 memcpy(base, temp, bytes);
127
128 addr += bytes;
129 temp += bytes;
130 len -= bytes;
131 }
132}
133
134static void sdla_write(struct net_device *dev, int addr,
135 const void *buf, short len)
136{
137 unsigned long flags;
138
139 spin_lock_irqsave(&sdla_lock, flags);
140 __sdla_write(dev, addr, buf, len);
141 spin_unlock_irqrestore(&sdla_lock, flags);
142}
143
144
145static void sdla_clear(struct net_device *dev)
146{
147 unsigned long flags;
148 char *base;
149 int len, addr, bytes;
150
151 len = 65536;
152 addr = 0;
153 bytes = SDLA_WINDOW_SIZE;
154 base = (void *) dev->mem_start;
155
156 spin_lock_irqsave(&sdla_lock, flags);
157 while(len)
158 {
159 SDLA_WINDOW(dev, addr);
160 memset(base, 0, bytes);
161
162 addr += bytes;
163 len -= bytes;
164 }
165 spin_unlock_irqrestore(&sdla_lock, flags);
166
167}
168
169static char sdla_byte(struct net_device *dev, int addr)
170{
171 unsigned long flags;
172 char byte, *temp;
173
174 temp = (void *) (dev->mem_start + (addr & SDLA_ADDR_MASK));
175
176 spin_lock_irqsave(&sdla_lock, flags);
177 SDLA_WINDOW(dev, addr);
178 byte = *temp;
179 spin_unlock_irqrestore(&sdla_lock, flags);
180
181 return(byte);
182}
183
Adrian Bunk7665a082005-09-09 23:17:28 -0700184static void sdla_stop(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185{
186 struct frad_local *flp;
187
188 flp = dev->priv;
189 switch(flp->type)
190 {
191 case SDLA_S502A:
192 outb(SDLA_S502A_HALT, dev->base_addr + SDLA_REG_CONTROL);
193 flp->state = SDLA_HALT;
194 break;
195 case SDLA_S502E:
196 outb(SDLA_HALT, dev->base_addr + SDLA_REG_Z80_CONTROL);
197 outb(SDLA_S502E_ENABLE, dev->base_addr + SDLA_REG_CONTROL);
198 flp->state = SDLA_S502E_ENABLE;
199 break;
200 case SDLA_S507:
201 flp->state &= ~SDLA_CPUEN;
202 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
203 break;
204 case SDLA_S508:
205 flp->state &= ~SDLA_CPUEN;
206 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
207 break;
208 }
209}
210
Adrian Bunk7665a082005-09-09 23:17:28 -0700211static void sdla_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212{
213 struct frad_local *flp;
214
215 flp = dev->priv;
216 switch(flp->type)
217 {
218 case SDLA_S502A:
219 outb(SDLA_S502A_NMI, dev->base_addr + SDLA_REG_CONTROL);
220 outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL);
221 flp->state = SDLA_S502A_START;
222 break;
223 case SDLA_S502E:
224 outb(SDLA_S502E_CPUEN, dev->base_addr + SDLA_REG_Z80_CONTROL);
225 outb(0x00, dev->base_addr + SDLA_REG_CONTROL);
226 flp->state = 0;
227 break;
228 case SDLA_S507:
229 flp->state |= SDLA_CPUEN;
230 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
231 break;
232 case SDLA_S508:
233 flp->state |= SDLA_CPUEN;
234 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
235 break;
236 }
237}
238
239/****************************************************
240 *
241 * this is used for the S502A/E cards to determine
242 * the speed of the onboard CPU. Calibration is
243 * necessary for the Frame Relay code uploaded
244 * later. Incorrect results cause timing problems
245 * with link checks & status messages
246 *
247 ***************************************************/
248
Adrian Bunk7665a082005-09-09 23:17:28 -0700249static int sdla_z80_poll(struct net_device *dev, int z80_addr, int jiffs, char resp1, char resp2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250{
251 unsigned long start, done, now;
252 char resp, *temp;
253
254 start = now = jiffies;
255 done = jiffies + jiffs;
256
257 temp = (void *)dev->mem_start;
258 temp += z80_addr & SDLA_ADDR_MASK;
259
260 resp = ~resp1;
261 while (time_before(jiffies, done) && (resp != resp1) && (!resp2 || (resp != resp2)))
262 {
263 if (jiffies != now)
264 {
265 SDLA_WINDOW(dev, z80_addr);
266 now = jiffies;
267 resp = *temp;
268 }
269 }
270 return(time_before(jiffies, done) ? jiffies - start : -1);
271}
272
273/* constants for Z80 CPU speed */
274#define Z80_READY '1' /* Z80 is ready to begin */
275#define LOADER_READY '2' /* driver is ready to begin */
276#define Z80_SCC_OK '3' /* SCC is on board */
277#define Z80_SCC_BAD '4' /* SCC was not found */
278
279static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr)
280{
281 int jiffs;
282 char data;
283
284 sdla_start(dev);
285 if (sdla_z80_poll(dev, 0, 3*HZ, Z80_READY, 0) < 0)
286 return(-EIO);
287
288 data = LOADER_READY;
289 sdla_write(dev, 0, &data, 1);
290
291 if ((jiffs = sdla_z80_poll(dev, 0, 8*HZ, Z80_SCC_OK, Z80_SCC_BAD)) < 0)
292 return(-EIO);
293
294 sdla_stop(dev);
295 sdla_read(dev, 0, &data, 1);
296
297 if (data == Z80_SCC_BAD)
298 {
299 printk("%s: SCC bad\n", dev->name);
300 return(-EIO);
301 }
302
303 if (data != Z80_SCC_OK)
304 return(-EINVAL);
305
306 if (jiffs < 165)
307 ifr->ifr_mtu = SDLA_CPU_16M;
308 else if (jiffs < 220)
309 ifr->ifr_mtu = SDLA_CPU_10M;
310 else if (jiffs < 258)
311 ifr->ifr_mtu = SDLA_CPU_8M;
312 else if (jiffs < 357)
313 ifr->ifr_mtu = SDLA_CPU_7M;
314 else if (jiffs < 467)
315 ifr->ifr_mtu = SDLA_CPU_5M;
316 else
317 ifr->ifr_mtu = SDLA_CPU_3M;
318
319 return(0);
320}
321
322/************************************************
323 *
324 * Direct interaction with the Frame Relay code
325 * starts here.
326 *
327 ************************************************/
328
329struct _dlci_stat
330{
Jan Blunck6a878182006-01-08 01:05:07 -0800331 short dlci;
332 char flags;
333} __attribute__((packed));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335struct _frad_stat
336{
337 char flags;
338 struct _dlci_stat dlcis[SDLA_MAX_DLCI];
339};
340
341static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int len, void *data)
342{
343 struct _dlci_stat *pstatus;
344 short *pdlci;
345 int i;
346 char *state, line[30];
347
348 switch (ret)
349 {
350 case SDLA_RET_MODEM:
351 state = data;
352 if (*state & SDLA_MODEM_DCD_LOW)
353 printk(KERN_INFO "%s: Modem DCD unexpectedly low!\n", dev->name);
354 if (*state & SDLA_MODEM_CTS_LOW)
355 printk(KERN_INFO "%s: Modem CTS unexpectedly low!\n", dev->name);
356 /* I should probably do something about this! */
357 break;
358
359 case SDLA_RET_CHANNEL_OFF:
360 printk(KERN_INFO "%s: Channel became inoperative!\n", dev->name);
361 /* same here */
362 break;
363
364 case SDLA_RET_CHANNEL_ON:
365 printk(KERN_INFO "%s: Channel became operative!\n", dev->name);
366 /* same here */
367 break;
368
369 case SDLA_RET_DLCI_STATUS:
370 printk(KERN_INFO "%s: Status change reported by Access Node.\n", dev->name);
371 len /= sizeof(struct _dlci_stat);
372 for(pstatus = data, i=0;i < len;i++,pstatus++)
373 {
374 if (pstatus->flags & SDLA_DLCI_NEW)
375 state = "new";
376 else if (pstatus->flags & SDLA_DLCI_DELETED)
377 state = "deleted";
378 else if (pstatus->flags & SDLA_DLCI_ACTIVE)
379 state = "active";
380 else
381 {
382 sprintf(line, "unknown status: %02X", pstatus->flags);
383 state = line;
384 }
385 printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
386 /* same here */
387 }
388 break;
389
390 case SDLA_RET_DLCI_UNKNOWN:
391 printk(KERN_INFO "%s: Received unknown DLCIs:", dev->name);
392 len /= sizeof(short);
393 for(pdlci = data,i=0;i < len;i++,pdlci++)
394 printk(" %i", *pdlci);
395 printk("\n");
396 break;
397
398 case SDLA_RET_TIMEOUT:
399 printk(KERN_ERR "%s: Command timed out!\n", dev->name);
400 break;
401
402 case SDLA_RET_BUF_OVERSIZE:
403 printk(KERN_INFO "%s: Bc/CIR overflow, acceptable size is %i\n", dev->name, len);
404 break;
405
406 case SDLA_RET_BUF_TOO_BIG:
407 printk(KERN_INFO "%s: Buffer size over specified max of %i\n", dev->name, len);
408 break;
409
410 case SDLA_RET_CHANNEL_INACTIVE:
411 case SDLA_RET_DLCI_INACTIVE:
412 case SDLA_RET_CIR_OVERFLOW:
413 case SDLA_RET_NO_BUFS:
414 if (cmd == SDLA_INFORMATION_WRITE)
415 break;
416
417 default:
418 printk(KERN_DEBUG "%s: Cmd 0x%2.2X generated return code 0x%2.2X\n", dev->name, cmd, ret);
419 /* Further processing could be done here */
420 break;
421 }
422}
423
424static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
425 void *inbuf, short inlen, void *outbuf, short *outlen)
426{
427 static struct _frad_stat status;
428 struct frad_local *flp;
429 struct sdla_cmd *cmd_buf;
430 unsigned long pflags;
431 unsigned long jiffs;
432 int ret, waiting, len;
433 long window;
434
435 flp = dev->priv;
436 window = flp->type == SDLA_S508 ? SDLA_508_CMD_BUF : SDLA_502_CMD_BUF;
437 cmd_buf = (struct sdla_cmd *)(dev->mem_start + (window & SDLA_ADDR_MASK));
438 ret = 0;
439 len = 0;
440 jiffs = jiffies + HZ; /* 1 second is plenty */
441
442 spin_lock_irqsave(&sdla_lock, pflags);
443 SDLA_WINDOW(dev, window);
444 cmd_buf->cmd = cmd;
445 cmd_buf->dlci = dlci;
446 cmd_buf->flags = flags;
447
448 if (inbuf)
449 memcpy(cmd_buf->data, inbuf, inlen);
450
451 cmd_buf->length = inlen;
452
453 cmd_buf->opp_flag = 1;
454 spin_unlock_irqrestore(&sdla_lock, pflags);
455
456 waiting = 1;
457 len = 0;
458 while (waiting && time_before_eq(jiffies, jiffs))
459 {
460 if (waiting++ % 3)
461 {
462 spin_lock_irqsave(&sdla_lock, pflags);
463 SDLA_WINDOW(dev, window);
464 waiting = ((volatile int)(cmd_buf->opp_flag));
465 spin_unlock_irqrestore(&sdla_lock, pflags);
466 }
467 }
468
469 if (!waiting)
470 {
471
472 spin_lock_irqsave(&sdla_lock, pflags);
473 SDLA_WINDOW(dev, window);
474 ret = cmd_buf->retval;
475 len = cmd_buf->length;
476 if (outbuf && outlen)
477 {
478 *outlen = *outlen >= len ? len : *outlen;
479
480 if (*outlen)
481 memcpy(outbuf, cmd_buf->data, *outlen);
482 }
483
484 /* This is a local copy that's used for error handling */
485 if (ret)
486 memcpy(&status, cmd_buf->data, len > sizeof(status) ? sizeof(status) : len);
487
488 spin_unlock_irqrestore(&sdla_lock, pflags);
489 }
490 else
491 ret = SDLA_RET_TIMEOUT;
492
493 if (ret != SDLA_RET_OK)
494 sdla_errors(dev, cmd, dlci, ret, len, &status);
495
496 return(ret);
497}
498
499/***********************************************
500 *
501 * these functions are called by the DLCI driver
502 *
503 ***********************************************/
504
505static int sdla_reconfig(struct net_device *dev);
506
Adrian Bunk7665a082005-09-09 23:17:28 -0700507static int sdla_activate(struct net_device *slave, struct net_device *master)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508{
509 struct frad_local *flp;
510 int i;
511
512 flp = slave->priv;
513
514 for(i=0;i<CONFIG_DLCI_MAX;i++)
515 if (flp->master[i] == master)
516 break;
517
518 if (i == CONFIG_DLCI_MAX)
519 return(-ENODEV);
520
521 flp->dlci[i] = abs(flp->dlci[i]);
522
523 if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
524 sdla_cmd(slave, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
525
526 return(0);
527}
528
Adrian Bunk7665a082005-09-09 23:17:28 -0700529static int sdla_deactivate(struct net_device *slave, struct net_device *master)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 struct frad_local *flp;
532 int i;
533
534 flp = slave->priv;
535
536 for(i=0;i<CONFIG_DLCI_MAX;i++)
537 if (flp->master[i] == master)
538 break;
539
540 if (i == CONFIG_DLCI_MAX)
541 return(-ENODEV);
542
543 flp->dlci[i] = -abs(flp->dlci[i]);
544
545 if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
546 sdla_cmd(slave, SDLA_DEACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
547
548 return(0);
549}
550
Adrian Bunk7665a082005-09-09 23:17:28 -0700551static int sdla_assoc(struct net_device *slave, struct net_device *master)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552{
553 struct frad_local *flp;
554 int i;
555
556 if (master->type != ARPHRD_DLCI)
557 return(-EINVAL);
558
559 flp = slave->priv;
560
561 for(i=0;i<CONFIG_DLCI_MAX;i++)
562 {
563 if (!flp->master[i])
564 break;
565 if (abs(flp->dlci[i]) == *(short *)(master->dev_addr))
566 return(-EADDRINUSE);
567 }
568
569 if (i == CONFIG_DLCI_MAX)
570 return(-EMLINK); /* #### Alan: Comments on this ?? */
571
572
573 flp->master[i] = master;
574 flp->dlci[i] = -*(short *)(master->dev_addr);
575 master->mtu = slave->mtu;
576
577 if (netif_running(slave)) {
578 if (flp->config.station == FRAD_STATION_CPE)
579 sdla_reconfig(slave);
580 else
581 sdla_cmd(slave, SDLA_ADD_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);
582 }
583
584 return(0);
585}
586
Adrian Bunk7665a082005-09-09 23:17:28 -0700587static int sdla_deassoc(struct net_device *slave, struct net_device *master)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588{
589 struct frad_local *flp;
590 int i;
591
592 flp = slave->priv;
593
594 for(i=0;i<CONFIG_DLCI_MAX;i++)
595 if (flp->master[i] == master)
596 break;
597
598 if (i == CONFIG_DLCI_MAX)
599 return(-ENODEV);
600
601 flp->master[i] = NULL;
602 flp->dlci[i] = 0;
603
604
605 if (netif_running(slave)) {
606 if (flp->config.station == FRAD_STATION_CPE)
607 sdla_reconfig(slave);
608 else
609 sdla_cmd(slave, SDLA_DELETE_DLCI, 0, 0, master->dev_addr, sizeof(short), NULL, NULL);
610 }
611
612 return(0);
613}
614
Adrian Bunk7665a082005-09-09 23:17:28 -0700615static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616{
617 struct frad_local *flp;
618 struct dlci_local *dlp;
619 int i;
620 short len, ret;
621
622 flp = slave->priv;
623
624 for(i=0;i<CONFIG_DLCI_MAX;i++)
625 if (flp->master[i] == master)
626 break;
627
628 if (i == CONFIG_DLCI_MAX)
629 return(-ENODEV);
630
631 dlp = master->priv;
632
633 ret = SDLA_RET_OK;
634 len = sizeof(struct dlci_conf);
635 if (netif_running(slave)) {
636 if (get)
637 ret = sdla_cmd(slave, SDLA_READ_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0,
638 NULL, 0, &dlp->config, &len);
639 else
640 ret = sdla_cmd(slave, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0,
641 &dlp->config, sizeof(struct dlci_conf) - 4 * sizeof(short), NULL, NULL);
642 }
643
644 return(ret == SDLA_RET_OK ? 0 : -EIO);
645}
646
647/**************************
648 *
649 * now for the Linux driver
650 *
651 **************************/
652
653/* NOTE: the DLCI driver deals with freeing the SKB!! */
654static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
655{
656 struct frad_local *flp;
657 int ret, addr, accept, i;
658 short size;
659 unsigned long flags;
660 struct buf_entry *pbuf;
661
662 flp = dev->priv;
663 ret = 0;
664 accept = 1;
665
666 netif_stop_queue(dev);
667
668 /*
669 * stupid GateD insists on setting up the multicast router thru us
670 * and we're ill equipped to handle a non Frame Relay packet at this
671 * time!
672 */
673
674 accept = 1;
675 switch (dev->type)
676 {
677 case ARPHRD_FRAD:
678 if (skb->dev->type != ARPHRD_DLCI)
679 {
680 printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
681 accept = 0;
682 }
683 break;
684 default:
685 printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
686 accept = 0;
687 break;
688 }
689 if (accept)
690 {
691 /* this is frame specific, but till there's a PPP module, it's the default */
692 switch (flp->type)
693 {
694 case SDLA_S502A:
695 case SDLA_S502E:
696 ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);
697 break;
698 case SDLA_S508:
699 size = sizeof(addr);
700 ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
701 if (ret == SDLA_RET_OK)
702 {
703
704 spin_lock_irqsave(&sdla_lock, flags);
705 SDLA_WINDOW(dev, addr);
706 pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
707 __sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
708 SDLA_WINDOW(dev, addr);
709 pbuf->opp_flag = 1;
710 spin_unlock_irqrestore(&sdla_lock, flags);
711 }
712 break;
713 }
714 switch (ret)
715 {
716 case SDLA_RET_OK:
717 flp->stats.tx_packets++;
718 ret = DLCI_RET_OK;
719 break;
720
721 case SDLA_RET_CIR_OVERFLOW:
722 case SDLA_RET_BUF_OVERSIZE:
723 case SDLA_RET_NO_BUFS:
724 flp->stats.tx_dropped++;
725 ret = DLCI_RET_DROP;
726 break;
727
728 default:
729 flp->stats.tx_errors++;
730 ret = DLCI_RET_ERR;
731 break;
732 }
733 }
734 netif_wake_queue(dev);
735 for(i=0;i<CONFIG_DLCI_MAX;i++)
736 {
737 if(flp->master[i]!=NULL)
738 netif_wake_queue(flp->master[i]);
739 }
740 return(ret);
741}
742
743static void sdla_receive(struct net_device *dev)
744{
745 struct net_device *master;
746 struct frad_local *flp;
747 struct dlci_local *dlp;
748 struct sk_buff *skb;
749
750 struct sdla_cmd *cmd;
751 struct buf_info *pbufi;
752 struct buf_entry *pbuf;
753
754 unsigned long flags;
755 int i=0, received, success, addr, buf_base, buf_top;
756 short dlci, len, len2, split;
757
758 flp = dev->priv;
759 success = 1;
760 received = addr = buf_top = buf_base = 0;
761 len = dlci = 0;
762 skb = NULL;
763 master = NULL;
764 cmd = NULL;
765 pbufi = NULL;
766 pbuf = NULL;
767
768 spin_lock_irqsave(&sdla_lock, flags);
769
770 switch (flp->type)
771 {
772 case SDLA_S502A:
773 case SDLA_S502E:
774 cmd = (void *) (dev->mem_start + (SDLA_502_RCV_BUF & SDLA_ADDR_MASK));
775 SDLA_WINDOW(dev, SDLA_502_RCV_BUF);
776 success = cmd->opp_flag;
777 if (!success)
778 break;
779
780 dlci = cmd->dlci;
781 len = cmd->length;
782 break;
783
784 case SDLA_S508:
785 pbufi = (void *) (dev->mem_start + (SDLA_508_RXBUF_INFO & SDLA_ADDR_MASK));
786 SDLA_WINDOW(dev, SDLA_508_RXBUF_INFO);
787 pbuf = (void *) (dev->mem_start + ((pbufi->rse_base + flp->buffer * sizeof(struct buf_entry)) & SDLA_ADDR_MASK));
788 success = pbuf->opp_flag;
789 if (!success)
790 break;
791
792 buf_top = pbufi->buf_top;
793 buf_base = pbufi->buf_base;
794 dlci = pbuf->dlci;
795 len = pbuf->length;
796 addr = pbuf->buf_addr;
797 break;
798 }
799
800 /* common code, find the DLCI and get the SKB */
801 if (success)
802 {
803 for (i=0;i<CONFIG_DLCI_MAX;i++)
804 if (flp->dlci[i] == dlci)
805 break;
806
807 if (i == CONFIG_DLCI_MAX)
808 {
809 printk(KERN_NOTICE "%s: Received packet from invalid DLCI %i, ignoring.", dev->name, dlci);
810 flp->stats.rx_errors++;
811 success = 0;
812 }
813 }
814
815 if (success)
816 {
817 master = flp->master[i];
818 skb = dev_alloc_skb(len + sizeof(struct frhdr));
819 if (skb == NULL)
820 {
821 printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
822 flp->stats.rx_dropped++;
823 success = 0;
824 }
825 else
826 skb_reserve(skb, sizeof(struct frhdr));
827 }
828
829 /* pick up the data */
830 switch (flp->type)
831 {
832 case SDLA_S502A:
833 case SDLA_S502E:
834 if (success)
835 __sdla_read(dev, SDLA_502_RCV_BUF + SDLA_502_DATA_OFS, skb_put(skb,len), len);
836
837 SDLA_WINDOW(dev, SDLA_502_RCV_BUF);
838 cmd->opp_flag = 0;
839 break;
840
841 case SDLA_S508:
842 if (success)
843 {
844 /* is this buffer split off the end of the internal ring buffer */
845 split = addr + len > buf_top + 1 ? len - (buf_top - addr + 1) : 0;
846 len2 = len - split;
847
848 __sdla_read(dev, addr, skb_put(skb, len2), len2);
849 if (split)
850 __sdla_read(dev, buf_base, skb_put(skb, split), split);
851 }
852
853 /* increment the buffer we're looking at */
854 SDLA_WINDOW(dev, SDLA_508_RXBUF_INFO);
855 flp->buffer = (flp->buffer + 1) % pbufi->rse_num;
856 pbuf->opp_flag = 0;
857 break;
858 }
859
860 if (success)
861 {
862 flp->stats.rx_packets++;
863 dlp = master->priv;
864 (*dlp->receive)(skb, master);
865 }
866
867 spin_unlock_irqrestore(&sdla_lock, flags);
868}
869
Jeff Garzik28fc1f52007-10-29 05:46:16 -0400870static irqreturn_t sdla_isr(int dummy, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871{
872 struct net_device *dev;
873 struct frad_local *flp;
874 char byte;
875
876 dev = dev_id;
877
Jeff Garzikc31f28e2006-10-06 14:56:04 -0400878 flp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
880 if (!flp->initialized)
881 {
Jeff Garzik28fc1f52007-10-29 05:46:16 -0400882 printk(KERN_WARNING "%s: irq %d for uninitialized device.\n",
883 dev->name, dev->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 return IRQ_NONE;
885 }
886
887 byte = sdla_byte(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE);
888 switch (byte)
889 {
890 case SDLA_INTR_RX:
891 sdla_receive(dev);
892 break;
893
894 /* the command will get an error return, which is processed above */
895 case SDLA_INTR_MODEM:
896 case SDLA_INTR_STATUS:
897 sdla_cmd(dev, SDLA_READ_DLC_STATUS, 0, 0, NULL, 0, NULL, NULL);
898 break;
899
900 case SDLA_INTR_TX:
901 case SDLA_INTR_COMPLETE:
902 case SDLA_INTR_TIMER:
903 printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte);
904 break;
905 }
906
907 /* the S502E requires a manual acknowledgement of the interrupt */
908 if (flp->type == SDLA_S502E)
909 {
910 flp->state &= ~SDLA_S502E_INTACK;
911 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
912 flp->state |= SDLA_S502E_INTACK;
913 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
914 }
915
916 /* this clears the byte, informing the Z80 we're done */
917 byte = 0;
918 sdla_write(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));
919 return IRQ_HANDLED;
920}
921
922static void sdla_poll(unsigned long device)
923{
924 struct net_device *dev;
925 struct frad_local *flp;
926
927 dev = (struct net_device *) device;
928 flp = dev->priv;
929
930 if (sdla_byte(dev, SDLA_502_RCV_BUF))
931 sdla_receive(dev);
932
933 flp->timer.expires = 1;
934 add_timer(&flp->timer);
935}
936
937static int sdla_close(struct net_device *dev)
938{
939 struct frad_local *flp;
940 struct intr_info intr;
941 int len, i;
942 short dlcis[CONFIG_DLCI_MAX];
943
944 flp = dev->priv;
945
946 len = 0;
947 for(i=0;i<CONFIG_DLCI_MAX;i++)
948 if (flp->dlci[i])
949 dlcis[len++] = abs(flp->dlci[i]);
950 len *= 2;
951
952 if (flp->config.station == FRAD_STATION_NODE)
953 {
954 for(i=0;i<CONFIG_DLCI_MAX;i++)
955 if (flp->dlci[i] > 0)
956 sdla_cmd(dev, SDLA_DEACTIVATE_DLCI, 0, 0, dlcis, len, NULL, NULL);
957 sdla_cmd(dev, SDLA_DELETE_DLCI, 0, 0, &flp->dlci[i], sizeof(flp->dlci[i]), NULL, NULL);
958 }
959
960 memset(&intr, 0, sizeof(intr));
961 /* let's start up the reception */
962 switch(flp->type)
963 {
964 case SDLA_S502A:
965 del_timer(&flp->timer);
966 break;
967
968 case SDLA_S502E:
969 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(char) + sizeof(short), NULL, NULL);
970 flp->state &= ~SDLA_S502E_INTACK;
971 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
972 break;
973
974 case SDLA_S507:
975 break;
976
977 case SDLA_S508:
978 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(struct intr_info), NULL, NULL);
979 flp->state &= ~SDLA_S508_INTEN;
980 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
981 break;
982 }
983
984 sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
985
986 netif_stop_queue(dev);
987
988 return(0);
989}
990
991struct conf_data {
992 struct frad_conf config;
993 short dlci[CONFIG_DLCI_MAX];
994};
995
996static int sdla_open(struct net_device *dev)
997{
998 struct frad_local *flp;
999 struct dlci_local *dlp;
1000 struct conf_data data;
1001 struct intr_info intr;
1002 int len, i;
1003 char byte;
1004
1005 flp = dev->priv;
1006
1007 if (!flp->initialized)
1008 return(-EPERM);
1009
1010 if (!flp->configured)
1011 return(-EPERM);
1012
1013 /* time to send in the configuration */
1014 len = 0;
1015 for(i=0;i<CONFIG_DLCI_MAX;i++)
1016 if (flp->dlci[i])
1017 data.dlci[len++] = abs(flp->dlci[i]);
1018 len *= 2;
1019
1020 memcpy(&data.config, &flp->config, sizeof(struct frad_conf));
1021 len += sizeof(struct frad_conf);
1022
1023 sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1024 sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL);
1025
1026 if (flp->type == SDLA_S508)
1027 flp->buffer = 0;
1028
1029 sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1030
1031 /* let's start up the reception */
1032 memset(&intr, 0, sizeof(intr));
1033 switch(flp->type)
1034 {
1035 case SDLA_S502A:
1036 flp->timer.expires = 1;
1037 add_timer(&flp->timer);
1038 break;
1039
1040 case SDLA_S502E:
1041 flp->state |= SDLA_S502E_ENABLE;
1042 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
1043 flp->state |= SDLA_S502E_INTACK;
1044 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
1045 byte = 0;
1046 sdla_write(dev, SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));
1047 intr.flags = SDLA_INTR_RX | SDLA_INTR_STATUS | SDLA_INTR_MODEM;
1048 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(char) + sizeof(short), NULL, NULL);
1049 break;
1050
1051 case SDLA_S507:
1052 break;
1053
1054 case SDLA_S508:
1055 flp->state |= SDLA_S508_INTEN;
1056 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
1057 byte = 0;
1058 sdla_write(dev, SDLA_508_IRQ_INTERFACE, &byte, sizeof(byte));
1059 intr.flags = SDLA_INTR_RX | SDLA_INTR_STATUS | SDLA_INTR_MODEM;
1060 intr.irq = dev->irq;
1061 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(struct intr_info), NULL, NULL);
1062 break;
1063 }
1064
1065 if (flp->config.station == FRAD_STATION_CPE)
1066 {
1067 byte = SDLA_ICS_STATUS_ENQ;
1068 sdla_cmd(dev, SDLA_ISSUE_IN_CHANNEL_SIGNAL, 0, 0, &byte, sizeof(byte), NULL, NULL);
1069 }
1070 else
1071 {
1072 sdla_cmd(dev, SDLA_ADD_DLCI, 0, 0, data.dlci, len - sizeof(struct frad_conf), NULL, NULL);
1073 for(i=0;i<CONFIG_DLCI_MAX;i++)
1074 if (flp->dlci[i] > 0)
1075 sdla_cmd(dev, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], 2*sizeof(flp->dlci[i]), NULL, NULL);
1076 }
1077
1078 /* configure any specific DLCI settings */
1079 for(i=0;i<CONFIG_DLCI_MAX;i++)
1080 if (flp->dlci[i])
1081 {
1082 dlp = flp->master[i]->priv;
1083 if (dlp->configured)
1084 sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf), NULL, NULL);
1085 }
1086
1087 netif_start_queue(dev);
1088
1089 return(0);
1090}
1091
1092static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, int get)
1093{
1094 struct frad_local *flp;
1095 struct conf_data data;
1096 int i;
1097 short size;
1098
1099 if (dev->type == 0xFFFF)
1100 return(-EUNATCH);
1101
1102 flp = dev->priv;
1103
1104 if (!get)
1105 {
1106 if (netif_running(dev))
1107 return(-EBUSY);
1108
1109 if(copy_from_user(&data.config, conf, sizeof(struct frad_conf)))
1110 return -EFAULT;
1111
1112 if (data.config.station & ~FRAD_STATION_NODE)
1113 return(-EINVAL);
1114
1115 if (data.config.flags & ~FRAD_VALID_FLAGS)
1116 return(-EINVAL);
1117
1118 if ((data.config.kbaud < 0) ||
1119 ((data.config.kbaud > 128) && (flp->type != SDLA_S508)))
1120 return(-EINVAL);
1121
1122 if (data.config.clocking & ~(FRAD_CLOCK_INT | SDLA_S508_PORT_RS232))
1123 return(-EINVAL);
1124
1125 if ((data.config.mtu < 0) || (data.config.mtu > SDLA_MAX_MTU))
1126 return(-EINVAL);
1127
1128 if ((data.config.T391 < 5) || (data.config.T391 > 30))
1129 return(-EINVAL);
1130
1131 if ((data.config.T392 < 5) || (data.config.T392 > 30))
1132 return(-EINVAL);
1133
1134 if ((data.config.N391 < 1) || (data.config.N391 > 255))
1135 return(-EINVAL);
1136
1137 if ((data.config.N392 < 1) || (data.config.N392 > 10))
1138 return(-EINVAL);
1139
1140 if ((data.config.N393 < 1) || (data.config.N393 > 10))
1141 return(-EINVAL);
1142
1143 memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
1144 flp->config.flags |= SDLA_DIRECT_RECV;
1145
1146 if (flp->type == SDLA_S508)
1147 flp->config.flags |= SDLA_TX70_RX30;
1148
1149 if (dev->mtu != flp->config.mtu)
1150 {
1151 /* this is required to change the MTU */
1152 dev->mtu = flp->config.mtu;
1153 for(i=0;i<CONFIG_DLCI_MAX;i++)
1154 if (flp->master[i])
1155 flp->master[i]->mtu = flp->config.mtu;
1156 }
1157
1158 flp->config.mtu += sizeof(struct frhdr);
1159
1160 /* off to the races! */
1161 if (!flp->configured)
1162 sdla_start(dev);
1163
1164 flp->configured = 1;
1165 }
1166 else
1167 {
1168 /* no sense reading if the CPU isn't started */
1169 if (netif_running(dev))
1170 {
1171 size = sizeof(data);
1172 if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)
1173 return(-EIO);
1174 }
1175 else
1176 if (flp->configured)
1177 memcpy(&data.config, &flp->config, sizeof(struct frad_conf));
1178 else
1179 memset(&data.config, 0, sizeof(struct frad_conf));
1180
1181 memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
1182 data.config.flags &= FRAD_VALID_FLAGS;
1183 data.config.mtu -= data.config.mtu > sizeof(struct frhdr) ? sizeof(struct frhdr) : data.config.mtu;
1184 return copy_to_user(conf, &data.config, sizeof(struct frad_conf))?-EFAULT:0;
1185 }
1186
1187 return(0);
1188}
1189
1190static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int read)
1191{
1192 struct sdla_mem mem;
1193 char *temp;
1194
1195 if(copy_from_user(&mem, info, sizeof(mem)))
1196 return -EFAULT;
1197
1198 if (read)
1199 {
Yoann Padioleaudd00cc42007-07-19 01:49:03 -07001200 temp = kzalloc(mem.len, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 if (!temp)
1202 return(-ENOMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 sdla_read(dev, mem.addr, temp, mem.len);
1204 if(copy_to_user(mem.data, temp, mem.len))
1205 {
1206 kfree(temp);
1207 return -EFAULT;
1208 }
1209 kfree(temp);
1210 }
1211 else
1212 {
1213 temp = kmalloc(mem.len, GFP_KERNEL);
1214 if (!temp)
1215 return(-ENOMEM);
1216 if(copy_from_user(temp, mem.data, mem.len))
1217 {
1218 kfree(temp);
1219 return -EFAULT;
1220 }
1221 sdla_write(dev, mem.addr, temp, mem.len);
1222 kfree(temp);
1223 }
1224 return(0);
1225}
1226
1227static int sdla_reconfig(struct net_device *dev)
1228{
1229 struct frad_local *flp;
1230 struct conf_data data;
1231 int i, len;
1232
1233 flp = dev->priv;
1234
1235 len = 0;
1236 for(i=0;i<CONFIG_DLCI_MAX;i++)
1237 if (flp->dlci[i])
1238 data.dlci[len++] = flp->dlci[i];
1239 len *= 2;
1240
1241 memcpy(&data, &flp->config, sizeof(struct frad_conf));
1242 len += sizeof(struct frad_conf);
1243
1244 sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1245 sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL);
1246 sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1247
1248 return(0);
1249}
1250
1251static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1252{
1253 struct frad_local *flp;
1254
1255 if(!capable(CAP_NET_ADMIN))
1256 return -EPERM;
1257
1258 flp = dev->priv;
1259
1260 if (!flp->initialized)
1261 return(-EINVAL);
1262
1263 switch (cmd)
1264 {
1265 case FRAD_GET_CONF:
1266 case FRAD_SET_CONF:
1267 return(sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF));
1268
1269 case SDLA_IDENTIFY:
1270 ifr->ifr_flags = flp->type;
1271 break;
1272
1273 case SDLA_CPUSPEED:
1274 return(sdla_cpuspeed(dev, ifr));
1275
1276/* ==========================================================
1277NOTE: This is rather a useless action right now, as the
1278 current driver does not support protocols other than
1279 FR. However, Sangoma has modules for a number of
1280 other protocols in the works.
1281============================================================*/
1282 case SDLA_PROTOCOL:
1283 if (flp->configured)
1284 return(-EALREADY);
1285
1286 switch (ifr->ifr_flags)
1287 {
1288 case ARPHRD_FRAD:
1289 dev->type = ifr->ifr_flags;
1290 break;
1291 default:
1292 return(-ENOPROTOOPT);
1293 }
1294 break;
1295
1296 case SDLA_CLEARMEM:
1297 sdla_clear(dev);
1298 break;
1299
1300 case SDLA_WRITEMEM:
1301 case SDLA_READMEM:
1302 if(!capable(CAP_SYS_RAWIO))
1303 return -EPERM;
1304 return(sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM));
1305
1306 case SDLA_START:
1307 sdla_start(dev);
1308 break;
1309
1310 case SDLA_STOP:
1311 sdla_stop(dev);
1312 break;
1313
1314 default:
1315 return(-EOPNOTSUPP);
1316 }
1317 return(0);
1318}
1319
Adrian Bunk7665a082005-09-09 23:17:28 -07001320static int sdla_change_mtu(struct net_device *dev, int new_mtu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321{
1322 struct frad_local *flp;
1323
1324 flp = dev->priv;
1325
1326 if (netif_running(dev))
1327 return(-EBUSY);
1328
1329 /* for now, you can't change the MTU! */
1330 return(-EOPNOTSUPP);
1331}
1332
Adrian Bunk7665a082005-09-09 23:17:28 -07001333static int sdla_set_config(struct net_device *dev, struct ifmap *map)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
1335 struct frad_local *flp;
1336 int i;
1337 char byte;
1338 unsigned base;
1339 int err = -EINVAL;
1340
1341 flp = dev->priv;
1342
1343 if (flp->initialized)
1344 return(-EINVAL);
1345
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001346 for(i=0; i < ARRAY_SIZE(valid_port); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 if (valid_port[i] == map->base_addr)
1348 break;
1349
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001350 if (i == ARRAY_SIZE(valid_port))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 return(-EINVAL);
1352
1353 if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
1354 printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr);
1355 return(-EINVAL);
1356 }
1357 base = map->base_addr;
1358
1359 /* test for card types, S502A, S502E, S507, S508 */
1360 /* these tests shut down the card completely, so clear the state */
1361 flp->type = SDLA_UNKNOWN;
1362 flp->state = 0;
1363
1364 for(i=1;i<SDLA_IO_EXTENTS;i++)
1365 if (inb(base + i) != 0xFF)
1366 break;
1367
1368 if (i == SDLA_IO_EXTENTS) {
1369 outb(SDLA_HALT, base + SDLA_REG_Z80_CONTROL);
1370 if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x08) {
1371 outb(SDLA_S502E_INTACK, base + SDLA_REG_CONTROL);
1372 if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x0C) {
1373 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1374 flp->type = SDLA_S502E;
1375 goto got_type;
1376 }
1377 }
1378 }
1379
1380 for(byte=inb(base),i=0;i<SDLA_IO_EXTENTS;i++)
1381 if (inb(base + i) != byte)
1382 break;
1383
1384 if (i == SDLA_IO_EXTENTS) {
1385 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1386 if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x30) {
1387 outb(SDLA_S507_ENABLE, base + SDLA_REG_CONTROL);
1388 if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x32) {
1389 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1390 flp->type = SDLA_S507;
1391 goto got_type;
1392 }
1393 }
1394 }
1395
1396 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1397 if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x00) {
1398 outb(SDLA_S508_INTEN, base + SDLA_REG_CONTROL);
1399 if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x10) {
1400 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1401 flp->type = SDLA_S508;
1402 goto got_type;
1403 }
1404 }
1405
1406 outb(SDLA_S502A_HALT, base + SDLA_REG_CONTROL);
1407 if (inb(base + SDLA_S502_STS) == 0x40) {
1408 outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
1409 if (inb(base + SDLA_S502_STS) == 0x40) {
1410 outb(SDLA_S502A_INTEN, base + SDLA_REG_CONTROL);
1411 if (inb(base + SDLA_S502_STS) == 0x44) {
1412 outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
1413 flp->type = SDLA_S502A;
1414 goto got_type;
1415 }
1416 }
1417 }
1418
1419 printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
1420 err = -ENODEV;
1421 goto fail;
1422
1423got_type:
1424 switch(base) {
1425 case 0x270:
1426 case 0x280:
1427 case 0x380:
1428 case 0x390:
1429 if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
1430 goto fail;
1431 }
1432
1433 switch (map->irq) {
1434 case 2:
1435 if (flp->type != SDLA_S502E)
1436 goto fail;
1437 break;
1438
1439 case 10:
1440 case 11:
1441 case 12:
1442 case 15:
1443 case 4:
1444 if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
1445 goto fail;
1446 break;
1447 case 3:
1448 case 5:
1449 case 7:
1450 if (flp->type == SDLA_S502A)
1451 goto fail;
1452 break;
1453
1454 default:
1455 goto fail;
1456 }
1457
1458 err = -EAGAIN;
1459 if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev))
1460 goto fail;
1461
1462 if (flp->type == SDLA_S507) {
1463 switch(dev->irq) {
1464 case 3:
1465 flp->state = SDLA_S507_IRQ3;
1466 break;
1467 case 4:
1468 flp->state = SDLA_S507_IRQ4;
1469 break;
1470 case 5:
1471 flp->state = SDLA_S507_IRQ5;
1472 break;
1473 case 7:
1474 flp->state = SDLA_S507_IRQ7;
1475 break;
1476 case 10:
1477 flp->state = SDLA_S507_IRQ10;
1478 break;
1479 case 11:
1480 flp->state = SDLA_S507_IRQ11;
1481 break;
1482 case 12:
1483 flp->state = SDLA_S507_IRQ12;
1484 break;
1485 case 15:
1486 flp->state = SDLA_S507_IRQ15;
1487 break;
1488 }
1489 }
1490
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001491 for(i=0; i < ARRAY_SIZE(valid_mem); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 if (valid_mem[i] == map->mem_start)
1493 break;
1494
1495 err = -EINVAL;
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001496 if (i == ARRAY_SIZE(valid_mem))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 goto fail2;
1498
1499 if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)
1500 goto fail2;
1501
1502 if (flp->type != SDLA_S507 && map->mem_start >> 16 == 0x0B)
1503 goto fail2;
1504
1505 if (flp->type == SDLA_S507 && map->mem_start >> 16 == 0x0D)
1506 goto fail2;
1507
1508 byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0;
1509 byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0));
1510 switch(flp->type) {
1511 case SDLA_S502A:
1512 case SDLA_S502E:
1513 switch (map->mem_start >> 16) {
1514 case 0x0A:
1515 byte |= SDLA_S502_SEG_A;
1516 break;
1517 case 0x0C:
1518 byte |= SDLA_S502_SEG_C;
1519 break;
1520 case 0x0D:
1521 byte |= SDLA_S502_SEG_D;
1522 break;
1523 case 0x0E:
1524 byte |= SDLA_S502_SEG_E;
1525 break;
1526 }
1527 break;
1528 case SDLA_S507:
1529 switch (map->mem_start >> 16) {
1530 case 0x0A:
1531 byte |= SDLA_S507_SEG_A;
1532 break;
1533 case 0x0B:
1534 byte |= SDLA_S507_SEG_B;
1535 break;
1536 case 0x0C:
1537 byte |= SDLA_S507_SEG_C;
1538 break;
1539 case 0x0E:
1540 byte |= SDLA_S507_SEG_E;
1541 break;
1542 }
1543 break;
1544 case SDLA_S508:
1545 switch (map->mem_start >> 16) {
1546 case 0x0A:
1547 byte |= SDLA_S508_SEG_A;
1548 break;
1549 case 0x0C:
1550 byte |= SDLA_S508_SEG_C;
1551 break;
1552 case 0x0D:
1553 byte |= SDLA_S508_SEG_D;
1554 break;
1555 case 0x0E:
1556 byte |= SDLA_S508_SEG_E;
1557 break;
1558 }
1559 break;
1560 }
1561
1562 /* set the memory bits, and enable access */
1563 outb(byte, base + SDLA_REG_PC_WINDOW);
1564
1565 switch(flp->type)
1566 {
1567 case SDLA_S502E:
1568 flp->state = SDLA_S502E_ENABLE;
1569 break;
1570 case SDLA_S507:
1571 flp->state |= SDLA_MEMEN;
1572 break;
1573 case SDLA_S508:
1574 flp->state = SDLA_MEMEN;
1575 break;
1576 }
1577 outb(flp->state, base + SDLA_REG_CONTROL);
1578
1579 dev->irq = map->irq;
1580 dev->base_addr = base;
1581 dev->mem_start = map->mem_start;
1582 dev->mem_end = dev->mem_start + 0x2000;
1583 flp->initialized = 1;
1584 return 0;
1585
1586fail2:
1587 free_irq(map->irq, dev);
1588fail:
1589 release_region(base, SDLA_IO_EXTENTS);
1590 return err;
1591}
1592
1593static struct net_device_stats *sdla_stats(struct net_device *dev)
1594{
1595 struct frad_local *flp;
1596 flp = dev->priv;
1597
1598 return(&flp->stats);
1599}
1600
1601static void setup_sdla(struct net_device *dev)
1602{
1603 struct frad_local *flp = dev->priv;
1604
1605 netdev_boot_setup_check(dev);
1606
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 dev->flags = 0;
1608 dev->type = 0xFFFF;
1609 dev->hard_header_len = 0;
1610 dev->addr_len = 0;
1611 dev->mtu = SDLA_MAX_MTU;
1612
1613 dev->open = sdla_open;
1614 dev->stop = sdla_close;
1615 dev->do_ioctl = sdla_ioctl;
1616 dev->set_config = sdla_set_config;
1617 dev->get_stats = sdla_stats;
1618 dev->hard_start_xmit = sdla_transmit;
1619 dev->change_mtu = sdla_change_mtu;
1620
1621 flp->activate = sdla_activate;
1622 flp->deactivate = sdla_deactivate;
1623 flp->assoc = sdla_assoc;
1624 flp->deassoc = sdla_deassoc;
1625 flp->dlci_conf = sdla_dlci_conf;
1626
1627 init_timer(&flp->timer);
1628 flp->timer.expires = 1;
1629 flp->timer.data = (unsigned long) dev;
1630 flp->timer.function = sdla_poll;
1631}
1632
1633static struct net_device *sdla;
1634
1635static int __init init_sdla(void)
1636{
1637 int err;
1638
1639 printk("%s.\n", version);
1640
1641 sdla = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla);
1642 if (!sdla)
1643 return -ENOMEM;
1644
1645 err = register_netdev(sdla);
1646 if (err)
1647 free_netdev(sdla);
1648
1649 return err;
1650}
1651
1652static void __exit exit_sdla(void)
1653{
1654 struct frad_local *flp = sdla->priv;
1655
1656 unregister_netdev(sdla);
1657 if (flp->initialized) {
1658 free_irq(sdla->irq, sdla);
1659 release_region(sdla->base_addr, SDLA_IO_EXTENTS);
1660 }
1661 del_timer_sync(&flp->timer);
1662 free_netdev(sdla);
1663}
1664
1665MODULE_LICENSE("GPL");
1666
1667module_init(init_sdla);
1668module_exit(exit_sdla);