1 /* $Id: act2000_isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
3 * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
6 * Copyright by Fritz Elfert <fritz@isdn4linux.de>
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
11 * Thanks to Friedemann Baitinger and IBM Germany
15 #define __NO_VERSION__
17 #include "act2000_isa.h"
20 static act2000_card *irq2card_map[16];
23 act2000_isa_delay(long t)
26 set_current_state(TASK_INTERRUPTIBLE);
32 * Reset Controller, then try to read the Card's signature.
34 * 1 = Signature found.
35 * 0 = Signature not found.
38 act2000_isa_reset(unsigned short portbase)
46 if ((reg = inb(portbase + ISA_COR)) != 0xff) {
47 outb(reg | ISA_COR_RESET, portbase + ISA_COR);
49 outb(reg, portbase + ISA_COR);
52 for (i = 0; i < 16; i++) {
53 if (inb(portbase + ISA_ISR) & ISA_ISR_SERIAL)
57 if (serial == ISA_SER_ID)
64 act2000_isa_detect(unsigned short portbase)
68 if (!check_region(portbase, ISA_REGION))
69 ret = act2000_isa_reset(portbase);
74 act2000_isa_interrupt(int irq, void *dev_id, struct pt_regs *regs)
76 act2000_card *card = irq2card_map[irq];
81 "act2000: Spurious interrupt!\n");
84 istatus = (inb(ISA_PORT_ISR) & 0x07);
85 if (istatus & ISA_ISR_OUT) {
86 /* RX fifo has data */
87 istatus &= ISA_ISR_OUT_MASK;
88 outb(0, ISA_PORT_SIS);
89 act2000_isa_receive(card);
90 outb(ISA_SIS_INT, ISA_PORT_SIS);
92 if (istatus & ISA_ISR_ERR) {
94 istatus &= ISA_ISR_ERR_MASK;
95 printk(KERN_WARNING "act2000: errIRQ\n");
98 printk(KERN_DEBUG "act2000: ?IRQ %d %02x\n", irq, istatus);
102 act2000_isa_select_irq(act2000_card * card)
106 reg = (inb(ISA_PORT_COR) & ~ISA_COR_IRQOFF) | ISA_COR_PERR;
130 outb(reg, ISA_PORT_COR);
134 act2000_isa_enable_irq(act2000_card * card)
136 act2000_isa_select_irq(card);
137 /* Enable READ irq */
138 outb(ISA_SIS_INT, ISA_PORT_SIS);
142 * Install interrupt handler, enable irq on card.
143 * If irq is -1, choose next free irq, else irq is given explicitely.
146 act2000_isa_config_irq(act2000_card * card, short irq)
148 if (card->flags & ACT2000_FLAGS_IVALID) {
149 free_irq(card->irq, NULL);
150 irq2card_map[card->irq] = NULL;
152 card->flags &= ~ACT2000_FLAGS_IVALID;
153 outb(ISA_COR_IRQOFF, ISA_PORT_COR);
157 if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
159 irq2card_map[card->irq] = card;
160 card->flags |= ACT2000_FLAGS_IVALID;
162 "act2000: Could not request irq %d\n",irq);
165 act2000_isa_select_irq(card);
166 /* Disable READ and WRITE irq */
167 outb(0, ISA_PORT_SIS);
168 outb(0, ISA_PORT_SOS);
174 act2000_isa_config_port(act2000_card * card, unsigned short portbase)
176 if (card->flags & ACT2000_FLAGS_PVALID) {
177 release_region(card->port, ISA_REGION);
178 card->flags &= ~ACT2000_FLAGS_PVALID;
180 if (!check_region(portbase, ISA_REGION)) {
181 if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
183 card->port = portbase;
184 card->flags |= ACT2000_FLAGS_PVALID;
191 * Release ressources, used by an adaptor.
194 act2000_isa_release(act2000_card * card)
200 if (card->flags & ACT2000_FLAGS_IVALID) {
201 free_irq(card->irq, NULL);
202 irq2card_map[card->irq] = NULL;
204 card->flags &= ~ACT2000_FLAGS_IVALID;
205 if (card->flags & ACT2000_FLAGS_PVALID)
206 release_region(card->port, ISA_REGION);
207 card->flags &= ~ACT2000_FLAGS_PVALID;
208 restore_flags(flags);
212 act2000_isa_writeb(act2000_card * card, u_char data)
217 if (inb(ISA_PORT_SOS) & ISA_SOS_READY) {
218 outb(data, ISA_PORT_SDO);
229 act2000_isa_readb(act2000_card * card, u_char * data)
234 if (inb(ISA_PORT_SIS) & ISA_SIS_READY) {
235 *data = inb(ISA_PORT_SDI);
246 act2000_isa_receive(act2000_card *card)
250 if (test_and_set_bit(ACT2000_LOCK_RX, (void *) &card->ilock) != 0)
252 while (!act2000_isa_readb(card, &c)) {
253 if (card->idat.isa.rcvidx < 8) {
254 card->idat.isa.rcvhdr[card->idat.isa.rcvidx++] = c;
255 if (card->idat.isa.rcvidx == 8) {
256 int valid = actcapi_chkhdr(card, (actcapi_msghdr *)&card->idat.isa.rcvhdr);
259 card->idat.isa.rcvlen = ((actcapi_msghdr *)&card->idat.isa.rcvhdr)->len;
260 card->idat.isa.rcvskb = dev_alloc_skb(card->idat.isa.rcvlen);
261 if (card->idat.isa.rcvskb == NULL) {
262 card->idat.isa.rcvignore = 1;
264 "act2000_isa_receive: no memory\n");
265 test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock);
268 memcpy(skb_put(card->idat.isa.rcvskb, 8), card->idat.isa.rcvhdr, 8);
269 card->idat.isa.rcvptr = skb_put(card->idat.isa.rcvskb, card->idat.isa.rcvlen - 8);
271 card->idat.isa.rcvidx = 0;
273 "act2000_isa_receive: Invalid CAPI msg\n");
275 int i; __u8 *p; __u8 *c; __u8 tmp[30];
276 for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, c = tmp; i < 8; i++)
277 c += sprintf(c, "%02x ", *(p++));
278 printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp);
283 if (!card->idat.isa.rcvignore)
284 *card->idat.isa.rcvptr++ = c;
285 if (++card->idat.isa.rcvidx >= card->idat.isa.rcvlen) {
286 if (!card->idat.isa.rcvignore) {
287 skb_queue_tail(&card->rcvq, card->idat.isa.rcvskb);
288 act2000_schedule_rx(card);
290 card->idat.isa.rcvidx = 0;
291 card->idat.isa.rcvlen = 8;
292 card->idat.isa.rcvignore = 0;
293 card->idat.isa.rcvskb = NULL;
294 card->idat.isa.rcvptr = card->idat.isa.rcvhdr;
298 if (!(card->flags & ACT2000_FLAGS_IVALID)) {
299 /* In polling mode, schedule myself */
300 if ((card->idat.isa.rcvidx) &&
301 (card->idat.isa.rcvignore ||
302 (card->idat.isa.rcvidx < card->idat.isa.rcvlen)))
303 act2000_schedule_poll(card);
305 test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock);
309 act2000_isa_send(act2000_card * card)
316 if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0)
322 if ((card->sbuf = skb_dequeue(&card->sndq))) {
323 card->ack_msg = card->sbuf->data;
324 msg = (actcapi_msg *)card->sbuf->data;
325 if ((msg->hdr.cmd.cmd == 0x86) &&
326 (msg->hdr.cmd.subcmd == 0) ) {
327 /* Save flags in message */
328 card->need_b3ack = msg->msg.data_b3_req.flags;
329 msg->msg.data_b3_req.flags = 0;
333 restore_flags(flags);
335 /* No more data to send */
336 test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
342 if (act2000_isa_writeb(card, *(skb->data))) {
343 /* Fifo is full, but more data to send */
344 test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
345 /* Schedule myself */
346 act2000_schedule_tx(card);
352 msg = (actcapi_msg *)card->ack_msg;
353 if ((msg->hdr.cmd.cmd == 0x86) &&
354 (msg->hdr.cmd.subcmd == 0) ) {
356 * If it's user data, reset data-ptr
357 * and put skb into ackq.
359 skb->data = card->ack_msg;
360 /* Restore flags in message */
361 msg->msg.data_b3_req.flags = card->need_b3ack;
362 skb_queue_tail(&card->ackq, skb);
370 * Get firmware ID, check for 'ISDN' signature.
373 act2000_isa_getid(act2000_card * card)
377 u_char *p = (u_char *) & fid;
383 if (act2000_isa_readb(card, p++))
388 printk(KERN_WARNING "act2000: No Firmware-ID!\n");
392 fid.revlen[0] = '\0';
393 if (strcmp(fid.isdn, "ISDN")) {
394 printk(KERN_WARNING "act2000: Wrong Firmware-ID!\n");
397 if ((p = strchr(fid.revision, '\n')))
399 printk(KERN_INFO "act2000: Firmware-ID: %s\n", fid.revision);
400 if (card->flags & ACT2000_FLAGS_IVALID) {
401 printk(KERN_DEBUG "Enabling Interrupts ...\n");
402 act2000_isa_enable_irq(card);
408 * Download microcode into card, check Firmware signature.
411 act2000_isa_download(act2000_card * card, act2000_ddef * cb)
423 if (!act2000_isa_reset(card->port))
425 act2000_isa_delay(HZ / 2);
426 if(copy_from_user(&cblock, (char *) cb, sizeof(cblock)))
428 length = cblock.length;
430 if ((ret = verify_area(VERIFY_READ, (void *) p, length)))
432 buf = (u_char *) kmalloc(1024, GFP_KERNEL);
437 l = (length > 1024) ? 1024 : length;
440 copy_from_user(buf, p, l);
442 if (act2000_isa_writeb(card, *b++)) {
444 "act2000: loader timed out"
445 " len=%d c=%d\n", length, c);
455 act2000_isa_delay(HZ / 2);
456 return (act2000_isa_getid(card));