/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $
*
* Winbond W6692 specific routines
*
* Author Petr Novak
* Copyright by Petr Novak <petr.novak@i.cz>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/init.h>
#include "hisax.h"
#include "w6692.h"
#include "isdnl1.h"
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
/* table entry in the PCI devices list */
typedef struct {
int vendor_id;
int device_id;
char *vendor_name;
char *card_name;
} PCI_ENTRY;
static const PCI_ENTRY id_list[] =
{
{PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
{PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
{0, 0, "U.S.Robotics", "ISDN PCI Card TA"}
};
#define W6692_SV_USR 0x16ec
#define W6692_SD_USR 0x3409
#define W6692_WINBOND 0
#define W6692_DYNALINK 1
#define W6692_USR 2
static const char *w6692_revision = "$Revision: 1.18.2.4 $";
#define DBUSY_TIMER_VALUE 80
static char *W6692Ver[] =
{"W6692 V00", "W6692 V01", "W6692 V10",
"W6692 V11"};
static void
W6692Version(struct IsdnCardState *cs, char *s)
{
int val;
val = cs->readW6692(cs, W_D_RBCH);
printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]);
}
static void
ph_command(struct IsdnCardState *cs, unsigned int command)
{
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "ph_command %x", command);
cs->writeisac(cs, W_CIX, command);
}
static void
W6692_new_ph(struct IsdnCardState *cs)
{
switch (cs->dc.w6692.ph_state) {
case (W_L1CMD_RST):
ph_command(cs, W_L1CMD_DRC);
l1_msg(cs, HW_RESET | INDICATION, NULL);
/* fallthru */
case (W_L1IND_CD):
l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
break;
case (W_L1IND_DRD):
l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
break;
case (W_L1IND_CE):
l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
break;
case (W_L1IND_LD):
l1_msg(cs, HW_RSYNC | INDICATION, NULL);
break;
case (W_L1IND_ARD):
l1_msg(cs, HW_INFO2 | INDICATION, NULL);
break;
case (W_L1IND_AI8):
l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
break;
case (W_L1IND_AI10):
l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
break;
default:
break;
}
}
static void
W6692_bh(struct work_struct *work)
{
struct IsdnCardState *cs =
container_of(work, struct IsdnCardState, tqueue);
struct PStack *stptr;
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
if (cs->debug)
debugl1(cs, "D-Channel Busy cleared");
stptr = cs->stlist;
while (stptr != NULL) {
stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
stptr = stptr->next;
}
}
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
W6692_new_ph(cs);
if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
DChannel_proc_rcv(cs);
if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
DChannel_proc_xmt(cs);
/*
if (test_and_clear_bit(D_RX_MON1, &cs-&g