11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Winbond W6692 specific routines 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author Petr Novak 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright by Petr Novak <petr.novak@i.cz> 7475be4d85a274d0961593db41cf85689db1d583cJoe Perches * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hisax.h" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "w6692.h" 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isdnl1.h" 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 195a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* table entry in the PCI devices list */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct { 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int vendor_id; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int device_id; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *vendor_name; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *card_name; 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} PCI_ENTRY; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const PCI_ENTRY id_list[] = 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"}, 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"}, 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0, 0, "U.S.Robotics", "ISDN PCI Card TA"} 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W6692_SV_USR 0x16ec 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W6692_SD_USR 0x3409 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W6692_WINBOND 0 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W6692_DYNALINK 1 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define W6692_USR 2 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic const char *w6692_revision = "$Revision: 1.18.2.4 $"; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBUSY_TIMER_VALUE 80 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4667eb5db5874076db01febed5a1a9281628fa9fb4Karsten Keilstatic char *W6692Ver[] = 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{"W6692 V00", "W6692 V01", "W6692 V10", 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "W6692 V11"}; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5067eb5db5874076db01febed5a1a9281628fa9fb4Karsten Keilstatic void 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692Version(struct IsdnCardState *cs, char *s) 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = cs->readW6692(cs, W_D_RBCH); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsph_command(struct IsdnCardState *cs, unsigned int command) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_ISAC) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "ph_command %x", command); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeisac(cs, W_CIX, command); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692_new_ph(struct IsdnCardState *cs) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cs->dc.w6692.ph_state) { 72475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1CMD_RST): 73475be4d85a274d0961593db41cf85689db1d583cJoe Perches ph_command(cs, W_L1CMD_DRC); 74475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_RESET | INDICATION, NULL); 75475be4d85a274d0961593db41cf85689db1d583cJoe Perches /* fallthru */ 76475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1IND_CD): 77475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); 78475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 79475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1IND_DRD): 80475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); 81475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 82475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1IND_CE): 83475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_POWERUP | CONFIRM, NULL); 84475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 85475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1IND_LD): 86475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_RSYNC | INDICATION, NULL); 87475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 88475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1IND_ARD): 89475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_INFO2 | INDICATION, NULL); 90475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 91475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1IND_AI8): 92475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); 93475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 94475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (W_L1IND_AI10): 95475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL); 96475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 97475be4d85a274d0961593db41cf85689db1d583cJoe Perches default: 98475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 103c4028958b6ecad064b1a6303a6a5906d4fe48d73David HowellsW6692_bh(struct work_struct *work) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 105c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct IsdnCardState *cs = 106c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells container_of(work, struct IsdnCardState, tqueue); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *stptr; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "D-Channel Busy cleared"); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stptr = cs->stlist; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (stptr != NULL) { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stptr = stptr->next; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_new_ph(cs); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DChannel_proc_rcv(cs); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DChannel_proc_xmt(cs); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 125475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (test_and_clear_bit(D_RX_MON1, &cs->event)) 126475be4d85a274d0961593db41cf85689db1d583cJoe Perches arcofi_fsm(cs, ARCOFI_RX_END, NULL); 127475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (test_and_clear_bit(D_TX_MON1, &cs->event)) 128475be4d85a274d0961593db41cf85689db1d583cJoe Perches arcofi_fsm(cs, ARCOFI_TX_END, NULL); 129475be4d85a274d0961593db41cf85689db1d583cJoe Perches*/ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692_empty_fifo(struct IsdnCardState *cs, int count) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *ptr; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692_empty_fifo"); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692_empty_fifo overrun %d", 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->rcvidx + count); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->rcvidx = 0; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = cs->rcvbuf + cs->rcvidx; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->rcvidx += count; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->readW6692fifo(cs, ptr, count); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_ISAC_FIFO) { 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *t = cs->dlog; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t += sprintf(t, "W6692_empty_fifo cnt %d", count); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QuickHex(t, ptr, count); 15735a4a5733b0a8290de39558b82896ab795b108a7Kees Cook debugl1(cs, "%s", cs->dlog); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692_fill_fifo(struct IsdnCardState *cs) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count, more; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *ptr; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692_fill_fifo"); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cs->tx_skb) 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = cs->tx_skb->len; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count <= 0) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds more = 0; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count > W_D_FIFO_THRESH) { 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds more = !0; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = W_D_FIFO_THRESH; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = cs->tx_skb->data; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_pull(cs->tx_skb, count); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_cnt += count; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692fifo(cs, ptr, count); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692_fill_fifo dbusytimer running"); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&cs->dbusytimer); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&cs->dbusytimer); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&cs->dbusytimer); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_ISAC_FIFO) { 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *t = cs->dlog; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t += sprintf(t, "W6692_fill_fifo cnt %d", count); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QuickHex(t, ptr, count); 19935a4a5733b0a8290de39558b82896ab795b108a7Kees Cook debugl1(cs, "%s", cs->dlog); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692B_empty_fifo(struct BCState *bcs, int count) 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *ptr; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct IsdnCardState *cs = bcs->cs; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692B_empty_fifo"); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) { 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692B_empty_fifo: incoming packet too large"); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.rcvidx = 0; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.rcvidx += count; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READW6692BFIFO(cs, bcs->channel, ptr, count); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_HSCX_FIFO) { 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *t = bcs->blog; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t += sprintf(t, "W6692B_empty_fifo %c cnt %d", 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->channel + '1', count); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QuickHex(t, ptr, count); 22935a4a5733b0a8290de39558b82896ab795b108a7Kees Cook debugl1(cs, "%s", bcs->blog); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692B_fill_fifo(struct BCState *bcs) 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct IsdnCardState *cs = bcs->cs; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int more, count; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *ptr; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bcs->tx_skb) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->tx_skb->len <= 0) 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->tx_skb->len > W_B_FIFO_THRESH) { 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds more = 1; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = W_B_FIFO_THRESH; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = bcs->tx_skb->len; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) 253475be4d85a274d0961593db41cf85689db1d583cJoe Perches debugl1(cs, "W6692B_fill_fifo%s%d", (more ? " " : " last "), count); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = bcs->tx_skb->data; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_pull(bcs->tx_skb, count); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_cnt -= count; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.count += count; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITEW6692BFIFO(cs, bcs->channel, ptr, count); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_HSCX_FIFO) { 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *t = bcs->blog; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds t += sprintf(t, "W6692B_fill_fifo %c cnt %d", 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->channel + '1', count); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds QuickHex(t, ptr, count); 26735a4a5733b0a8290de39558b82896ab795b108a7Kees Cook debugl1(cs, "%s", bcs->blog); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692B_interrupt(struct IsdnCardState *cs, u_char bchan) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char val; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char r; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct BCState *bcs; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 280475be4d85a274d0961593db41cf85689db1d583cJoe Perches bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs + 1); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_bit(BC_FLG_INIT, &bcs->Flag)) { 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692B not INIT yet"); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_B_EXI_RME) { /* RME */ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) { 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 B STAR %x", r); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((r & W_B_STAR_RDOV) && bcs->mode) 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 B RDOV mode=%d", 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->mode); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r & W_B_STAR_CRCE) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 B CRC error"); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = W_B_FIFO_THRESH; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692B_empty_fifo(bcs, count); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((count = bcs->hw.w6692.rcvidx) > 0) { 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_HSCX_FIFO) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 Bchan Frame %d", count); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(skb = dev_alloc_skb(count))) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "W6692: Bchan receive out of memory\n"); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_tail(&bcs->rqueue, skb); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.rcvidx = 0; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(bcs, B_RCVBUFREADY); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_B_EXI_RMR) { /* RMR */ 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r & W_B_STAR_RDOV) { 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 325475be4d85a274d0961593db41cf85689db1d583cJoe Perches debugl1(cs, "W6692 B RDOV(RMR) mode=%d", bcs->mode); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->mode != L1_MODE_TRANS) 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.rcvidx = 0; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->mode == L1_MODE_TRANS) { 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* receive audio data */ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH))) 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: receive out of memory\n"); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_tail(&bcs->rqueue, skb); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.rcvidx = 0; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(bcs, B_RCVBUFREADY); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_B_EXI_XDUN) { /* XDUN */ 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 B EXIR %x Lost TX", val); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->mode == 1) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692B_fill_fifo(bcs); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Here we lost an TX interrupt, so 350475be4d85a274d0961593db41cf85689db1d583cJoe Perches * restart transmitting the whole frame. 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->tx_skb) { 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_push(bcs->tx_skb, bcs->hw.w6692.count); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_cnt += bcs->hw.w6692.count; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.count = 0; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_B_EXI_XFR) { /* XFR */ 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r & W_B_STAR_XDOW) { 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 B STAR %x XDOW", r); 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->tx_skb && (bcs->mode != 1)) { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_push(bcs->tx_skb, bcs->hw.w6692.count); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_cnt += bcs->hw.w6692.count; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.count = 0; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->tx_skb) { 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->tx_skb->len) { 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692B_fill_fifo(bcs); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 377475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) && 378475be4d85a274d0961593db41cf85689db1d583cJoe Perches (PACKET_NOACK != bcs->tx_skb->pkt_type)) { 379475be4d85a274d0961593db41cf85689db1d583cJoe Perches u_long flags; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&bcs->aclock, flags); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->ackcnt += bcs->hw.w6692.count; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&bcs->aclock, flags); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(bcs, B_ACKPENDING); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_irq(bcs->tx_skb); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.count = 0; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_skb = NULL; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.count = 0; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692B_fill_fifo(bcs); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(bcs, B_XMTBUFREADY); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t 4027d12e780e003f93433d49ce78cfedf4b4c52adc5David HowellsW6692_interrupt(int intno, void *dev_id) 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct IsdnCardState *cs = dev_id; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char val, exval, v1; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int count; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_long flags; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int icnt = 5; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&cs->lock, flags); 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = cs->readW6692(cs, W_ISTA); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!val) { 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&cs->lock, flags); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 417475be4d85a274d0961593db41cf85689db1d583cJoe PerchesStartW6692: 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_ISAC) 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 ISTA %x", val); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_INT_D_RME) { /* RME */ 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exval = cs->readW6692(cs, W_D_RSTA); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) { 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_RSTA_RDOV) 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 RDOV"); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_RSTA_CRCE) 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 D-channel CRC error"); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_RSTA_RMB) 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 D-channel ABORT"); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count == 0) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = W_D_FIFO_THRESH; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_empty_fifo(cs, count); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((count = cs->rcvidx) > 0) { 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->rcvidx = 0; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(skb = alloc_skb(count, GFP_ATOMIC))) 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: D receive out of memory\n"); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(skb_put(skb, count), cs->rcvbuf, count); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_tail(&cs->rq, skb); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->rcvidx = 0; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(cs, D_RCVBUFREADY); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_INT_D_RMR) { /* RMR */ 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_empty_fifo(cs, W_D_FIFO_THRESH); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_INT_D_XFR) { /* XFR */ 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&cs->dbusytimer); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(cs, D_CLEARBUSY); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->tx_skb) { 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->tx_skb->len) { 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_fill_fifo(cs); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto afterXFR; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_irq(cs->tx_skb); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_cnt = 0; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_skb = NULL; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cs->tx_skb = skb_dequeue(&cs->sq))) { 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_cnt = 0; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_fill_fifo(cs); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(cs, D_XMTBUFREADY); 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 476475be4d85a274d0961593db41cf85689db1d583cJoe PerchesafterXFR: 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & (W_INT_XINT0 | W_INT_XINT1)) { /* XINT0/1 - never */ 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_ISAC) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 spurious XINT!"); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_INT_D_EXI) { /* EXI */ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exval = cs->readW6692(cs, W_D_EXIR); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_WARN) 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 D_EXIR %02x", exval); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { /* Transmit underrun/collision */ 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 D-chan underrun/collision"); 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n"); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&cs->dbusytimer); 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(cs, D_CLEARBUSY); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->tx_skb) { /* Restart frame */ 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_push(cs->tx_skb, cs->tx_cnt); 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_cnt = 0; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_fill_fifo(cs); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n"); 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 XDUN/XCOL no skb"); 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_EXI_RDOV) { /* RDOV */ 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 D-channel RDOV"); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: W6692 D-RDOV\n"); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_EXI_TIN2) { /* TIN2 - never */ 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 spurious TIN2 interrupt"); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_EXI_MOC) { /* MOC - not supported */ 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 spurious MOC interrupt"); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1 = cs->readW6692(cs, W_MOSR); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 MOSR %02x", v1); 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */ 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1 = cs->readW6692(cs, W_CIR); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_ISAC) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 ISC CIR=0x%02X", v1); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (v1 & W_CIR_ICC) { 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_ISAC) 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_event(cs, D_L1STATECHANGE); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (v1 & W_CIR_SCC) { 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1 = cs->readW6692(cs, W_SQR); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 SCC SQR=0x%02X", v1); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_EXI_WEXP) { 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 spurious WEXP interrupt!"); 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exval & W_D_EXI_TEXP) { 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 spurious TEXP interrupt!"); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_INT_B1_EXI) { 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 B channel 1 interrupt"); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692B_interrupt(cs, 0); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val & W_INT_B2_EXI) { 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "W6692 B channel 2 interrupt"); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692B_interrupt(cs, 1); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = cs->readW6692(cs, W_ISTA); 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (val && icnt) { 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds icnt--; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto StartW6692; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!icnt) { 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "W6692 IRQ LOOP\n"); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_IMASK, 0xff); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&cs->lock, flags); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692_l1hw(struct PStack *st, int pr, void *arg) 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_long flags; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int val; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (pr) { 567475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_DATA | REQUEST): 568475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & DEB_DLOG_HEX) 569475be4d85a274d0961593db41cf85689db1d583cJoe Perches LogFrame(cs, skb->data, skb->len); 570475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & DEB_DLOG_VERBOSE) 571475be4d85a274d0961593db41cf85689db1d583cJoe Perches dlogframe(cs, skb, 0); 572475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&cs->lock, flags); 573475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->tx_skb) { 574475be4d85a274d0961593db41cf85689db1d583cJoe Perches skb_queue_tail(&cs->sq, skb); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef L2FRAME_DEBUG /* psa */ 576475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & L1_DEB_LAPD) 577475be4d85a274d0961593db41cf85689db1d583cJoe Perches Logl2Frame(cs, skb, "PH_DATA Queued", 0); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 579475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else { 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_skb = skb; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_cnt = 0; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef L2FRAME_DEBUG /* psa */ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_LAPD) 584475be4d85a274d0961593db41cf85689db1d583cJoe Perches Logl2Frame(cs, skb, "PH_DATA", 0); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_fill_fifo(cs); 587475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 588475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&cs->lock, flags); 589475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 590475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_PULL | INDICATION): 591475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&cs->lock, flags); 592475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->tx_skb) { 593475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & L1_DEB_WARN) 594475be4d85a274d0961593db41cf85689db1d583cJoe Perches debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); 595475be4d85a274d0961593db41cf85689db1d583cJoe Perches skb_queue_tail(&cs->sq, skb); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&cs->lock, flags); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 598475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 599475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & DEB_DLOG_HEX) 600475be4d85a274d0961593db41cf85689db1d583cJoe Perches LogFrame(cs, skb->data, skb->len); 601475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & DEB_DLOG_VERBOSE) 602475be4d85a274d0961593db41cf85689db1d583cJoe Perches dlogframe(cs, skb, 0); 603475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->tx_skb = skb; 604475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->tx_cnt = 0; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef L2FRAME_DEBUG /* psa */ 606475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & L1_DEB_LAPD) 607475be4d85a274d0961593db41cf85689db1d583cJoe Perches Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 609475be4d85a274d0961593db41cf85689db1d583cJoe Perches W6692_fill_fifo(cs); 610475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&cs->lock, flags); 611475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 612475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_PULL | REQUEST): 613475be4d85a274d0961593db41cf85689db1d583cJoe Perches#ifdef L2FRAME_DEBUG /* psa */ 614475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & L1_DEB_LAPD) 615475be4d85a274d0961593db41cf85689db1d583cJoe Perches debugl1(cs, "-> PH_REQUEST_PULL"); 616475be4d85a274d0961593db41cf85689db1d583cJoe Perches#endif 617475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (!cs->tx_skb) { 618475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 619475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); 620475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else 621475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 622475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 623475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (HW_RESET | REQUEST): 624475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&cs->lock, flags); 625475be4d85a274d0961593db41cf85689db1d583cJoe Perches if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) { 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ph_command(cs, W_L1CMD_ECK); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&cs->lock, flags); 628475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else { 629475be4d85a274d0961593db41cf85689db1d583cJoe Perches ph_command(cs, W_L1CMD_RST); 630475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->dc.w6692.ph_state = W_L1CMD_RST; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&cs->lock, flags); 632475be4d85a274d0961593db41cf85689db1d583cJoe Perches W6692_new_ph(cs); 633475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 634475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 635475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (HW_ENABLE | REQUEST): 636475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&cs->lock, flags); 637475be4d85a274d0961593db41cf85689db1d583cJoe Perches ph_command(cs, W_L1CMD_ECK); 638475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&cs->lock, flags); 639475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 640475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (HW_INFO3 | REQUEST): 641475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&cs->lock, flags); 642475be4d85a274d0961593db41cf85689db1d583cJoe Perches ph_command(cs, W_L1CMD_AR8); 643475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&cs->lock, flags); 644475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 645475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (HW_TESTLOOP | REQUEST): 646475be4d85a274d0961593db41cf85689db1d583cJoe Perches val = 0; 647475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (1 & (long) arg) 648475be4d85a274d0961593db41cf85689db1d583cJoe Perches val |= 0x0c; 649475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (2 & (long) arg) 650475be4d85a274d0961593db41cf85689db1d583cJoe Perches val |= 0x3; 651475be4d85a274d0961593db41cf85689db1d583cJoe Perches /* !!! not implemented yet */ 652475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 653475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (HW_DEACTIVATE | RESPONSE): 654475be4d85a274d0961593db41cf85689db1d583cJoe Perches skb_queue_purge(&cs->rq); 655475be4d85a274d0961593db41cf85689db1d583cJoe Perches skb_queue_purge(&cs->sq); 656475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->tx_skb) { 657475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_kfree_skb_any(cs->tx_skb); 658475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->tx_skb = NULL; 659475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 660475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) 661475be4d85a274d0961593db41cf85689db1d583cJoe Perches del_timer(&cs->dbusytimer); 662475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) 663475be4d85a274d0961593db41cf85689db1d583cJoe Perches schedule_event(cs, D_CLEARBUSY); 664475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 665475be4d85a274d0961593db41cf85689db1d583cJoe Perches default: 666475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->debug & L1_DEB_WARN) 667475be4d85a274d0961593db41cf85689db1d583cJoe Perches debugl1(cs, "W6692_l1hw unknown %04x", pr); 668475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_W6692(struct PStack *st, struct IsdnCardState *cs) 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l1.l1hw = W6692_l1hw; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDC_Close_W6692(struct IsdnCardState *cs) 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdbusy_timer_handler(struct IsdnCardState *cs) 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct PStack *stptr; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rbch, star; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_long flags; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&cs->lock, flags); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rbch = cs->readW6692(cs, W_D_RBCH); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds star = cs->readW6692(cs, W_D_STAR); 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug) 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x", 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rbch, star); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (star & W_D_STAR_XBZ) { /* D-Channel Busy */ 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stptr = cs->stlist; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (stptr != NULL) { 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stptr = stptr->next; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* discard frame; reset transceiver */ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->tx_skb) { 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_any(cs->tx_skb); 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_cnt = 0; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->tx_skb = NULL; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n"); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "D-Channel Busy no skb"); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&cs->lock, flags); 7177d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells cs->irq_func(cs->irq, cs); 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&cs->lock, flags); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692Bmode(struct BCState *bcs, int mode, int bchan) 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct IsdnCardState *cs = bcs->cs; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->debug & L1_DEB_HSCX) 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds debugl1(cs, "w6692 %c mode %d ichan %d", 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds '1' + bchan, mode, bchan); 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->mode = mode; 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->channel = bchan; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.bchan = bchan; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (mode) { 737475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (L1_MODE_NULL): 738475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0); 739475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 740475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (L1_MODE_TRANS): 741475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS); 742475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 743475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (L1_MODE_HDLC): 744475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF); 745475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff); 746475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff); 747475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mode) 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST | 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W_B_CMDR_RACT | W_B_CMDR_XRST); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsW6692_l2l1(struct PStack *st, int pr, void *arg) 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = arg; 759475be4d85a274d0961593db41cf85689db1d583cJoe Perches struct BCState *bcs = st->l1.bcs; 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_long flags; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (pr) { 763475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_DATA | REQUEST): 764475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&bcs->cs->lock, flags); 765475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (bcs->tx_skb) { 766475be4d85a274d0961593db41cf85689db1d583cJoe Perches skb_queue_tail(&bcs->squeue, skb); 767475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else { 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_skb = skb; 769475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.count = 0; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->cs->BC_Send_Data(bcs); 772475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 773475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&bcs->cs->lock, flags); 774475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 775475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_PULL | INDICATION): 776475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (bcs->tx_skb) { 777475be4d85a274d0961593db41cf85689db1d583cJoe Perches printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n"); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 779475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 780475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&bcs->cs->lock, flags); 781475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); 782475be4d85a274d0961593db41cf85689db1d583cJoe Perches bcs->tx_skb = skb; 783475be4d85a274d0961593db41cf85689db1d583cJoe Perches bcs->hw.w6692.count = 0; 784475be4d85a274d0961593db41cf85689db1d583cJoe Perches bcs->cs->BC_Send_Data(bcs); 785475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&bcs->cs->lock, flags); 786475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 787475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_PULL | REQUEST): 788475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (!bcs->tx_skb) { 789475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 790475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); 791475be4d85a274d0961593db41cf85689db1d583cJoe Perches } else 792475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); 793475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 794475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_ACTIVATE | REQUEST): 795475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&bcs->cs->lock, flags); 796475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); 797475be4d85a274d0961593db41cf85689db1d583cJoe Perches W6692Bmode(bcs, st->l1.mode, st->l1.bc); 798475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&bcs->cs->lock, flags); 799475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg_b(st, pr, arg); 800475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 801475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_DEACTIVATE | REQUEST): 802475be4d85a274d0961593db41cf85689db1d583cJoe Perches l1_msg_b(st, pr, arg); 803475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 804475be4d85a274d0961593db41cf85689db1d583cJoe Perches case (PH_DEACTIVATE | CONFIRM): 805475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_lock_irqsave(&bcs->cs->lock, flags); 806475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); 807475be4d85a274d0961593db41cf85689db1d583cJoe Perches test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 808475be4d85a274d0961593db41cf85689db1d583cJoe Perches W6692Bmode(bcs, 0, st->l1.bc); 809475be4d85a274d0961593db41cf85689db1d583cJoe Perches spin_unlock_irqrestore(&bcs->cs->lock, flags); 810475be4d85a274d0961593db41cf85689db1d583cJoe Perches st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); 811475be4d85a274d0961593db41cf85689db1d583cJoe Perches break; 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsclose_w6692state(struct BCState *bcs) 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692Bmode(bcs, 0, bcs->channel); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { 8203c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl kfree(bcs->hw.w6692.rcvbuf); 8213c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl bcs->hw.w6692.rcvbuf = NULL; 8223c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl kfree(bcs->blog); 8233c7208f253571ee5f157b98f0e315b5172afe092Jesper Juhl bcs->blog = NULL; 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&bcs->rqueue); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&bcs->squeue); 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bcs->tx_skb) { 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_any(bcs->tx_skb); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_skb = NULL; 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsopen_w6692state(struct IsdnCardState *cs, struct BCState *bcs) 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "HiSax: No memory for w6692.rcvbuf\n"); 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (1); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "HiSax: No memory for bcs->blog\n"); 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(bcs->hw.w6692.rcvbuf); 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.rcvbuf = NULL; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (2); 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_head_init(&bcs->rqueue); 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_head_init(&bcs->squeue); 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_skb = NULL; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->event = 0; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->hw.w6692.rcvidx = 0; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->tx_cnt = 0; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_w6692(struct PStack *st, struct BCState *bcs) 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->channel = st->l1.bc; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (open_w6692state(st->l1.hardware, bcs)) 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-1); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l1.bcs = bcs; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st->l2.l2l1 = W6692_l2l1; 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setstack_manager(st); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bcs->st = st; 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setstack_l1_B(st); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 877672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void resetW6692(struct IsdnCardState *cs) 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(10); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CTL, 0x00); 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(10); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_IMASK, 0xff); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_SAM, 0xff); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_TAM, 0xff); 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_EXIM, 0x00); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT); 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_IMASK, 0x18); 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->subtyp == W6692_USR) { 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* seems that USR implemented some power control features 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pin 79 is connected to the oscilator circuit so we 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * have to handle it here 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_PCTL, 0x80); 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_XDATA, 0x00); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89967eb5db5874076db01febed5a1a9281628fa9fb4Karsten Keilstatic void initW6692(struct IsdnCardState *cs, int part) 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (part & 1) { 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->setstack_d = setstack_W6692; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->DC_Close = DC_Close_W6692; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->dbusytimer.function = (void *) dbusy_timer_handler; 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->dbusytimer.data = (long) cs; 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&cs->dbusytimer); 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resetW6692(cs); 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ph_command(cs, W_L1CMD_RST); 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->dc.w6692.ph_state = W_L1CMD_RST; 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692_new_ph(cs); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ph_command(cs, W_L1CMD_ECK); 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->bcs[0].BC_SetStack = setstack_w6692; 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->bcs[1].BC_SetStack = setstack_w6692; 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->bcs[0].BC_Close = close_w6692state; 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->bcs[1].BC_Close = close_w6692state; 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692Bmode(cs->bcs, 0, 0); 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692Bmode(cs->bcs + 1, 0, 0); 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (part & 2) { 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reenable all IRQ */ 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_IMASK, 0x18); 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_EXIM, 0x00); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00); 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset D-chan receiver and transmitter */ 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Interface functions */ 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_char 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsReadW6692(struct IsdnCardState *cs, u_char offset) 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (inb(cs->hw.w6692.iobase + offset)); 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsWriteW6692(struct IsdnCardState *cs, u_char offset, u_char value) 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(value, cs->hw.w6692.iobase + offset); 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 946475be4d85a274d0961593db41cf85689db1d583cJoe PerchesReadISACfifo(struct IsdnCardState *cs, u_char *data, int size) 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 952475be4d85a274d0961593db41cf85689db1d583cJoe PerchesWriteISACfifo(struct IsdnCardState *cs, u_char *data, int size) 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_char 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset) 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset)); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsWriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value) 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsw6692_card_msg(struct IsdnCardState *cs, int mt, void *arg) 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (mt) { 973475be4d85a274d0961593db41cf85689db1d583cJoe Perches case CARD_RESET: 974475be4d85a274d0961593db41cf85689db1d583cJoe Perches resetW6692(cs); 975475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (0); 976475be4d85a274d0961593db41cf85689db1d583cJoe Perches case CARD_RELEASE: 977475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->writeW6692(cs, W_IMASK, 0xff); 978475be4d85a274d0961593db41cf85689db1d583cJoe Perches release_region(cs->hw.w6692.iobase, 256); 979475be4d85a274d0961593db41cf85689db1d583cJoe Perches if (cs->subtyp == W6692_USR) { 980475be4d85a274d0961593db41cf85689db1d583cJoe Perches cs->writeW6692(cs, W_XDATA, 0x04); 981475be4d85a274d0961593db41cf85689db1d583cJoe Perches } 982475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (0); 983475be4d85a274d0961593db41cf85689db1d583cJoe Perches case CARD_INIT: 984475be4d85a274d0961593db41cf85689db1d583cJoe Perches initW6692(cs, 3); 985475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (0); 986475be4d85a274d0961593db41cf85689db1d583cJoe Perches case CARD_TEST: 987475be4d85a274d0961593db41cf85689db1d583cJoe Perches return (0); 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 992475be4d85a274d0961593db41cf85689db1d583cJoe Perchesstatic int id_idx; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 994ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanstatic struct pci_dev *dev_w6692 = NULL; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 996ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanint setup_w6692(struct IsdnCard *card) 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct IsdnCardState *cs = card->cs; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char tmp[64]; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char found = 0; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char pci_irq = 0; 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int pci_ioaddr = 0; 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(tmp, w6692_revision); 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->typ != ISDN_CTYPE_W6692) 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 1008bfc7c89f068bbbc2c48588385529d15c6feef802Jeff Garzik 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (id_list[id_idx].vendor_id) { 101041a68a748bbc61f5bcea999e33ba72926dfbe6f7Tilman Schmidt dev_w6692 = hisax_find_pci_device(id_list[id_idx].vendor_id, 1011475be4d85a274d0961593db41cf85689db1d583cJoe Perches id_list[id_idx].device_id, 1012475be4d85a274d0961593db41cf85689db1d583cJoe Perches dev_w6692); 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev_w6692) { 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pci_enable_device(dev_w6692)) 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->subtyp = id_idx; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_idx++; 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev_w6692) { 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found = 1; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_irq = dev_w6692->irq; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* I think address 0 is allways the configuration area */ 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* and address 1 is the real IO space KKe 03.09.99 */ 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_ioaddr = pci_resource_start(dev_w6692, 1); 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* USR ISDN PCI card TA need some special handling */ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cs->subtyp == W6692_WINBOND) { 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((W6692_SV_USR == dev_w6692->subsystem_vendor) && 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (W6692_SD_USR == dev_w6692->subsystem_device)) { 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->subtyp = W6692_USR; 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!found) { 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "W6692: No PCI card found\n"); 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->irq = pci_irq; 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cs->irq) { 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pci_ioaddr) { 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->hw.w6692.iobase = pci_ioaddr; 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_ioaddr, pci_irq); 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name)) { 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "HiSax: %s I/O ports %x-%x already in use\n", 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_list[cs->subtyp].card_name, 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->hw.w6692.iobase, 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->hw.w6692.iobase + 255); 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (0); 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "HiSax: %s config irq:%d I/O:%x\n", 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id_list[cs->subtyp].card_name, cs->irq, 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->hw.w6692.iobase); 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1066c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&cs->tqueue, W6692_bh); 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->readW6692 = &ReadW6692; 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeW6692 = &WriteW6692; 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->readisacfifo = &ReadISACfifo; 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->writeisacfifo = &WriteISACfifo; 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Read_Reg = &ReadW6692B; 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Write_Reg = &WriteW6692B; 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->BC_Send_Data = &W6692B_fill_fifo; 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->cardmsg = &w6692_card_msg; 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cs->irq_func = &W6692_interrupt; 10769ba02bec3888d391bad0fb0a8dd584f88eed6c8dThomas Gleixner cs->irq_flags |= IRQF_SHARED; 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds W6692Version(cs, "W6692:"); 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR)); 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM)); 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA)); 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (1); 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1085