1 /* $Id: act2000_isa.c,v 1.5 1998/02/12 23:06:47 keil Exp $
3 * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
5 * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
6 * Thanks to Friedemann Baitinger and IBM Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * $Log: act2000_isa.c,v $
23 * Revision 1.5 1998/02/12 23:06:47 keil
24 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
26 * Revision 1.4 1997/10/09 22:23:00 fritz
27 * New HL<->LL interface:
28 * New BSENT callback with nr. of bytes included.
29 * Sending without ACK.
31 * Revision 1.3 1997/09/25 17:25:38 fritz
32 * Support for adding cards at runtime.
33 * Support for new Firmware.
35 * Revision 1.2 1997/09/24 23:11:44 fritz
36 * Optimized IRQ load and polling-mode.
38 * Revision 1.1 1997/09/23 18:00:05 fritz
39 * New driver for IBM Active 2000.
43 #define __NO_VERSION__
45 #include "act2000_isa.h"
48 static act2000_card
*irq2card_map
[16] =
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
53 static int isa_irqs
[] =
55 3, 5, 7, 10, 11, 12, 15
57 #define ISA_NRIRQS (sizeof(isa_irqs)/sizeof(int))
63 current
->state
= TASK_INTERRUPTIBLE
;
69 * Reset Controller, then try to read the Card's signature.
71 * 1 = Signature found.
72 * 0 = Signature not found.
75 isa_reset(unsigned short portbase
)
83 if ((reg
= inb(portbase
+ ISA_COR
)) != 0xff) {
84 outb(reg
| ISA_COR_RESET
, portbase
+ ISA_COR
);
86 outb(reg
, portbase
+ ISA_COR
);
89 for (i
= 0; i
< 16; i
++) {
90 if (inb(portbase
+ ISA_ISR
) & ISA_ISR_SERIAL
)
94 if (serial
== ISA_SER_ID
)
101 isa_detect(unsigned short portbase
)
108 if (!check_region(portbase
, ISA_REGION
))
109 ret
= isa_reset(portbase
);
110 restore_flags(flags
);
115 isa_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
117 act2000_card
*card
= irq2card_map
[irq
];
122 "act2000: Spurious interrupt!\n");
125 istatus
= (inb(ISA_PORT_ISR
) & 0x07);
126 if (istatus
& ISA_ISR_OUT
) {
127 /* RX fifo has data */
128 istatus
&= ISA_ISR_OUT_MASK
;
129 outb(0, ISA_PORT_SIS
);
131 outb(ISA_SIS_INT
, ISA_PORT_SIS
);
133 if (istatus
& ISA_ISR_ERR
) {
134 /* Error Interrupt */
135 istatus
&= ISA_ISR_ERR_MASK
;
136 printk(KERN_WARNING
"act2000: errIRQ\n");
139 printk(KERN_DEBUG
"act2000: ?IRQ %d %02x\n", irq
, istatus
);
143 isa_select_irq(act2000_card
* card
)
147 reg
= (inb(ISA_PORT_COR
) & ~ISA_COR_IRQOFF
) | ISA_COR_PERR
;
171 outb(reg
, ISA_PORT_COR
);
175 isa_enable_irq(act2000_card
* card
)
177 isa_select_irq(card
);
178 /* Enable READ irq */
179 outb(ISA_SIS_INT
, ISA_PORT_SIS
);
183 * Install interrupt handler, enable irq on card.
184 * If irq is -1, choose next free irq, else irq is given explicitely.
187 isa_config_irq(act2000_card
* card
, short irq
)
192 if (card
->flags
& ACT2000_FLAGS_IVALID
) {
193 free_irq(card
->irq
, NULL
);
194 irq2card_map
[card
->irq
] = NULL
;
196 card
->flags
&= ~ACT2000_FLAGS_IVALID
;
197 outb(ISA_COR_IRQOFF
, ISA_PORT_COR
);
204 for (i
= 0; i
< ISA_NRIRQS
; i
++) {
205 if (!request_irq(isa_irqs
[i
], &isa_interrupt
, 0, card
->regname
, NULL
)) {
206 card
->irq
= isa_irqs
[i
];
207 irq2card_map
[card
->irq
] = card
;
208 card
->flags
|= ACT2000_FLAGS_IVALID
;
214 if (!request_irq(irq
, &isa_interrupt
, 0, card
->regname
, NULL
)) {
216 irq2card_map
[card
->irq
] = card
;
217 card
->flags
|= ACT2000_FLAGS_IVALID
;
220 restore_flags(flags
);
221 if (!card
->flags
& ACT2000_FLAGS_IVALID
) {
223 "act2000: Could not request irq\n");
226 isa_select_irq(card
);
227 /* Disable READ and WRITE irq */
228 outb(0, ISA_PORT_SIS
);
229 outb(0, ISA_PORT_SOS
);
235 isa_config_port(act2000_card
* card
, unsigned short portbase
)
237 if (card
->flags
& ACT2000_FLAGS_PVALID
) {
238 release_region(card
->port
, ISA_REGION
);
239 card
->flags
&= ~ACT2000_FLAGS_PVALID
;
241 if (!check_region(portbase
, ISA_REGION
)) {
242 request_region(portbase
, ACT2000_PORTLEN
, card
->regname
);
243 card
->port
= portbase
;
244 card
->flags
|= ACT2000_FLAGS_PVALID
;
251 * Release ressources, used by an adaptor.
254 isa_release(act2000_card
* card
)
260 if (card
->flags
& ACT2000_FLAGS_IVALID
) {
261 free_irq(card
->irq
, NULL
);
262 irq2card_map
[card
->irq
] = NULL
;
264 card
->flags
&= ~ACT2000_FLAGS_IVALID
;
265 if (card
->flags
& ACT2000_FLAGS_PVALID
)
266 release_region(card
->port
, ISA_REGION
);
267 card
->flags
&= ~ACT2000_FLAGS_PVALID
;
268 restore_flags(flags
);
272 isa_writeb(act2000_card
* card
, u_char data
)
277 if (inb(ISA_PORT_SOS
) & ISA_SOS_READY
) {
278 outb(data
, ISA_PORT_SDO
);
289 isa_readb(act2000_card
* card
, u_char
* data
)
294 if (inb(ISA_PORT_SIS
) & ISA_SIS_READY
) {
295 *data
= inb(ISA_PORT_SDI
);
306 isa_receive(act2000_card
*card
)
310 if (test_and_set_bit(ACT2000_LOCK_RX
, (void *) &card
->ilock
) != 0)
312 while (!isa_readb(card
, &c
)) {
313 if (card
->idat
.isa
.rcvidx
< 8) {
314 card
->idat
.isa
.rcvhdr
[card
->idat
.isa
.rcvidx
++] = c
;
315 if (card
->idat
.isa
.rcvidx
== 8) {
316 int valid
= actcapi_chkhdr(card
, (actcapi_msghdr
*)&card
->idat
.isa
.rcvhdr
);
319 card
->idat
.isa
.rcvlen
= ((actcapi_msghdr
*)&card
->idat
.isa
.rcvhdr
)->len
;
320 card
->idat
.isa
.rcvskb
= dev_alloc_skb(card
->idat
.isa
.rcvlen
);
321 if (card
->idat
.isa
.rcvskb
== NULL
) {
322 card
->idat
.isa
.rcvignore
= 1;
324 "isa_receive: no memory\n");
325 test_and_clear_bit(ACT2000_LOCK_RX
, (void *) &card
->ilock
);
328 memcpy(skb_put(card
->idat
.isa
.rcvskb
, 8), card
->idat
.isa
.rcvhdr
, 8);
329 card
->idat
.isa
.rcvptr
= skb_put(card
->idat
.isa
.rcvskb
, card
->idat
.isa
.rcvlen
- 8);
331 card
->idat
.isa
.rcvidx
= 0;
333 "isa_receive: Invalid CAPI msg\n");
335 int i
; __u8
*p
; __u8
*c
; __u8 tmp
[30];
336 for (i
= 0, p
= (__u8
*)&card
->idat
.isa
.rcvhdr
, c
= tmp
; i
< 8; i
++)
337 c
+= sprintf(c
, "%02x ", *(p
++));
338 printk(KERN_WARNING
"isa_receive: %s\n", tmp
);
343 if (!card
->idat
.isa
.rcvignore
)
344 *card
->idat
.isa
.rcvptr
++ = c
;
345 if (++card
->idat
.isa
.rcvidx
>= card
->idat
.isa
.rcvlen
) {
346 if (!card
->idat
.isa
.rcvignore
) {
347 skb_queue_tail(&card
->rcvq
, card
->idat
.isa
.rcvskb
);
348 act2000_schedule_rx(card
);
350 card
->idat
.isa
.rcvidx
= 0;
351 card
->idat
.isa
.rcvlen
= 8;
352 card
->idat
.isa
.rcvignore
= 0;
353 card
->idat
.isa
.rcvskb
= NULL
;
354 card
->idat
.isa
.rcvptr
= card
->idat
.isa
.rcvhdr
;
358 if (!(card
->flags
& ACT2000_FLAGS_IVALID
)) {
359 /* In polling mode, schedule myself */
360 if ((card
->idat
.isa
.rcvidx
) &&
361 (card
->idat
.isa
.rcvignore
||
362 (card
->idat
.isa
.rcvidx
< card
->idat
.isa
.rcvlen
)))
363 act2000_schedule_poll(card
);
365 test_and_clear_bit(ACT2000_LOCK_RX
, (void *) &card
->ilock
);
369 isa_send(act2000_card
* card
)
376 if (test_and_set_bit(ACT2000_LOCK_TX
, (void *) &card
->ilock
) != 0)
382 if ((card
->sbuf
= skb_dequeue(&card
->sndq
))) {
383 card
->ack_msg
= card
->sbuf
->data
;
384 msg
= (actcapi_msg
*)card
->sbuf
->data
;
385 if ((msg
->hdr
.cmd
.cmd
== 0x86) &&
386 (msg
->hdr
.cmd
.subcmd
== 0) ) {
387 /* Save flags in message */
388 card
->need_b3ack
= msg
->msg
.data_b3_req
.flags
;
389 msg
->msg
.data_b3_req
.flags
= 0;
393 restore_flags(flags
);
395 /* No more data to send */
396 test_and_clear_bit(ACT2000_LOCK_TX
, (void *) &card
->ilock
);
402 if (isa_writeb(card
, *(skb
->data
))) {
403 /* Fifo is full, but more data to send */
405 printk(KERN_DEBUG
"isa_send: %d bytes\n", l
);
407 test_and_clear_bit(ACT2000_LOCK_TX
, (void *) &card
->ilock
);
408 /* Schedule myself */
409 act2000_schedule_tx(card
);
415 msg
= (actcapi_msg
*)card
->ack_msg
;
416 if ((msg
->hdr
.cmd
.cmd
== 0x86) &&
417 (msg
->hdr
.cmd
.subcmd
== 0) ) {
419 * If it's user data, reset data-ptr
420 * and put skb into ackq.
422 skb
->data
= card
->ack_msg
;
423 /* Restore flags in message */
424 msg
->msg
.data_b3_req
.flags
= card
->need_b3ack
;
425 skb_queue_tail(&card
->ackq
, skb
);
430 printk(KERN_DEBUG
"isa_send: %d bytes\n", l
);
436 * Get firmware ID, check for 'ISDN' signature.
439 isa_getid(act2000_card
* card
)
443 u_char
*p
= (u_char
*) & fid
;
449 if (isa_readb(card
, p
++))
454 printk(KERN_WARNING
"act2000: No Firmware-ID!\n");
458 fid
.revlen
[0] = '\0';
459 if (strcmp(fid
.isdn
, "ISDN")) {
460 printk(KERN_WARNING
"act2000: Wrong Firmware-ID!\n");
463 if ((p
= strchr(fid
.revision
, '\n')))
465 printk(KERN_INFO
"act2000: Firmware-ID: %s\n", fid
.revision
);
466 if (card
->flags
& ACT2000_FLAGS_IVALID
) {
467 printk(KERN_DEBUG
"Enabling Interrupts ...\n");
468 isa_enable_irq(card
);
474 * Download microcode into card, check Firmware signature.
477 isa_download(act2000_card
* card
, act2000_ddef
* cb
)
489 if (!isa_reset(card
->port
))
492 if ((ret
= verify_area(VERIFY_READ
, (void *) cb
, sizeof(cblock
))))
494 copy_from_user(&cblock
, (char *) cb
, sizeof(cblock
));
495 length
= cblock
.length
;
497 if ((ret
= verify_area(VERIFY_READ
, (void *) p
, length
)))
499 buf
= (u_char
*) kmalloc(1024, GFP_KERNEL
);
504 l
= (length
> 1024) ? 1024 : length
;
507 copy_from_user(buf
, p
, l
);
509 if (isa_writeb(card
, *b
++)) {
511 "act2000: loader timed out"
512 " len=%d c=%d\n", length
, c
);
523 return (isa_getid(card
));