blob: 05df0a345b609744f243d1bbafcd05bbbe0e7d9f [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
David Howells7d12e782006-10-05 14:55:46 +0100870static irqreturn_t sdla_isr(int irq, 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 {
882 printk(KERN_WARNING "%s: irq %d for uninitialized device.\n", dev->name, irq);
883 return IRQ_NONE;
884 }
885
886 byte = sdla_byte(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE);
887 switch (byte)
888 {
889 case SDLA_INTR_RX:
890 sdla_receive(dev);
891 break;
892
893 /* the command will get an error return, which is processed above */
894 case SDLA_INTR_MODEM:
895 case SDLA_INTR_STATUS:
896 sdla_cmd(dev, SDLA_READ_DLC_STATUS, 0, 0, NULL, 0, NULL, NULL);
897 break;
898
899 case SDLA_INTR_TX:
900 case SDLA_INTR_COMPLETE:
901 case SDLA_INTR_TIMER:
902 printk(KERN_WARNING "%s: invalid irq flag 0x%02X.\n", dev->name, byte);
903 break;
904 }
905
906 /* the S502E requires a manual acknowledgement of the interrupt */
907 if (flp->type == SDLA_S502E)
908 {
909 flp->state &= ~SDLA_S502E_INTACK;
910 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
911 flp->state |= SDLA_S502E_INTACK;
912 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
913 }
914
915 /* this clears the byte, informing the Z80 we're done */
916 byte = 0;
917 sdla_write(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));
918 return IRQ_HANDLED;
919}
920
921static void sdla_poll(unsigned long device)
922{
923 struct net_device *dev;
924 struct frad_local *flp;
925
926 dev = (struct net_device *) device;
927 flp = dev->priv;
928
929 if (sdla_byte(dev, SDLA_502_RCV_BUF))
930 sdla_receive(dev);
931
932 flp->timer.expires = 1;
933 add_timer(&flp->timer);
934}
935
936static int sdla_close(struct net_device *dev)
937{
938 struct frad_local *flp;
939 struct intr_info intr;
940 int len, i;
941 short dlcis[CONFIG_DLCI_MAX];
942
943 flp = dev->priv;
944
945 len = 0;
946 for(i=0;i<CONFIG_DLCI_MAX;i++)
947 if (flp->dlci[i])
948 dlcis[len++] = abs(flp->dlci[i]);
949 len *= 2;
950
951 if (flp->config.station == FRAD_STATION_NODE)
952 {
953 for(i=0;i<CONFIG_DLCI_MAX;i++)
954 if (flp->dlci[i] > 0)
955 sdla_cmd(dev, SDLA_DEACTIVATE_DLCI, 0, 0, dlcis, len, NULL, NULL);
956 sdla_cmd(dev, SDLA_DELETE_DLCI, 0, 0, &flp->dlci[i], sizeof(flp->dlci[i]), NULL, NULL);
957 }
958
959 memset(&intr, 0, sizeof(intr));
960 /* let's start up the reception */
961 switch(flp->type)
962 {
963 case SDLA_S502A:
964 del_timer(&flp->timer);
965 break;
966
967 case SDLA_S502E:
968 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(char) + sizeof(short), NULL, NULL);
969 flp->state &= ~SDLA_S502E_INTACK;
970 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
971 break;
972
973 case SDLA_S507:
974 break;
975
976 case SDLA_S508:
977 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(struct intr_info), NULL, NULL);
978 flp->state &= ~SDLA_S508_INTEN;
979 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
980 break;
981 }
982
983 sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
984
985 netif_stop_queue(dev);
986
987 return(0);
988}
989
990struct conf_data {
991 struct frad_conf config;
992 short dlci[CONFIG_DLCI_MAX];
993};
994
995static int sdla_open(struct net_device *dev)
996{
997 struct frad_local *flp;
998 struct dlci_local *dlp;
999 struct conf_data data;
1000 struct intr_info intr;
1001 int len, i;
1002 char byte;
1003
1004 flp = dev->priv;
1005
1006 if (!flp->initialized)
1007 return(-EPERM);
1008
1009 if (!flp->configured)
1010 return(-EPERM);
1011
1012 /* time to send in the configuration */
1013 len = 0;
1014 for(i=0;i<CONFIG_DLCI_MAX;i++)
1015 if (flp->dlci[i])
1016 data.dlci[len++] = abs(flp->dlci[i]);
1017 len *= 2;
1018
1019 memcpy(&data.config, &flp->config, sizeof(struct frad_conf));
1020 len += sizeof(struct frad_conf);
1021
1022 sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1023 sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL);
1024
1025 if (flp->type == SDLA_S508)
1026 flp->buffer = 0;
1027
1028 sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1029
1030 /* let's start up the reception */
1031 memset(&intr, 0, sizeof(intr));
1032 switch(flp->type)
1033 {
1034 case SDLA_S502A:
1035 flp->timer.expires = 1;
1036 add_timer(&flp->timer);
1037 break;
1038
1039 case SDLA_S502E:
1040 flp->state |= SDLA_S502E_ENABLE;
1041 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
1042 flp->state |= SDLA_S502E_INTACK;
1043 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
1044 byte = 0;
1045 sdla_write(dev, SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));
1046 intr.flags = SDLA_INTR_RX | SDLA_INTR_STATUS | SDLA_INTR_MODEM;
1047 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(char) + sizeof(short), NULL, NULL);
1048 break;
1049
1050 case SDLA_S507:
1051 break;
1052
1053 case SDLA_S508:
1054 flp->state |= SDLA_S508_INTEN;
1055 outb(flp->state, dev->base_addr + SDLA_REG_CONTROL);
1056 byte = 0;
1057 sdla_write(dev, SDLA_508_IRQ_INTERFACE, &byte, sizeof(byte));
1058 intr.flags = SDLA_INTR_RX | SDLA_INTR_STATUS | SDLA_INTR_MODEM;
1059 intr.irq = dev->irq;
1060 sdla_cmd(dev, SDLA_SET_IRQ_TRIGGER, 0, 0, &intr, sizeof(struct intr_info), NULL, NULL);
1061 break;
1062 }
1063
1064 if (flp->config.station == FRAD_STATION_CPE)
1065 {
1066 byte = SDLA_ICS_STATUS_ENQ;
1067 sdla_cmd(dev, SDLA_ISSUE_IN_CHANNEL_SIGNAL, 0, 0, &byte, sizeof(byte), NULL, NULL);
1068 }
1069 else
1070 {
1071 sdla_cmd(dev, SDLA_ADD_DLCI, 0, 0, data.dlci, len - sizeof(struct frad_conf), NULL, NULL);
1072 for(i=0;i<CONFIG_DLCI_MAX;i++)
1073 if (flp->dlci[i] > 0)
1074 sdla_cmd(dev, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], 2*sizeof(flp->dlci[i]), NULL, NULL);
1075 }
1076
1077 /* configure any specific DLCI settings */
1078 for(i=0;i<CONFIG_DLCI_MAX;i++)
1079 if (flp->dlci[i])
1080 {
1081 dlp = flp->master[i]->priv;
1082 if (dlp->configured)
1083 sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf), NULL, NULL);
1084 }
1085
1086 netif_start_queue(dev);
1087
1088 return(0);
1089}
1090
1091static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, int get)
1092{
1093 struct frad_local *flp;
1094 struct conf_data data;
1095 int i;
1096 short size;
1097
1098 if (dev->type == 0xFFFF)
1099 return(-EUNATCH);
1100
1101 flp = dev->priv;
1102
1103 if (!get)
1104 {
1105 if (netif_running(dev))
1106 return(-EBUSY);
1107
1108 if(copy_from_user(&data.config, conf, sizeof(struct frad_conf)))
1109 return -EFAULT;
1110
1111 if (data.config.station & ~FRAD_STATION_NODE)
1112 return(-EINVAL);
1113
1114 if (data.config.flags & ~FRAD_VALID_FLAGS)
1115 return(-EINVAL);
1116
1117 if ((data.config.kbaud < 0) ||
1118 ((data.config.kbaud > 128) && (flp->type != SDLA_S508)))
1119 return(-EINVAL);
1120
1121 if (data.config.clocking & ~(FRAD_CLOCK_INT | SDLA_S508_PORT_RS232))
1122 return(-EINVAL);
1123
1124 if ((data.config.mtu < 0) || (data.config.mtu > SDLA_MAX_MTU))
1125 return(-EINVAL);
1126
1127 if ((data.config.T391 < 5) || (data.config.T391 > 30))
1128 return(-EINVAL);
1129
1130 if ((data.config.T392 < 5) || (data.config.T392 > 30))
1131 return(-EINVAL);
1132
1133 if ((data.config.N391 < 1) || (data.config.N391 > 255))
1134 return(-EINVAL);
1135
1136 if ((data.config.N392 < 1) || (data.config.N392 > 10))
1137 return(-EINVAL);
1138
1139 if ((data.config.N393 < 1) || (data.config.N393 > 10))
1140 return(-EINVAL);
1141
1142 memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
1143 flp->config.flags |= SDLA_DIRECT_RECV;
1144
1145 if (flp->type == SDLA_S508)
1146 flp->config.flags |= SDLA_TX70_RX30;
1147
1148 if (dev->mtu != flp->config.mtu)
1149 {
1150 /* this is required to change the MTU */
1151 dev->mtu = flp->config.mtu;
1152 for(i=0;i<CONFIG_DLCI_MAX;i++)
1153 if (flp->master[i])
1154 flp->master[i]->mtu = flp->config.mtu;
1155 }
1156
1157 flp->config.mtu += sizeof(struct frhdr);
1158
1159 /* off to the races! */
1160 if (!flp->configured)
1161 sdla_start(dev);
1162
1163 flp->configured = 1;
1164 }
1165 else
1166 {
1167 /* no sense reading if the CPU isn't started */
1168 if (netif_running(dev))
1169 {
1170 size = sizeof(data);
1171 if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)
1172 return(-EIO);
1173 }
1174 else
1175 if (flp->configured)
1176 memcpy(&data.config, &flp->config, sizeof(struct frad_conf));
1177 else
1178 memset(&data.config, 0, sizeof(struct frad_conf));
1179
1180 memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
1181 data.config.flags &= FRAD_VALID_FLAGS;
1182 data.config.mtu -= data.config.mtu > sizeof(struct frhdr) ? sizeof(struct frhdr) : data.config.mtu;
1183 return copy_to_user(conf, &data.config, sizeof(struct frad_conf))?-EFAULT:0;
1184 }
1185
1186 return(0);
1187}
1188
1189static int sdla_xfer(struct net_device *dev, struct sdla_mem __user *info, int read)
1190{
1191 struct sdla_mem mem;
1192 char *temp;
1193
1194 if(copy_from_user(&mem, info, sizeof(mem)))
1195 return -EFAULT;
1196
1197 if (read)
1198 {
Yoann Padioleaudd00cc42007-07-19 01:49:03 -07001199 temp = kzalloc(mem.len, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 if (!temp)
1201 return(-ENOMEM);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 sdla_read(dev, mem.addr, temp, mem.len);
1203 if(copy_to_user(mem.data, temp, mem.len))
1204 {
1205 kfree(temp);
1206 return -EFAULT;
1207 }
1208 kfree(temp);
1209 }
1210 else
1211 {
1212 temp = kmalloc(mem.len, GFP_KERNEL);
1213 if (!temp)
1214 return(-ENOMEM);
1215 if(copy_from_user(temp, mem.data, mem.len))
1216 {
1217 kfree(temp);
1218 return -EFAULT;
1219 }
1220 sdla_write(dev, mem.addr, temp, mem.len);
1221 kfree(temp);
1222 }
1223 return(0);
1224}
1225
1226static int sdla_reconfig(struct net_device *dev)
1227{
1228 struct frad_local *flp;
1229 struct conf_data data;
1230 int i, len;
1231
1232 flp = dev->priv;
1233
1234 len = 0;
1235 for(i=0;i<CONFIG_DLCI_MAX;i++)
1236 if (flp->dlci[i])
1237 data.dlci[len++] = flp->dlci[i];
1238 len *= 2;
1239
1240 memcpy(&data, &flp->config, sizeof(struct frad_conf));
1241 len += sizeof(struct frad_conf);
1242
1243 sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1244 sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, 0, 0, &data, len, NULL, NULL);
1245 sdla_cmd(dev, SDLA_ENABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
1246
1247 return(0);
1248}
1249
1250static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1251{
1252 struct frad_local *flp;
1253
1254 if(!capable(CAP_NET_ADMIN))
1255 return -EPERM;
1256
1257 flp = dev->priv;
1258
1259 if (!flp->initialized)
1260 return(-EINVAL);
1261
1262 switch (cmd)
1263 {
1264 case FRAD_GET_CONF:
1265 case FRAD_SET_CONF:
1266 return(sdla_config(dev, ifr->ifr_data, cmd == FRAD_GET_CONF));
1267
1268 case SDLA_IDENTIFY:
1269 ifr->ifr_flags = flp->type;
1270 break;
1271
1272 case SDLA_CPUSPEED:
1273 return(sdla_cpuspeed(dev, ifr));
1274
1275/* ==========================================================
1276NOTE: This is rather a useless action right now, as the
1277 current driver does not support protocols other than
1278 FR. However, Sangoma has modules for a number of
1279 other protocols in the works.
1280============================================================*/
1281 case SDLA_PROTOCOL:
1282 if (flp->configured)
1283 return(-EALREADY);
1284
1285 switch (ifr->ifr_flags)
1286 {
1287 case ARPHRD_FRAD:
1288 dev->type = ifr->ifr_flags;
1289 break;
1290 default:
1291 return(-ENOPROTOOPT);
1292 }
1293 break;
1294
1295 case SDLA_CLEARMEM:
1296 sdla_clear(dev);
1297 break;
1298
1299 case SDLA_WRITEMEM:
1300 case SDLA_READMEM:
1301 if(!capable(CAP_SYS_RAWIO))
1302 return -EPERM;
1303 return(sdla_xfer(dev, ifr->ifr_data, cmd == SDLA_READMEM));
1304
1305 case SDLA_START:
1306 sdla_start(dev);
1307 break;
1308
1309 case SDLA_STOP:
1310 sdla_stop(dev);
1311 break;
1312
1313 default:
1314 return(-EOPNOTSUPP);
1315 }
1316 return(0);
1317}
1318
Adrian Bunk7665a082005-09-09 23:17:28 -07001319static int sdla_change_mtu(struct net_device *dev, int new_mtu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320{
1321 struct frad_local *flp;
1322
1323 flp = dev->priv;
1324
1325 if (netif_running(dev))
1326 return(-EBUSY);
1327
1328 /* for now, you can't change the MTU! */
1329 return(-EOPNOTSUPP);
1330}
1331
Adrian Bunk7665a082005-09-09 23:17:28 -07001332static int sdla_set_config(struct net_device *dev, struct ifmap *map)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333{
1334 struct frad_local *flp;
1335 int i;
1336 char byte;
1337 unsigned base;
1338 int err = -EINVAL;
1339
1340 flp = dev->priv;
1341
1342 if (flp->initialized)
1343 return(-EINVAL);
1344
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001345 for(i=0; i < ARRAY_SIZE(valid_port); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 if (valid_port[i] == map->base_addr)
1347 break;
1348
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001349 if (i == ARRAY_SIZE(valid_port))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 return(-EINVAL);
1351
1352 if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){
1353 printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr);
1354 return(-EINVAL);
1355 }
1356 base = map->base_addr;
1357
1358 /* test for card types, S502A, S502E, S507, S508 */
1359 /* these tests shut down the card completely, so clear the state */
1360 flp->type = SDLA_UNKNOWN;
1361 flp->state = 0;
1362
1363 for(i=1;i<SDLA_IO_EXTENTS;i++)
1364 if (inb(base + i) != 0xFF)
1365 break;
1366
1367 if (i == SDLA_IO_EXTENTS) {
1368 outb(SDLA_HALT, base + SDLA_REG_Z80_CONTROL);
1369 if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x08) {
1370 outb(SDLA_S502E_INTACK, base + SDLA_REG_CONTROL);
1371 if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x0C) {
1372 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1373 flp->type = SDLA_S502E;
1374 goto got_type;
1375 }
1376 }
1377 }
1378
1379 for(byte=inb(base),i=0;i<SDLA_IO_EXTENTS;i++)
1380 if (inb(base + i) != byte)
1381 break;
1382
1383 if (i == SDLA_IO_EXTENTS) {
1384 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1385 if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x30) {
1386 outb(SDLA_S507_ENABLE, base + SDLA_REG_CONTROL);
1387 if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x32) {
1388 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1389 flp->type = SDLA_S507;
1390 goto got_type;
1391 }
1392 }
1393 }
1394
1395 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1396 if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x00) {
1397 outb(SDLA_S508_INTEN, base + SDLA_REG_CONTROL);
1398 if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x10) {
1399 outb(SDLA_HALT, base + SDLA_REG_CONTROL);
1400 flp->type = SDLA_S508;
1401 goto got_type;
1402 }
1403 }
1404
1405 outb(SDLA_S502A_HALT, base + SDLA_REG_CONTROL);
1406 if (inb(base + SDLA_S502_STS) == 0x40) {
1407 outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
1408 if (inb(base + SDLA_S502_STS) == 0x40) {
1409 outb(SDLA_S502A_INTEN, base + SDLA_REG_CONTROL);
1410 if (inb(base + SDLA_S502_STS) == 0x44) {
1411 outb(SDLA_S502A_START, base + SDLA_REG_CONTROL);
1412 flp->type = SDLA_S502A;
1413 goto got_type;
1414 }
1415 }
1416 }
1417
1418 printk(KERN_NOTICE "%s: Unknown card type\n", dev->name);
1419 err = -ENODEV;
1420 goto fail;
1421
1422got_type:
1423 switch(base) {
1424 case 0x270:
1425 case 0x280:
1426 case 0x380:
1427 case 0x390:
1428 if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
1429 goto fail;
1430 }
1431
1432 switch (map->irq) {
1433 case 2:
1434 if (flp->type != SDLA_S502E)
1435 goto fail;
1436 break;
1437
1438 case 10:
1439 case 11:
1440 case 12:
1441 case 15:
1442 case 4:
1443 if (flp->type != SDLA_S508 && flp->type != SDLA_S507)
1444 goto fail;
1445 break;
1446 case 3:
1447 case 5:
1448 case 7:
1449 if (flp->type == SDLA_S502A)
1450 goto fail;
1451 break;
1452
1453 default:
1454 goto fail;
1455 }
1456
1457 err = -EAGAIN;
1458 if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev))
1459 goto fail;
1460
1461 if (flp->type == SDLA_S507) {
1462 switch(dev->irq) {
1463 case 3:
1464 flp->state = SDLA_S507_IRQ3;
1465 break;
1466 case 4:
1467 flp->state = SDLA_S507_IRQ4;
1468 break;
1469 case 5:
1470 flp->state = SDLA_S507_IRQ5;
1471 break;
1472 case 7:
1473 flp->state = SDLA_S507_IRQ7;
1474 break;
1475 case 10:
1476 flp->state = SDLA_S507_IRQ10;
1477 break;
1478 case 11:
1479 flp->state = SDLA_S507_IRQ11;
1480 break;
1481 case 12:
1482 flp->state = SDLA_S507_IRQ12;
1483 break;
1484 case 15:
1485 flp->state = SDLA_S507_IRQ15;
1486 break;
1487 }
1488 }
1489
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001490 for(i=0; i < ARRAY_SIZE(valid_mem); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 if (valid_mem[i] == map->mem_start)
1492 break;
1493
1494 err = -EINVAL;
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001495 if (i == ARRAY_SIZE(valid_mem))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 goto fail2;
1497
1498 if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E)
1499 goto fail2;
1500
1501 if (flp->type != SDLA_S507 && map->mem_start >> 16 == 0x0B)
1502 goto fail2;
1503
1504 if (flp->type == SDLA_S507 && map->mem_start >> 16 == 0x0D)
1505 goto fail2;
1506
1507 byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0;
1508 byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0));
1509 switch(flp->type) {
1510 case SDLA_S502A:
1511 case SDLA_S502E:
1512 switch (map->mem_start >> 16) {
1513 case 0x0A:
1514 byte |= SDLA_S502_SEG_A;
1515 break;
1516 case 0x0C:
1517 byte |= SDLA_S502_SEG_C;
1518 break;
1519 case 0x0D:
1520 byte |= SDLA_S502_SEG_D;
1521 break;
1522 case 0x0E:
1523 byte |= SDLA_S502_SEG_E;
1524 break;
1525 }
1526 break;
1527 case SDLA_S507:
1528 switch (map->mem_start >> 16) {
1529 case 0x0A:
1530 byte |= SDLA_S507_SEG_A;
1531 break;
1532 case 0x0B:
1533 byte |= SDLA_S507_SEG_B;
1534 break;
1535 case 0x0C:
1536 byte |= SDLA_S507_SEG_C;
1537 break;
1538 case 0x0E:
1539 byte |= SDLA_S507_SEG_E;
1540 break;
1541 }
1542 break;
1543 case SDLA_S508:
1544 switch (map->mem_start >> 16) {
1545 case 0x0A:
1546 byte |= SDLA_S508_SEG_A;
1547 break;
1548 case 0x0C:
1549 byte |= SDLA_S508_SEG_C;
1550 break;
1551 case 0x0D:
1552 byte |= SDLA_S508_SEG_D;
1553 break;
1554 case 0x0E:
1555 byte |= SDLA_S508_SEG_E;
1556 break;
1557 }
1558 break;
1559 }
1560
1561 /* set the memory bits, and enable access */
1562 outb(byte, base + SDLA_REG_PC_WINDOW);
1563
1564 switch(flp->type)
1565 {
1566 case SDLA_S502E:
1567 flp->state = SDLA_S502E_ENABLE;
1568 break;
1569 case SDLA_S507:
1570 flp->state |= SDLA_MEMEN;
1571 break;
1572 case SDLA_S508:
1573 flp->state = SDLA_MEMEN;
1574 break;
1575 }
1576 outb(flp->state, base + SDLA_REG_CONTROL);
1577
1578 dev->irq = map->irq;
1579 dev->base_addr = base;
1580 dev->mem_start = map->mem_start;
1581 dev->mem_end = dev->mem_start + 0x2000;
1582 flp->initialized = 1;
1583 return 0;
1584
1585fail2:
1586 free_irq(map->irq, dev);
1587fail:
1588 release_region(base, SDLA_IO_EXTENTS);
1589 return err;
1590}
1591
1592static struct net_device_stats *sdla_stats(struct net_device *dev)
1593{
1594 struct frad_local *flp;
1595 flp = dev->priv;
1596
1597 return(&flp->stats);
1598}
1599
1600static void setup_sdla(struct net_device *dev)
1601{
1602 struct frad_local *flp = dev->priv;
1603
1604 netdev_boot_setup_check(dev);
1605
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 dev->flags = 0;
1607 dev->type = 0xFFFF;
1608 dev->hard_header_len = 0;
1609 dev->addr_len = 0;
1610 dev->mtu = SDLA_MAX_MTU;
1611
1612 dev->open = sdla_open;
1613 dev->stop = sdla_close;
1614 dev->do_ioctl = sdla_ioctl;
1615 dev->set_config = sdla_set_config;
1616 dev->get_stats = sdla_stats;
1617 dev->hard_start_xmit = sdla_transmit;
1618 dev->change_mtu = sdla_change_mtu;
1619
1620 flp->activate = sdla_activate;
1621 flp->deactivate = sdla_deactivate;
1622 flp->assoc = sdla_assoc;
1623 flp->deassoc = sdla_deassoc;
1624 flp->dlci_conf = sdla_dlci_conf;
1625
1626 init_timer(&flp->timer);
1627 flp->timer.expires = 1;
1628 flp->timer.data = (unsigned long) dev;
1629 flp->timer.function = sdla_poll;
1630}
1631
1632static struct net_device *sdla;
1633
1634static int __init init_sdla(void)
1635{
1636 int err;
1637
1638 printk("%s.\n", version);
1639
1640 sdla = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla);
1641 if (!sdla)
1642 return -ENOMEM;
1643
1644 err = register_netdev(sdla);
1645 if (err)
1646 free_netdev(sdla);
1647
1648 return err;
1649}
1650
1651static void __exit exit_sdla(void)
1652{
1653 struct frad_local *flp = sdla->priv;
1654
1655 unregister_netdev(sdla);
1656 if (flp->initialized) {
1657 free_irq(sdla->irq, sdla);
1658 release_region(sdla->base_addr, SDLA_IO_EXTENTS);
1659 }
1660 del_timer_sync(&flp->timer);
1661 free_netdev(sdla);
1662}
1663
1664MODULE_LICENSE("GPL");
1665
1666module_init(init_sdla);
1667module_exit(exit_sdla);