Commit df081c08 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linux-isdn.bkbits.net/linux-2.5.isdn

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 339bf945 13ba7935
...@@ -343,12 +343,16 @@ static int __devinit b1pci_pci_probe(struct pci_dev *pdev, ...@@ -343,12 +343,16 @@ static int __devinit b1pci_pci_probe(struct pci_dev *pdev,
static void __devexit b1pci_pci_remove(struct pci_dev *pdev) static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
{ {
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
avmcard *card = pci_get_drvdata(pdev); avmcard *card = pci_get_drvdata(pdev);
if (card->dma) if (card->dma)
b1pciv4_remove(pdev); b1pciv4_remove(pdev);
else else
b1pci_remove(pdev); b1pci_remove(pdev);
#else
b1pci_remove(pdev);
#endif
} }
static struct pci_driver b1pci_pci_driver = { static struct pci_driver b1pci_pci_driver = {
......
/* $Id: amd7930.c,v 1.5.6.4 2001/09/23 22:24:46 kai Exp $
*
* HiSax ISDN driver - chip specific routines for AMD 7930
*
* Author Brent Baccala
* Copyright by Brent Baccala <baccala@FreeSoft.org>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* - Existing ISDN HiSax driver provides all the smarts
* - it compiles, runs, talks to an isolated phone switch, connects
* to a Cisco, pings go through
* - AMD 7930 support only (no DBRI yet)
* - no US NI-1 support (may not work on US phone system - untested)
* - periodic packet loss, apparently due to lost interrupts
* - ISDN sometimes freezes, requiring reboot before it will work again
*
* The code is unreliable enough to be consider alpha
*
* This file is (c) under GNU General Public License
*
* Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
* SparcStation 1+. The chip provides microphone and speaker interfaces
* which provide mono-channel audio at 8K samples per second via either
* 8-bit A-law or 8-bit mu-law encoding. Also, the chip features an
* ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
* which performs basic D channel LAPD processing and provides raw
* B channel data. The digital audio channel, the two ISDN B channels,
* and two 64 Kbps channels to the microprocessor are all interconnected
* via a multiplexer.
*
* This driver interfaces to the Linux HiSax ISDN driver, which performs
* all high-level Q.921 and Q.931 ISDN functions. The file is not
* itself a hardware driver; rather it uses functions exported by
* the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
* allowing the chip to be simultaneously used for both audio and ISDN data.
* The hardware driver does _no_ buffering, but provides several callbacks
* which are called during interrupt service and should therefore run quickly.
*
* D channel transmission is performed by passing the hardware driver the
* address and size of an skb's data area, then waiting for a callback
* to signal successful transmission of the packet. A task is then
* queued to notify the HiSax driver that another packet may be transmitted.
*
* D channel reception is quite simple, mainly because of:
* 1) the slow speed of the D channel - 16 kbps, and
* 2) the presence of an 8- or 32-byte (depending on chip version) FIFO
* to buffer the D channel data on the chip
* Worst case scenario of back-to-back packets with the 8 byte buffer
* at 16 kbps yields an service time of 4 ms - long enough to preclude
* the need for fancy buffering. We queue a background task that copies
* data out of the receive buffer into an skb, and the hardware driver
* simply does nothing until we're done with the receive buffer and
* reset it for a new packet.
*
* B channel processing is more complex, because of:
* 1) the faster speed - 64 kbps,
* 2) the lack of any on-chip buffering (it interrupts for every byte), and
* 3) the lack of any chip support for HDLC encapsulation
*
* The HiSax driver can put each B channel into one of three modes -
* L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
* and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
* L1_MODE_HDLC is the most common, used for almost all "pure" digital
* data sessions. L1_MODE_TRANS is used for ISDN audio.
*
* HDLC B channel transmission is performed via a large buffer into
* which the skb is copied while performing HDLC bit-stuffing. A CRC
* is computed and attached to the end of the buffer, which is then
* passed to the low-level routines for raw transmission. Once
* transmission is complete, the hardware driver is set to enter HDLC
* idle by successive transmission of mark (all 1) bytes, waiting for
* the ISDN driver to prepare another packet for transmission and
* deliver it.
*
* HDLC B channel reception is performed via an X-byte ring buffer
* divided into N sections of X/N bytes each. Defaults: X=256 bytes, N=4.
* As the hardware driver notifies us that each section is full, we
* hand it the next section and schedule a background task to peruse
* the received section, bit-by-bit, with an HDLC decoder. As
* packets are detected, they are copied into a large buffer while
* decoding HDLC bit-stuffing. The ending CRC is verified, and if
* it is correct, we alloc a new skb of the correct length (which we
* now know), copy the packet into it, and hand it to the upper layers.
* Optimization: for large packets, we hand the buffer (which also
* happens to be an skb) directly to the upper layer after an skb_trim,
* and alloc a new large buffer for future packets, thus avoiding a copy.
* Then we return to HDLC processing; state is saved between calls.
*
*/
#include "hisax.h"
#include "../../sbus/audio/amd7930.h"
#include "isac.h"
#include "isdnl1.h"
#include "rawhdlc.h"
#include <linux/interrupt.h>
static const char *amd7930_revision = "$Revision: 1.5.6.4 $";
#define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */
#define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into
* (must divide RCV_BUFSIZE) */
static void Bchan_fill_fifo(struct BCState *, struct sk_buff *);
static void
Bchan_xmt_bh(void *data)
{
struct BCState *bcs = data;
struct sk_buff *skb;
if (bcs->hw.amd7930.tx_skb != NULL) {
dev_kfree_skb(bcs->hw.amd7930.tx_skb);
bcs->hw.amd7930.tx_skb = NULL;
}
xmit_ready_b(bcs);
}
static void
Bchan_xmit_callback(struct BCState *bcs)
{
schedule_work(&bcs->hw.amd7930.xmt_work);
}
/* B channel transmission: two modes (three, if you count L1_MODE_NULL)
*
* L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
* the packet (i.e. make_raw_hdlc_data). Since this can be a
* time-consuming operation, our completion callback just schedules
* a bottom half to do encapsulation for the next packet. In between,
* the link will just idle
*
* L1_MODE_TRANS - Data goes through, well, transparent. No HDLC encap,
* and we can't just let the link idle, so the "bottom half" actually
* gets called during the top half (it's our callback routine in this case),
* but it's a lot faster now since we don't call make_raw_hdlc_data
*/
static void
Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb)
{
struct IsdnCardState *cs = bcs->cs;
int len;
if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
char tmp[1024];
char *t = tmp;
t += sprintf(t, "amd7930_fill_fifo %c cnt %d",
bcs->channel ? 'B' : 'A', skb->len);
if (cs->debug & L1_DEB_HSCX_FIFO)
QuickHex(t, skb->data, skb->len);
debugl1(cs, tmp);
}
if (bcs->mode == L1_MODE_HDLC) {
len = make_raw_hdlc_data(skb->data, skb->len,
bcs->hw.amd7930.tx_buff, RAW_BUFMAX);
if (len > 0)
amd7930_bxmit(0, bcs->channel,
bcs->hw.amd7930.tx_buff, len,
(void *) &Bchan_xmit_callback,
(void *) bcs);
dev_kfree_skb(skb);
} else if (bcs->mode == L1_MODE_TRANS) {
amd7930_bxmit(0, bcs->channel,
bcs->hw.amd7930.tx_buff, skb->len,
(void *) &Bchan_xmt_bh,
(void *) bcs);
bcs->hw.amd7930.tx_skb = skb;
} else {
dev_kfree_skb(skb);
}
}
static void
Bchan_mode(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
if (cs->debug & L1_DEB_HSCX) {
char tmp[40];
sprintf(tmp, "AMD 7930 mode %d bchan %d/%d",
mode, bc, bcs->channel);
debugl1(cs, tmp);
}
bcs->mode = mode;
}
/* Bchan_l2l1 is the entry point for upper layer routines that want to
* transmit on the B channel. PH_DATA_REQ is a normal packet that
* we either start transmitting (if idle) or queue (if busy).
* PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
* once the link is idle. After a "pull" callback, the upper layer
* routines can use PH_PULL_IND to send data.
*/
static void
Bchan_l2l1(struct PStack *st, int pr, void *arg)
{
struct sk_buff *skb = arg;
switch (pr) {
case (PH_DATA_REQ):
if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
skb_queue_tail(&st->l1.bcs->squeue, skb);
} else {
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
Bchan_fill_fifo(st->l1.bcs, skb);
}
break;
case (PH_PULL_IND):
if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
printk(KERN_WARNING "amd7930: this shouldn't happen\n");
break;
}
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
Bchan_fill_fifo(st->l1.bcs, skb);
break;
case (PH_PULL_REQ):
if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL_CNF, NULL);
} else
set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
}
}
/* Receiver callback and bottom half - decodes HDLC at leisure (if
* L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue. If
* a large packet is received, stick rv_skb (the buffer that the
* packet has been decoded into) on the receive queue and alloc a new
* (large) skb to act as buffer for future receives. If a small
* packet is received, leave rv_skb alone, alloc a new skb of the
* correct size, and copy the packet into it
*/
static void
Bchan_recv_callback(struct BCState *bcs)
{
struct amd7930_hw *hw = &bcs->hw.amd7930;
hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS;
hw->rv_buff_in %= RCV_BUFSIZE;
if (hw->rv_buff_in != hw->rv_buff_out) {
amd7930_brecv(0, bcs->channel,
hw->rv_buff + hw->rv_buff_in,
RCV_BUFSIZE/RCV_BUFBLKS,
(void *) &Bchan_recv_callback, (void *) bcs);
}
schedule_work(&hw->rcv_work);
}
static void
Bchan_rcv_bh(void *data)
{
struct BCState *bcs = data;
struct IsdnCardState *cs = bcs->cs;
struct amd7930_hw *hw = &bcs->hw.amd7930;
struct sk_buff *skb;
int len;
if (cs->debug & L1_DEB_HSCX) {
char tmp[1024];
sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)",
hw->rv_buff_in, hw->rv_buff_out);
debugl1(cs, tmp);
QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
RCV_BUFSIZE/RCV_BUFBLKS);
debugl1(cs, tmp);
}
do {
if (bcs->mode == L1_MODE_HDLC) {
while ((len = read_raw_hdlc_data(hw->hdlc_state,
hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS,
hw->rv_skb->tail, HSCX_BUFMAX))) {
if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) {
char tmp[1024];
char *t = tmp;
t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len);
QuickHex(t, hw->rv_skb->tail, len);
debugl1(cs, tmp);
}
if (len > HSCX_BUFMAX/2) {
/* Large packet received */
if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) {
printk(KERN_WARNING "amd7930: receive out of memory");
} else {
skb_put(hw->rv_skb, len);
skb_queue_tail(&bcs->rqueue, hw->rv_skb);
hw->rv_skb = skb;
bcs->event |= 1 << B_RCVBUFREADY;
schedule_work(&bcs->work);
}
} else if (len > 0) {
/* Small packet received */
if (!(skb = dev_alloc_skb(len))) {
printk(KERN_WARNING "amd7930: receive out of memory\n");
} else {
memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
skb_queue_tail(&bcs->rqueue, skb);
bcs->event |= 1 << B_RCVBUFREADY;
schedule_work(&bcs->work);
}
} else {
/* Reception Error */
/* printk("amd7930: B channel receive error\n"); */
}
}
} else if (bcs->mode == L1_MODE_TRANS) {
if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) {
printk(KERN_WARNING "amd7930: receive out of memory\n");
} else {
memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS),
hw->rv_buff + hw->rv_buff_out,
RCV_BUFSIZE/RCV_BUFBLKS);
skb_queue_tail(&bcs->rqueue, skb);
bcs->event |= 1 << B_RCVBUFREADY;
schedule_work(&bcs->work);
}
}
if (hw->rv_buff_in == hw->rv_buff_out) {
/* Buffer was filled up - need to restart receiver */
amd7930_brecv(0, bcs->channel,
hw->rv_buff + hw->rv_buff_in,
RCV_BUFSIZE/RCV_BUFBLKS,
(void *) &Bchan_recv_callback,
(void *) bcs);
}
hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS;
hw->rv_buff_out %= RCV_BUFSIZE;
} while (hw->rv_buff_in != hw->rv_buff_out);
}
static void
Bchan_close(struct BCState *bcs)
{
struct sk_buff *skb;
Bchan_mode(bcs, 0, 0);
amd7930_bclose(0, bcs->channel);
if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
}
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
}
static int
Bchan_open(struct BCState *bcs)
{
struct amd7930_hw *hw = &bcs->hw.amd7930;
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
skb_queue_head_init(&bcs->rqueue);
skb_queue_head_init(&bcs->squeue);
}
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
amd7930_bopen(0, bcs->channel, 0xff);
hw->rv_buff_in = 0;
hw->rv_buff_out = 0;
hw->tx_skb = NULL;
init_hdlc_state(hw->hdlc_state, 0);
amd7930_brecv(0, bcs->channel,
hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS,
(void *) &Bchan_recv_callback, (void *) bcs);
bcs->event = 0;
bcs->tx_cnt = 0;
return (0);
}
static void
Bchan_init(struct BCState *bcs)
{
if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for amd7930.tx_buff\n");
return;
}
if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for amd7930.rv_buff\n");
return;
}
if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
printk(KERN_WARNING
"HiSax: No memory for amd7930.rv_skb\n");
return;
}
if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state),
GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for amd7930.hdlc_state\n");
return;
}
INIT_WORK(&bcs->hw.amd7930.rcv_work, &Bchan_rcv_bh, bcs);
INIT_WORK(&bcs->hw.amd7930.xmt_work, &Bchan_xmt_bh, bcs);
}
static void
Bchan_manl1(struct PStack *st, int pr,
void *arg)
{
switch (pr) {
case (PH_ACTIVATE_REQ):
test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
break;
case (PH_DEACTIVATE_REQ):
if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
Bchan_mode(st->l1.bcs, 0, 0);
test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
break;
}
}
int
setstack_amd7930(struct PStack *st, struct BCState *bcs)
{
if (Bchan_open(bcs))
return (-1);
st->l1.bcs = bcs;
st->l2.l2l1 = Bchan_l2l1;
st->ma.manl1 = Bchan_manl1;
setstack_manager(st);
bcs->st = st;
return (0);
}
static void
amd7930_drecv_callback(void *arg, int error, unsigned int count)
{
struct IsdnCardState *cs = (struct IsdnCardState *) arg;
static struct work_struct task;
struct sk_buff *skb;
/* NOTE: This function is called directly from an interrupt handler */
if (1) {
if (!(skb = alloc_skb(count, GFP_ATOMIC)))
printk(KERN_WARNING "HiSax: D receive out of memory\n");
else {
memcpy(skb_put(skb, count), cs->rcvbuf, count);
skb_queue_tail(&cs->rq, skb);
}
INIT_WORK(&task, (void *) DChannel_proc_rcv, (void *) cs);
schedule_work(&task);
}
if (cs->debug & L1_DEB_ISAC_FIFO) {
char tmp[128];
char *t = tmp;
t += sprintf(t, "amd7930 Drecv cnt %d", count);
if (error) t += sprintf(t, " ERR %x", error);
QuickHex(t, cs->rcvbuf, count);
debugl1(cs, tmp);
}
amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
&amd7930_drecv_callback, cs);
}
static void
amd7930_dxmit_callback(void *arg, int error)
{
struct IsdnCardState *cs = (struct IsdnCardState *) arg;
static struct work_struct task;
/* NOTE: This function is called directly from an interrupt handler */
/* may wish to do retransmission here, if error indicates collision */
if (cs->debug & L1_DEB_ISAC_FIFO) {
char tmp[128];
char *t = tmp;
t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len);
if (error) t += sprintf(t, " ERR %x", error);
QuickHex(t, cs->tx_skb->data, cs->tx_skb->len);
debugl1(cs, tmp);
}
cs->tx_skb = NULL;
INIT_WORK(&task, (void *) DChannel_proc_xmt, (void *) cs);
schedule_work(&task);
}
static void
amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg)
{
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
struct sk_buff *skb = arg;
char str[64];
switch (pr) {
case (PH_DATA_REQ):
if (cs->tx_skb) {
skb_queue_tail(&cs->sq, skb);
#ifdef L2FRAME_DEBUG /* psa */
if (cs->debug & L1_DEB_LAPD)
Logl2Frame(cs, skb, "PH_DATA Queued", 0);
#endif
} else {
if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
/* I-FRAME */
LogFrame(cs, skb->data, skb->len);
sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
dlogframe(cs, skb->data+4, skb->len-4,
str);
}
cs->tx_skb = skb;
cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG /* psa */
if (cs->debug & L1_DEB_LAPD)
Logl2Frame(cs, skb, "PH_DATA", 0);
#endif
amd7930_dxmit(0, skb->data, skb->len,
&amd7930_dxmit_callback, cs);
}
break;
case (PH_PULL_IND):
if (cs->tx_skb) {
if (cs->debug & L1_DEB_WARN)
debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
skb_queue_tail(&cs->sq, skb);
break;
}
if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */
LogFrame(cs, skb->data, skb->len);
sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
dlogframe(cs, skb->data + 4, skb->len - 4,
str);
}
cs->tx_skb = skb;
cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG /* psa */
if (cs->debug & L1_DEB_LAPD)
Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
#endif
amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
&amd7930_dxmit_callback, cs);
break;
case (PH_PULL_REQ):
#ifdef L2FRAME_DEBUG /* psa */
if (cs->debug & L1_DEB_LAPD)
debugl1(cs, "-> PH_REQUEST_PULL");
#endif
if (!cs->tx_skb) {
test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
st->l1.l1l2(st, PH_PULL_CNF, NULL);
} else
test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
break;
}
}
int
setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs)
{
st->l2.l2l1 = amd7930_Dchan_l2l1;
if (! cs->rcvbuf) {
printk("setDstack_amd7930: No cs->rcvbuf!\n");
} else {
amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
&amd7930_drecv_callback, cs);
}
return (0);
}
static void
manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
struct PStack *st;
st = cs->stlist;
while (st) {
st->ma.manl1(st, msg, arg);
st = st->next;
}
}
static void
amd7930_new_ph(struct IsdnCardState *cs)
{
switch (amd7930_get_liu_state(0)) {
case 3:
manl1_msg(cs, PH_POWERUP_CNF, NULL);
break;
case 7:
manl1_msg(cs, PH_I4_P8_IND, NULL);
break;
case 8:
manl1_msg(cs, PH_RSYNC_IND, NULL);
break;
}
}
/* amd7930 LIU state change callback */
static void
amd7930_liu_callback(struct IsdnCardState *cs)
{
static struct work_struct task;
if (!cs)
return;
if (cs->debug & L1_DEB_ISAC) {
char tmp[32];
sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0));
debugl1(cs, tmp);
}
INIT_WORK(&task, (void *) &amd7930_new_ph, (void *) cs);
schedule_work(&task);
}
void
amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
{
u8 val;
char tmp[32];
if (cs->debug & L1_DEB_ISAC) {
char tmp[32];
sprintf(tmp, "amd7930_l1cmd msg %x", msg);
debugl1(cs, tmp);
}
switch(msg) {
case PH_RESET_REQ:
if (amd7930_get_liu_state(0) <= 3)
amd7930_liu_activate(0,0);
else
amd7930_liu_deactivate(0);
break;
case PH_ENABLE_REQ:
break;
case PH_INFO3_REQ:
amd7930_liu_activate(0,0);
break;
case PH_TESTLOOP_REQ:
break;
default:
if (cs->debug & L1_DEB_WARN) {
sprintf(tmp, "amd7930_l1cmd unknown %4x", msg);
debugl1(cs, tmp);
}
break;
}
}
static void init_amd7930(struct IsdnCardState *cs)
{
Bchan_init(&cs->bcs[0]);
Bchan_init(&cs->bcs[1]);
cs->bcs[0].BC_SetStack = setstack_amd7930;
cs->bcs[1].BC_SetStack = setstack_amd7930;
cs->bcs[0].BC_Close = Bchan_close;
cs->bcs[1].BC_Close = Bchan_close;
Bchan_mode(cs->bcs, 0, 0);
Bchan_mode(cs->bcs + 1, 0, 0);
}
static int
amd7930_init(struct IsdnCardState *cs)
{
cs->l1cmd = amd7930_l1cmd;
amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
init_amd7930(cs);
return 0;
}
static struct card_ops amd7930_ops = {
.init = amd7930_init,
};
int __init
setup_amd7930(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, amd7930_revision);
printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp));
cs->irq = amd7930_get_irqnum(0);
if (cs->irq == 0)
return 0;
cs->card_ops = &amd7930_ops;
return 1;
}
...@@ -231,6 +231,51 @@ static struct card_ops asuscom_ipac_ops = { ...@@ -231,6 +231,51 @@ static struct card_ops asuscom_ipac_ops = {
.irq_func = ipac_irq, .irq_func = ipac_irq,
}; };
static int __init
asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
int rc;
u8 val;
printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n",
card->para[1], card->para[0]);
cs->hw.asus.cfg_reg = card->para[1];
cs->irq = card->para[0];
rc = -EBUSY;
if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn"))
goto err;
rc = -ENODEV;
cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
if ((val == 1) || (val == 2)) {
cs->subtyp = ASUS_IPAC;
cs->card_ops = &asuscom_ipac_ops;
cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
} else {
cs->subtyp = ASUS_ISACHSCX;
cs->card_ops = &asuscom_ops;
cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
}
printk(KERN_INFO "ISDNLink: resetting card\n");
cs->card_ops->reset(cs);
return 0;
err:
hisax_release_resources(cs);
return rc;
}
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct isapnp_device_id asus_ids[] __initdata = { static struct isapnp_device_id asus_ids[] __initdata = {
{ ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688), { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
...@@ -255,9 +300,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -255,9 +300,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __init int __init
setup_asuscom(struct IsdnCard *card) setup_asuscom(struct IsdnCard *card)
{ {
int bytecnt;
struct IsdnCardState *cs = card->cs;
u8 val;
char tmp[64]; char tmp[64];
strcpy(tmp, Asuscom_revision); strcpy(tmp, Asuscom_revision);
...@@ -310,36 +352,7 @@ setup_asuscom(struct IsdnCard *card) ...@@ -310,36 +352,7 @@ setup_asuscom(struct IsdnCard *card)
} }
} }
#endif #endif
bytecnt = 8; if (asuscom_probe(card->cs, card) < 0)
cs->hw.asus.cfg_reg = card->para[1]; return 0;
cs->irq = card->para[0];
if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn"))
goto err;
printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
cs->hw.asus.cfg_reg, cs->irq);
cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
if ((val == 1) || (val == 2)) {
cs->subtyp = ASUS_IPAC;
cs->card_ops = &asuscom_ipac_ops;
cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
} else {
cs->subtyp = ASUS_ISACHSCX;
cs->card_ops = &asuscom_ops;
cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
}
printk(KERN_INFO "ISDNLink: resetting card\n");
cs->card_ops->reset(cs);
return 1; return 1;
err:
hisax_release_resources(cs);
return 0;
} }
...@@ -160,16 +160,16 @@ static struct card_ops avm_a1_ops = { ...@@ -160,16 +160,16 @@ static struct card_ops avm_a1_ops = {
.irq_func = avm_a1_interrupt, .irq_func = avm_a1_interrupt,
}; };
int __init static int __init
setup_avm_a1(struct IsdnCard *card) avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
int rc;
u8 val; u8 val;
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, avm_revision); printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n",
printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); card->para[1], card->para[0]);
rc = -EBUSY;
cs->hw.avm.cfg_reg = request_io(&cs->rs, card->para[1] + 0x1800, 8, "avm cfg"); cs->hw.avm.cfg_reg = request_io(&cs->rs, card->para[1] + 0x1800, 8, "avm cfg");
if (!cs->hw.avm.cfg_reg) goto err; if (!cs->hw.avm.cfg_reg) goto err;
cs->hw.avm.isac = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac"); cs->hw.avm.isac = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac");
...@@ -216,23 +216,24 @@ setup_avm_a1(struct IsdnCard *card) ...@@ -216,23 +216,24 @@ setup_avm_a1(struct IsdnCard *card)
printk(KERN_INFO "AVM A1: Byte at %x is %x\n", printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
cs->hw.avm.cfg_reg, val); cs->hw.avm.cfg_reg, val);
printk(KERN_INFO
"HiSax: %s config irq:%d cfg:0x%X\n",
CardType[cs->typ], cs->irq,
cs->hw.avm.cfg_reg);
printk(KERN_INFO
"HiSax: isac:0x%X/0x%X\n",
cs->hw.avm.isac + 32, cs->hw.avm.isacfifo);
printk(KERN_INFO
"HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n",
cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0],
cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]);
cs->card_ops = &avm_a1_ops; cs->card_ops = &avm_a1_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err; goto err;
return 1; return 0;
err: err:
hisax_release_resources(cs); hisax_release_resources(cs);
return 0; return rc;
}
int __init
setup_avm_a1(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, avm_revision);
printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp));
if (avm_a1_probe(card->cs, card) < 0)
return 0;
return 1;
} }
...@@ -215,20 +215,13 @@ static struct card_ops avm_a1p_ops = { ...@@ -215,20 +215,13 @@ static struct card_ops avm_a1p_ops = {
.irq_func = avm_a1p_interrupt, .irq_func = avm_a1p_interrupt,
}; };
int __devinit static int __init
setup_avm_a1_pcmcia(struct IsdnCard *card) avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
u8 model, vers; u8 model, vers;
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, avm_revision);
printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
HiSax_getrev(tmp));
cs->hw.avm.cfg_reg = card->para[1];
cs->irq = card->para[0]; cs->irq = card->para[0];
cs->hw.avm.cfg_reg = card->para[1];
outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
...@@ -244,11 +237,26 @@ setup_avm_a1_pcmcia(struct IsdnCard *card) ...@@ -244,11 +237,26 @@ setup_avm_a1_pcmcia(struct IsdnCard *card)
vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET); vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n", printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
cs->hw.avm.cfg_reg, cs->irq, model, vers); cs->hw.avm.cfg_reg, cs->irq, model, vers);
cs->card_ops = &avm_a1p_ops; cs->card_ops = &avm_a1p_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
return 0; goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
int __devinit
setup_avm_a1_pcmcia(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, avm_revision);
printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
HiSax_getrev(tmp));
if (avm_a1p_probe(card->cs, card))
return 0;
return 1; return 1;
} }
...@@ -497,7 +497,7 @@ static struct bc_l1_ops hdlc_l1_ops = { ...@@ -497,7 +497,7 @@ static struct bc_l1_ops hdlc_l1_ops = {
.close = close_hdlcstate, .close = close_hdlcstate,
}; };
void __init static void __init
inithdlc(struct IsdnCardState *cs) inithdlc(struct IsdnCardState *cs)
{ {
u_int val; u_int val;
...@@ -596,6 +596,82 @@ static struct card_ops avm_pci_ops = { ...@@ -596,6 +596,82 @@ static struct card_ops avm_pci_ops = {
.irq_func = avm_pcipnp_interrupt, .irq_func = avm_pcipnp_interrupt,
}; };
static int __init
avm_pcipnp_hw_init(struct IsdnCardState *cs)
{
cs->bc_hw_ops = &hdlc_hw_ops;
cs->bc_l1_ops = &hdlc_l1_ops;
cs->card_ops = &avm_pci_ops;
avm_pcipnp_reset(cs);
return isac_setup(cs, &isac_ops);
}
static int __init
avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
int rc;
u32 val;
printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n",
pci_resource_start(pdev, 1), pdev->irq);
rc = -EBUSY;
if (pci_enable_device(pdev))
goto err;
cs->subtyp = AVM_FRITZ_PCI;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI"))
goto err;
val = inl(cs->hw.avm.cfg_reg);
printk(KERN_INFO "AVM PCI: stat %#x\n", val);
printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
val & 0xff, (val>>8) & 0xff);
if (avm_pcipnp_hw_init(cs))
goto err;
return 0;
err:
hisax_release_resources(cs);
return rc;
}
static int __init
avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
int rc;
u8 val, ver;
printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n",
card->para[1], card->para[0]);
cs->subtyp = AVM_FRITZ_PNP;
cs->irq = card->para[0];
cs->hw.avm.cfg_reg = card->para[1];
cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
rc = -EBUSY;
if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP"))
goto err;
val = inb(cs->hw.avm.cfg_reg);
ver = inb(cs->hw.avm.cfg_reg + 1);
printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
if (avm_pcipnp_hw_init(cs))
goto err;
return 0;
err:
hisax_release_resources(cs);
return rc;
}
static struct pci_dev *dev_avm __initdata = NULL; static struct pci_dev *dev_avm __initdata = NULL;
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct pnp_card *card_avm __initdata = NULL; static struct pnp_card *card_avm __initdata = NULL;
...@@ -605,17 +681,15 @@ static struct pnp_dev *pnp_avm __initdata = NULL; ...@@ -605,17 +681,15 @@ static struct pnp_dev *pnp_avm __initdata = NULL;
int __init int __init
setup_avm_pcipnp(struct IsdnCard *card) setup_avm_pcipnp(struct IsdnCard *card)
{ {
u_int val, ver;
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, avm_pci_rev); strcpy(tmp, avm_pci_rev);
printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
if (card->para[1]) { if (card->para[1]) {
/* old manual method */ /* old manual method */
cs->hw.avm.cfg_reg = card->para[1]; if (avm_pnp_probe(card->cs, card))
cs->irq = card->para[0]; return 0;
cs->subtyp = AVM_FRITZ_PNP; return 1;
} else { } else {
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (isapnp_present()) { if (isapnp_present()) {
...@@ -647,69 +721,24 @@ setup_avm_pcipnp(struct IsdnCard *card) ...@@ -647,69 +721,24 @@ setup_avm_pcipnp(struct IsdnCard *card)
pnp_device_detach(pnp_avm); pnp_device_detach(pnp_avm);
return(0); return(0);
} }
cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0); card->para[1] = pnp_port_start(pnp_avm, 0);
cs->irq = pnp_irq(pnp_avm, 0); card->para[0] = pnp_irq(pnp_avm, 0);
cs->subtyp = AVM_FRITZ_PNP; if (avm_pnp_probe(card->cs, card))
goto ready; return 0;
return 1;
} }
} }
} else {
printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
} }
#endif #endif
#if CONFIG_PCI #if CONFIG_PCI
if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
PCI_DEVICE_ID_AVM_A1, dev_avm))) { PCI_DEVICE_ID_AVM_A1, dev_avm))) {
cs->irq = dev_avm->irq; if (avm_pci_probe(card->cs, dev_avm))
if (!cs->irq) { return 0;
printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); return 1;
return(0);
}
if (pci_enable_device(dev_avm))
return(0);
cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
if (!cs->hw.avm.cfg_reg) {
printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
return(0);
}
cs->subtyp = AVM_FRITZ_PCI;
} else {
printk(KERN_WARNING "FritzPCI: No PCI card found\n");
return(0);
} }
cs->irq_flags |= SA_SHIRQ;
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
} }
ready: printk(KERN_WARNING "FritzPCI: No card found\n");
cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32,
cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP"))
goto err;
switch (cs->subtyp) {
case AVM_FRITZ_PCI:
val = inl(cs->hw.avm.cfg_reg);
printk(KERN_INFO "AVM PCI: stat %#x\n", val);
printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
val & 0xff, (val>>8) & 0xff);
break;
case AVM_FRITZ_PNP:
val = inb(cs->hw.avm.cfg_reg);
ver = inb(cs->hw.avm.cfg_reg + 1);
printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
avm_pcipnp_reset(cs);
break;
}
printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
cs->irq, cs->hw.avm.cfg_reg);
cs->bc_hw_ops = &hdlc_hw_ops;
cs->bc_l1_ops = &hdlc_l1_ops;
cs->card_ops = &avm_pci_ops;
isac_setup(cs, &isac_ops);
return 1;
err:
hisax_release_resources(cs);
return 0; return 0;
} }
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
#include "bkm_ax.h" #include "bkm_ax.h"
extern const char *CardType[]; extern const char *CardType[];
// FIXME needs per card lock
static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED; static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED;
const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $"; const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $";
static inline u8 static inline u8
readreg(unsigned int ale, unsigned long adr, u8 off) readreg(unsigned int ale, unsigned long adr, u8 off)
{ {
...@@ -249,15 +249,57 @@ static struct card_ops bkm_a4t_ops = { ...@@ -249,15 +249,57 @@ static struct card_ops bkm_a4t_ops = {
.irq_func = bkm_interrupt, .irq_func = bkm_interrupt,
}; };
static int __init
bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
I20_REGISTER_FILE *pI20_Regs;
int rc;
printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n",
pci_resource_start(pdev, 0), pdev->irq);
rc = -EBUSY;
if (pci_enable_device(pdev))
goto err;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1);
cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T");
if (!cs->hw.ax.base)
goto err;
/* Check suspicious address */
// FIXME needs to use read[bl]
pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
printk(KERN_WARNING "HiSax: address %lx suspicious\n",
cs->hw.ax.base);
goto err;
}
cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
cs->hw.ax.isac_ale = GCS_1;
cs->hw.ax.jade_ale = GCS_3;
reset_bkm(cs);
cs->card_ops = &bkm_a4t_ops;
isac_setup(cs, &isac_ops);
jade_setup(cs, &jade_ops);
return 0;
err:
hisax_release_resources(cs);
return rc;
}
static struct pci_dev *dev_a4t __initdata = NULL; static struct pci_dev *dev_a4t __initdata = NULL;
int __init int __init
setup_bkm_a4t(struct IsdnCard *card) setup_bkm_a4t(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
u_int pci_memaddr = 0, found = 0;
I20_REGISTER_FILE *pI20_Regs;
strcpy(tmp, bkm_a4t_revision); strcpy(tmp, bkm_a4t_revision);
printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
...@@ -268,49 +310,13 @@ setup_bkm_a4t(struct IsdnCard *card) ...@@ -268,49 +310,13 @@ setup_bkm_a4t(struct IsdnCard *card)
sub_vendor = dev_a4t->subsystem_vendor; sub_vendor = dev_a4t->subsystem_vendor;
sub_sys = dev_a4t->subsystem_device; sub_sys = dev_a4t->subsystem_device;
if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) { if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T &&
if (pci_enable_device(dev_a4t)) sub_vendor == PCI_VENDOR_ID_BERKOM) {
return(0); if (bkm_a4t_probe(card->cs, dev_a4t))
found = 1; return 0;
pci_memaddr = pci_resource_start(dev_a4t, 0); return 1;
cs->irq = dev_a4t->irq;
break;
} }
} }
if (!found) { printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); return 0;
return (0);
}
if (!cs->irq) { /* IRQ range check ?? */
printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
return (0);
}
cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T");
if (!cs->hw.ax.base) {
printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
return (0);
}
/* Check suspecious address */
pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
hisax_release_resources(cs);
return (0);
}
cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
cs->hw.ax.isac_ale = GCS_1;
cs->hw.ax.jade_ale = GCS_3;
printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
CardType[card->typ], cs->hw.ax.base, cs->irq);
reset_bkm(cs);
cs->irq_flags |= SA_SHIRQ;
cs->card_ops = &bkm_a4t_ops;
isac_setup(cs, &isac_ops);
jade_setup(cs, &jade_ops);
return 1;
} }
...@@ -490,125 +490,36 @@ static int __init HiSax_setup(char *line) ...@@ -490,125 +490,36 @@ static int __init HiSax_setup(char *line)
__setup("hisax=", HiSax_setup); __setup("hisax=", HiSax_setup);
#endif /* MODULES */ #endif /* MODULES */
#if CARD_TELES0
extern int setup_teles0(struct IsdnCard *card); extern int setup_teles0(struct IsdnCard *card);
#endif
#if CARD_TELES3
extern int setup_teles3(struct IsdnCard *card); extern int setup_teles3(struct IsdnCard *card);
#endif
#if CARD_S0BOX
extern int setup_s0box(struct IsdnCard *card); extern int setup_s0box(struct IsdnCard *card);
#endif
#if CARD_TELESPCI
extern int setup_telespci(struct IsdnCard *card); extern int setup_telespci(struct IsdnCard *card);
#endif
#if CARD_AVM_A1
extern int setup_avm_a1(struct IsdnCard *card); extern int setup_avm_a1(struct IsdnCard *card);
#endif
#if CARD_AVM_A1_PCMCIA
extern int setup_avm_a1_pcmcia(struct IsdnCard *card); extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
#endif
#if CARD_FRITZPCI
extern int setup_avm_pcipnp(struct IsdnCard *card); extern int setup_avm_pcipnp(struct IsdnCard *card);
#endif
#if CARD_ELSA
extern int setup_elsa(struct IsdnCard *card); extern int setup_elsa(struct IsdnCard *card);
#endif
#if CARD_IX1MICROR2
extern int setup_ix1micro(struct IsdnCard *card); extern int setup_ix1micro(struct IsdnCard *card);
#endif
#if CARD_DIEHLDIVA
extern int setup_diva(struct IsdnCard *card); extern int setup_diva(struct IsdnCard *card);
#endif
#if CARD_ASUSCOM
extern int setup_asuscom(struct IsdnCard *card); extern int setup_asuscom(struct IsdnCard *card);
#endif
#if CARD_TELEINT
extern int setup_TeleInt(struct IsdnCard *card); extern int setup_TeleInt(struct IsdnCard *card);
#endif
#if CARD_SEDLBAUER
extern int setup_sedlbauer(struct IsdnCard *card); extern int setup_sedlbauer(struct IsdnCard *card);
#endif
#if CARD_SPORTSTER
extern int setup_sportster(struct IsdnCard *card); extern int setup_sportster(struct IsdnCard *card);
#endif
#if CARD_MIC
extern int setup_mic(struct IsdnCard *card); extern int setup_mic(struct IsdnCard *card);
#endif
#if CARD_NETJET_S
extern int setup_netjet_s(struct IsdnCard *card); extern int setup_netjet_s(struct IsdnCard *card);
#endif
#if CARD_HFCS
extern int setup_hfcs(struct IsdnCard *card); extern int setup_hfcs(struct IsdnCard *card);
#endif
#if CARD_HFC_PCI
extern int setup_hfcpci(struct IsdnCard *card); extern int setup_hfcpci(struct IsdnCard *card);
#endif
#if CARD_HFC_SX
extern int setup_hfcsx(struct IsdnCard *card); extern int setup_hfcsx(struct IsdnCard *card);
#endif
#if CARD_AMD7930
extern int setup_amd7930(struct IsdnCard *card); extern int setup_amd7930(struct IsdnCard *card);
#endif
#if CARD_NICCY
extern int setup_niccy(struct IsdnCard *card); extern int setup_niccy(struct IsdnCard *card);
#endif
#if CARD_ISURF
extern int setup_isurf(struct IsdnCard *card); extern int setup_isurf(struct IsdnCard *card);
#endif
#if CARD_HSTSAPHIR
extern int setup_saphir(struct IsdnCard *card); extern int setup_saphir(struct IsdnCard *card);
#endif
#if CARD_TESTEMU
extern int setup_testemu(struct IsdnCard *card); extern int setup_testemu(struct IsdnCard *card);
#endif
#if CARD_BKM_A4T
extern int setup_bkm_a4t(struct IsdnCard *card); extern int setup_bkm_a4t(struct IsdnCard *card);
#endif
#if CARD_SCT_QUADRO
extern int setup_sct_quadro(struct IsdnCard *card); extern int setup_sct_quadro(struct IsdnCard *card);
#endif
#if CARD_GAZEL
extern int setup_gazel(struct IsdnCard *card); extern int setup_gazel(struct IsdnCard *card);
#endif
#if CARD_W6692
extern int setup_w6692(struct IsdnCard *card); extern int setup_w6692(struct IsdnCard *card);
#endif
#if CARD_NETJET_U
extern int setup_netjet_u(struct IsdnCard *card); extern int setup_netjet_u(struct IsdnCard *card);
#endif
#if CARD_FN_ENTERNOW_PCI
extern int setup_enternow_pci(struct IsdnCard *card); extern int setup_enternow_pci(struct IsdnCard *card);
#endif
/* /*
* Find card with given driverId * Find card with given driverId
...@@ -703,16 +614,16 @@ int jiftime(char *s, long mark) ...@@ -703,16 +614,16 @@ int jiftime(char *s, long mark)
return 8; return 8;
} }
static u8 tmpbuf[HISAX_STATUS_BUFSIZE]; static char tmpbuf[HISAX_STATUS_BUFSIZE];
void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
va_list args) va_list args)
{ {
/* if head == NULL the fmt contains the full info */ /* if head == NULL the fmt contains the full info */
unsigned long flags; unsigned long flags;
int count, i; int count, i;
u8 *p; char *p;
isdn_ctrl ic; isdn_ctrl ic;
int len; int len;
...@@ -727,7 +638,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...@@ -727,7 +638,7 @@ void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
len = p - tmpbuf; len = p - tmpbuf;
p = tmpbuf; p = tmpbuf;
} else { } else {
p = fmt; p = (char *) fmt;
len = strlen(fmt); len = strlen(fmt);
} }
if (!cs) { if (!cs) {
...@@ -814,12 +725,6 @@ static void ll_unload(struct IsdnCardState *cs) ...@@ -814,12 +725,6 @@ static void ll_unload(struct IsdnCardState *cs)
ic.command = ISDN_STAT_UNLOAD; ic.command = ISDN_STAT_UNLOAD;
ic.driver = cs->myid; ic.driver = cs->myid;
cs->iif.statcallb(&ic); cs->iif.statcallb(&ic);
if (cs->status_buf)
kfree(cs->status_buf);
cs->status_read = NULL;
cs->status_write = NULL;
cs->status_end = NULL;
kfree(cs->dlog);
} }
static void closecard(int cardnr) static void closecard(int cardnr)
...@@ -893,59 +798,97 @@ static int __devinit init_card(struct IsdnCardState *cs) ...@@ -893,59 +798,97 @@ static int __devinit init_card(struct IsdnCardState *cs)
return 3; return 3;
} }
static struct IsdnCardState *
alloc_IsdnCardState(void)
{
struct IsdnCardState *cs;
cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME
if (!cs)
goto err;
memset(cs, 0, sizeof(*cs));
cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC);
if (!cs->dlog)
goto err_cs;
cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC);
if (!cs->status_buf)
goto err_dlog;
cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC);
if (!cs->rcvbuf)
goto err_status_buf;
cs->chanlimit = 2; /* maximum B-channel number */
cs->debug = L1_DEB_WARN;
cs->irq_flags = I4L_IRQ_FLAG;
cs->stlist = NULL;
cs->status_read = cs->status_buf;
cs->status_write = cs->status_buf;
cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
cs->rcvidx = 0;
cs->tx_skb = NULL;
cs->tx_cnt = 0;
cs->event = 0;
skb_queue_head_init(&cs->rq);
skb_queue_head_init(&cs->sq);
spin_lock_init(&cs->lock);
resources_init(&cs->rs);
return cs;
err_status_buf:
kfree(cs->status_buf);
err_dlog:
kfree(cs->dlog);
err_cs:
kfree(cs);
err:
return NULL;
}
static void
free_IsdnCardState(struct IsdnCardState *cs)
{
kfree(cs->rcvbuf);
kfree(cs->status_buf);
kfree(cs->dlog);
kfree(cs);
}
static int __devinit checkcard(int cardnr, char *id, int *busy_flag) static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
{ {
int ret = 0; int ret = 0;
struct IsdnCard *card = cards + cardnr; struct IsdnCard *card = cards + cardnr;
struct IsdnCardState *cs; struct IsdnCardState *cs;
cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); cs = alloc_IsdnCardState();
if (!cs) { if (!cs) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: No memory for IsdnCardState(card %d)\n", "HiSax: No memory for IsdnCardState(card %d)\n",
cardnr + 1); cardnr + 1);
goto out; goto out;
} }
memset(cs, 0, sizeof(struct IsdnCardState));
card->cs = cs; card->cs = cs;
cs->chanlimit = 2; /* maximum B-channel number */
cs->logecho = 0; /* No echo logging */
cs->cardnr = cardnr;
cs->debug = L1_DEB_WARN;
cs->HW_Flags = 0;
cs->busy_flag = busy_flag;
cs->irq_flags = I4L_IRQ_FLAG;
#if TEI_PER_CARD #if TEI_PER_CARD
if (card->protocol == ISDN_PTYPE_NI1) if (card->protocol == ISDN_PTYPE_NI1)
test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
#else #else
test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
#endif #endif
cs->cardnr = cardnr;
cs->protocol = card->protocol; cs->protocol = card->protocol;
cs->typ = card->typ;
cs->busy_flag = busy_flag;
if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) { if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: Card Type %d out of range\n", card->typ); "HiSax: Card Type %d out of range\n", card->typ);
goto outf_cs; goto outf_cs;
} }
if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for dlog(card %d)\n", cardnr + 1);
goto outf_cs;
}
if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for status_buf(card %d)\n",
cardnr + 1);
goto outf_dlog;
}
cs->stlist = NULL;
cs->status_read = cs->status_buf;
cs->status_write = cs->status_buf;
cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
cs->typ = card->typ;
spin_lock_init(&cs->lock);
resources_init(&cs->rs);
SET_MODULE_OWNER(&cs->iif); SET_MODULE_OWNER(&cs->iif);
strcpy(cs->iif.id, id); strcpy(cs->iif.id, id);
cs->iif.channels = 2; cs->iif.channels = 2;
...@@ -982,13 +925,13 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag) ...@@ -982,13 +925,13 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
(card->protocol == ISDN_PTYPE_NI1) ? "NI1" : (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
"NONE", cs->iif.id, cs->myid); "NONE", cs->iif.id, cs->myid);
switch (card->typ) { switch (card->typ) {
#if CARD_TELES0 #ifdef CONFIG_HISAX_16_0
case ISDN_CTYPE_16_0: case ISDN_CTYPE_16_0:
case ISDN_CTYPE_8_0: case ISDN_CTYPE_8_0:
ret = setup_teles0(card); ret = setup_teles0(card);
break; break;
#endif #endif
#if CARD_TELES3 #ifdef CONFIG_HISAX_16_3
case ISDN_CTYPE_16_3: case ISDN_CTYPE_16_3:
case ISDN_CTYPE_PNP: case ISDN_CTYPE_PNP:
case ISDN_CTYPE_TELESPCMCIA: case ISDN_CTYPE_TELESPCMCIA:
...@@ -996,32 +939,32 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag) ...@@ -996,32 +939,32 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
ret = setup_teles3(card); ret = setup_teles3(card);
break; break;
#endif #endif
#if CARD_S0BOX #ifdef CONFIG_HISAX_S0BOX
case ISDN_CTYPE_S0BOX: case ISDN_CTYPE_S0BOX:
ret = setup_s0box(card); ret = setup_s0box(card);
break; break;
#endif #endif
#if CARD_TELESPCI #ifdef CONFIG_HISAX_TELESPCI
case ISDN_CTYPE_TELESPCI: case ISDN_CTYPE_TELESPCI:
ret = setup_telespci(card); ret = setup_telespci(card);
break; break;
#endif #endif
#if CARD_AVM_A1 #ifdef CONFIG_HISAX_AVM_A1
case ISDN_CTYPE_A1: case ISDN_CTYPE_A1:
ret = setup_avm_a1(card); ret = setup_avm_a1(card);
break; break;
#endif #endif
#if CARD_AVM_A1_PCMCIA #ifdef CONFIG_HISAX_AVM_A1_PCMCIA
case ISDN_CTYPE_A1_PCMCIA: case ISDN_CTYPE_A1_PCMCIA:
ret = setup_avm_a1_pcmcia(card); ret = setup_avm_a1_pcmcia(card);
break; break;
#endif #endif
#if CARD_FRITZPCI #ifdef CONFIG_HISAX_FRITZPCI
case ISDN_CTYPE_FRITZPCI: case ISDN_CTYPE_FRITZPCI:
ret = setup_avm_pcipnp(card); ret = setup_avm_pcipnp(card);
break; break;
#endif #endif
#if CARD_ELSA #ifdef CONFIG_HISAX_ELSA
case ISDN_CTYPE_ELSA: case ISDN_CTYPE_ELSA:
case ISDN_CTYPE_ELSA_PNP: case ISDN_CTYPE_ELSA_PNP:
case ISDN_CTYPE_ELSA_PCMCIA: case ISDN_CTYPE_ELSA_PCMCIA:
...@@ -1029,115 +972,115 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag) ...@@ -1029,115 +972,115 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
ret = setup_elsa(card); ret = setup_elsa(card);
break; break;
#endif #endif
#if CARD_IX1MICROR2 #ifdef CONFIG_HISAX_IX1MICROR2
case ISDN_CTYPE_IX1MICROR2: case ISDN_CTYPE_IX1MICROR2:
ret = setup_ix1micro(card); ret = setup_ix1micro(card);
break; break;
#endif #endif
#if CARD_DIEHLDIVA #ifdef CONFIG_HISAX_DIEHLDIVA
case ISDN_CTYPE_DIEHLDIVA: case ISDN_CTYPE_DIEHLDIVA:
ret = setup_diva(card); ret = setup_diva(card);
break; break;
#endif #endif
#if CARD_ASUSCOM #ifdef CONFIG_HISAX_ASUSCOM
case ISDN_CTYPE_ASUSCOM: case ISDN_CTYPE_ASUSCOM:
ret = setup_asuscom(card); ret = setup_asuscom(card);
break; break;
#endif #endif
#if CARD_TELEINT #ifdef CONFIG_HISAX_TELEINT
case ISDN_CTYPE_TELEINT: case ISDN_CTYPE_TELEINT:
ret = setup_TeleInt(card); ret = setup_TeleInt(card);
break; break;
#endif #endif
#if CARD_SEDLBAUER #ifdef CONFIG_HISAX_SEDLBAUER
case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER:
case ISDN_CTYPE_SEDLBAUER_PCMCIA: case ISDN_CTYPE_SEDLBAUER_PCMCIA:
case ISDN_CTYPE_SEDLBAUER_FAX: case ISDN_CTYPE_SEDLBAUER_FAX:
ret = setup_sedlbauer(card); ret = setup_sedlbauer(card);
break; break;
#endif #endif
#if CARD_SPORTSTER #ifdef CONFIG_HISAX_SPORTSTER
case ISDN_CTYPE_SPORTSTER: case ISDN_CTYPE_SPORTSTER:
ret = setup_sportster(card); ret = setup_sportster(card);
break; break;
#endif #endif
#if CARD_MIC #ifdef CONFIG_HISAX_MIC
case ISDN_CTYPE_MIC: case ISDN_CTYPE_MIC:
ret = setup_mic(card); ret = setup_mic(card);
break; break;
#endif #endif
#if CARD_NETJET_S #ifdef CONFIG_HISAX_NETJET
case ISDN_CTYPE_NETJET_S: case ISDN_CTYPE_NETJET_S:
ret = setup_netjet_s(card); ret = setup_netjet_s(card);
break; break;
#endif #endif
#if CARD_HFCS #ifdef CONFIG_HISAX_HFCS
case ISDN_CTYPE_TELES3C: case ISDN_CTYPE_TELES3C:
case ISDN_CTYPE_ACERP10: case ISDN_CTYPE_ACERP10:
ret = setup_hfcs(card); ret = setup_hfcs(card);
break; break;
#endif #endif
#if CARD_HFC_PCI #ifdef CONFIG_HISAX_HFC_PCI
case ISDN_CTYPE_HFC_PCI: case ISDN_CTYPE_HFC_PCI:
ret = setup_hfcpci(card); ret = setup_hfcpci(card);
break; break;
#endif #endif
#if CARD_HFC_SX #ifdef CONFIG_HISAX_HFC_SX
case ISDN_CTYPE_HFC_SX: case ISDN_CTYPE_HFC_SX:
ret = setup_hfcsx(card); ret = setup_hfcsx(card);
break; break;
#endif #endif
#if CARD_NICCY #ifdef CONFIG_HISAX_NICCY
case ISDN_CTYPE_NICCY: case ISDN_CTYPE_NICCY:
ret = setup_niccy(card); ret = setup_niccy(card);
break; break;
#endif #endif
#if CARD_AMD7930 #ifdef CONFIG_HISAX_AMD7930
case ISDN_CTYPE_AMD7930: case ISDN_CTYPE_AMD7930:
ret = setup_amd7930(card); ret = setup_amd7930(card);
break; break;
#endif #endif
#if CARD_ISURF #ifdef CONFIG_HISAX_ISURF
case ISDN_CTYPE_ISURF: case ISDN_CTYPE_ISURF:
ret = setup_isurf(card); ret = setup_isurf(card);
break; break;
#endif #endif
#if CARD_HSTSAPHIR #ifdef CONFIG_HISAX_HSTSAPHIR
case ISDN_CTYPE_HSTSAPHIR: case ISDN_CTYPE_HSTSAPHIR:
ret = setup_saphir(card); ret = setup_saphir(card);
break; break;
#endif #endif
#if CARD_TESTEMU #ifdef CONFIG_HISAX_TESTEMU
case ISDN_CTYPE_TESTEMU: case ISDN_CTYPE_TESTEMU:
ret = setup_testemu(card); ret = setup_testemu(card);
break; break;
#endif #endif
#if CARD_BKM_A4T #ifdef CONFIG_HISAX_BKM_A4T
case ISDN_CTYPE_BKM_A4T: case ISDN_CTYPE_BKM_A4T:
ret = setup_bkm_a4t(card); ret = setup_bkm_a4t(card);
break; break;
#endif #endif
#if CARD_SCT_QUADRO #ifdef CONFIG_HISAX_SCT_QUADRO
case ISDN_CTYPE_SCT_QUADRO: case ISDN_CTYPE_SCT_QUADRO:
ret = setup_sct_quadro(card); ret = setup_sct_quadro(card);
break; break;
#endif #endif
#if CARD_GAZEL #ifdef CONFIG_HISAX_GAZEL
case ISDN_CTYPE_GAZEL: case ISDN_CTYPE_GAZEL:
ret = setup_gazel(card); ret = setup_gazel(card);
break; break;
#endif #endif
#if CARD_W6692 #ifdef CONFIG_HISAX_W6692
case ISDN_CTYPE_W6692: case ISDN_CTYPE_W6692:
ret = setup_w6692(card); ret = setup_w6692(card);
break; break;
#endif #endif
#if CARD_NETJET_U #ifdef CONFIG_HISAX_NETJET_U
case ISDN_CTYPE_NETJET_U: case ISDN_CTYPE_NETJET_U:
ret = setup_netjet_u(card); ret = setup_netjet_u(card);
break; break;
#endif #endif
#if CARD_FN_ENTERNOW_PCI #ifdef CONFIG_HISAX_ENTERNOW_PCI
case ISDN_CTYPE_ENTERNOW: case ISDN_CTYPE_ENTERNOW:
ret = setup_enternow_pci(card); ret = setup_enternow_pci(card);
break; break;
...@@ -1156,19 +1099,6 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag) ...@@ -1156,19 +1099,6 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
ll_unload(cs); ll_unload(cs);
goto outf_cs; goto outf_cs;
} }
if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
ll_unload(cs);
goto outf_cs;
}
cs->rcvidx = 0;
cs->tx_skb = NULL;
cs->tx_cnt = 0;
cs->event = 0;
skb_queue_head_init(&cs->rq);
skb_queue_head_init(&cs->sq);
init_bcstate(cs, 0); init_bcstate(cs, 0);
init_bcstate(cs, 1); init_bcstate(cs, 1);
...@@ -1201,10 +1131,8 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag) ...@@ -1201,10 +1131,8 @@ static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
ret = 1; ret = 1;
goto out; goto out;
outf_dlog:
kfree(cs->dlog);
outf_cs: outf_cs:
kfree(cs); free_IsdnCardState(cs);
card->cs = NULL; card->cs = NULL;
out: out:
return ret; return ret;
...@@ -1253,8 +1181,8 @@ int __devinit HiSax_inithardware(int *busy_flag) ...@@ -1253,8 +1181,8 @@ int __devinit HiSax_inithardware(int *busy_flag)
i++; i++;
} else { } else {
printk(KERN_WARNING printk(KERN_WARNING
"HiSax: Card %s not installed !\n", "HiSax: Card type %d not installed !\n",
CardType[cards[i].typ]); cards[i].typ);
HiSax_shiftcards(i); HiSax_shiftcards(i);
nrcards--; nrcards--;
} }
......
...@@ -362,7 +362,7 @@ diva_ipacx_pci_irq(int intno, void *dev_id, struct pt_regs *regs) ...@@ -362,7 +362,7 @@ diva_ipacx_pci_irq(int intno, void *dev_id, struct pt_regs *regs)
static void static void
diva_release(struct IsdnCardState *cs) diva_release(struct IsdnCardState *cs)
{ {
del_timer(&cs->hw.diva.tl); del_timer_sync(&cs->hw.diva.tl);
if (cs->hw.diva.cfg_reg) if (cs->hw.diva.cfg_reg)
byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
...@@ -515,6 +515,162 @@ static struct card_ops diva_ipacx_pci_ops = { ...@@ -515,6 +515,162 @@ static struct card_ops diva_ipacx_pci_ops = {
.irq_func = diva_ipacx_pci_irq, .irq_func = diva_ipacx_pci_irq,
}; };
static int __init
diva_ipac_probe(struct IsdnCardState *cs)
{
u8 val;
// request_io
val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
printk(KERN_INFO "Diva: IPAC version %x\n", val);
return (val == 1 || val == 2);
}
static int __init
diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->subtyp = DIVA_IPAC_ISA;
cs->irq = card->para[0];
cs->hw.diva.cfg_reg = card->para[1];
cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
"IPAC ISA", cs->hw.diva.cfg_reg, cs->irq);
if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
goto err;
diva_ipac_isa_reset(cs);
cs->card_ops = &diva_ipac_isa_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->subtyp = DIVA_ISA;
cs->irq = card->para[0];
cs->hw.diva.cfg_reg = card->para[1];
cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
"ISA", cs->hw.diva.cfg_reg, cs->irq);
if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
goto err;
diva_reset(cs);
init_timer(&cs->hw.diva.tl);
cs->hw.diva.tl.function = (void *) diva_led_handler;
cs->hw.diva.tl.data = (long) cs;
cs->card_ops = &diva_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
int is_ipac;
cs->hw.diva.cfg_reg = card->para[1];
if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn"))
return -EBUSY;
is_ipac = diva_ipac_probe(cs);
hisax_release_resources(cs);
if (is_ipac)
return diva_ipac_isa_probe(cs, card);
else
return diva_isac_isa_probe(cs, card);
}
static int __init
diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
cs->subtyp = DIVA_PCI;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.diva.cfg_reg = pci_resource_start(pdev, 2);
cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
"PCI", cs->hw.diva.cfg_reg, cs->irq);
printk(KERN_INFO "Diva: %s space at %#lx\n",
"PCI", cs->hw.diva.pci_cfg);
if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn"))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
cs->subtyp = DIVA_IPAC_PCI;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.diva.pci_cfg = (unsigned long)request_mmio(
&cs->rs, pci_resource_start(pdev, 0), 4096, "diva");
cs->hw.diva.cfg_reg = (unsigned long)request_mmio(
&cs->rs, pci_resource_start(pdev, 1), 4096, "diva");
printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
"IPAC PCI", cs->hw.diva.cfg_reg, cs->irq);
printk(KERN_INFO "Diva: %s space at %#lx\n",
"IPAC PCI", cs->hw.diva.pci_cfg);
diva_ipac_pci_reset(cs);
cs->card_ops = &diva_ipac_pci_ops;
if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
cs->subtyp = DIVA_IPACX_PCI;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n",
"IPACX PCI", cs->hw.diva.cfg_reg, cs->irq);
printk(KERN_INFO "Diva: %s space at %#lx\n",
"IPACX PCI", cs->hw.diva.pci_cfg);
diva_ipacx_pci_reset(cs);
cs->card_ops = &diva_ipacx_pci_ops;
if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva __initdata = NULL;
static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL;
static struct pci_dev *dev_diva201 __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL;
...@@ -545,101 +701,60 @@ static struct isapnp_device_id *pdev = &diva_ids[0]; ...@@ -545,101 +701,60 @@ static struct isapnp_device_id *pdev = &diva_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL; static struct pnp_card *pnp_c __devinitdata = NULL;
#endif #endif
int __init int __init
setup_diva(struct IsdnCard *card) setup_diva(struct IsdnCard *card)
{ {
int bytecnt = 8;
u8 val;
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, Diva_revision); strcpy(tmp, Diva_revision);
printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));
if (card->para[1]) { if (card->para[1]) {
cs->hw.diva.ctrl_reg = 0; if (diva_isa_probe(card->cs, card) < 0)
cs->hw.diva.cfg_reg = card->para[1]; return 0;
val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, return 1;
cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
printk(KERN_INFO "Diva: IPAC version %x\n", val); }
if ((val == 1) || (val==2)) {
cs->subtyp = DIVA_IPAC_ISA;
cs->hw.diva.ctrl = 0;
cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
} else {
cs->subtyp = DIVA_ISA;
cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
}
cs->irq = card->para[0];
} else {
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (isapnp_present()) { if (isapnp_present()) {
struct pnp_card *pb; struct pnp_card *pb;
struct pnp_dev *pd; struct pnp_dev *pd;
while(pdev->card_vendor) { while(pdev->card_vendor) {
if ((pb = pnp_find_card(pdev->card_vendor, if ((pb = pnp_find_card(pdev->card_vendor,
pdev->card_device, pdev->card_device, pnp_c))) {
pnp_c))) { pnp_c = pb;
pnp_c = pb; pd = NULL;
pd = NULL; if ((pd = pnp_find_dev(pnp_c,
if ((pd = pnp_find_dev(pnp_c, pdev->vendor,
pdev->vendor, pdev->function,
pdev->function, pd))) {
pd))) { printk(KERN_INFO "HiSax: %s detected\n",
printk(KERN_INFO "HiSax: %s detected\n", (char *)pdev->driver_data);
(char *)pdev->driver_data); if (pnp_device_attach(pd) < 0) {
if (pnp_device_attach(pd) < 0) { printk(KERN_ERR "Diva PnP: attach failed\n");
printk(KERN_ERR "Diva PnP: attach failed\n"); return 0;
}
if (pnp_activate_dev(pd) < 0) {
printk(KERN_ERR "Diva PnP: activate failed\n");
pnp_device_detach(pd);
return 0;
}
if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
pnp_irq(pd, 0), pnp_port_start(pd, 0));
pnp_device_detach(pd);
return(0);
}
card->para[1] = pnp_port_start(pd, 0);
card->para[0] = pnp_irq(pd, 0);
if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
if (diva_ipac_isa_probe(cs->card, cs))
return 0; return 0;
} return 1;
if (pnp_activate_dev(pd) < 0) { } else {
printk(KERN_ERR "Diva PnP: activate failed\n"); if (diva_isac_isa_probe(cs->card, cs))
pnp_device_detach(pd);
return 0; return 0;
} return 1;
if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
pnp_irq(pd, 0), pnp_port_start(pd, 0));
pnp_device_detach(pd);
return(0);
}
card->para[1] = pnp_port_start(pd, 0);
card->para[0] = pnp_irq(pd, 0);
cs->hw.diva.cfg_reg = card->para[1];
cs->irq = card->para[0];
if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
cs->subtyp = DIVA_IPAC_ISA;
cs->hw.diva.ctrl = 0;
cs->hw.diva.isac =
card->para[1] + DIVA_IPAC_DATA;
cs->hw.diva.hscx =
card->para[1] + DIVA_IPAC_DATA;
cs->hw.diva.isac_adr =
card->para[1] + DIVA_IPAC_ADR;
cs->hw.diva.hscx_adr =
card->para[1] + DIVA_IPAC_ADR;
} else {
cs->subtyp = DIVA_ISA;
cs->hw.diva.ctrl =
card->para[1] + DIVA_ISA_CTRL;
cs->hw.diva.isac =
card->para[1] + DIVA_ISA_ISAC_DATA;
cs->hw.diva.hscx =
card->para[1] + DIVA_HSCX_DATA;
cs->hw.diva.isac_adr =
card->para[1] + DIVA_ISA_ISAC_ADR;
cs->hw.diva.hscx_adr =
card->para[1] + DIVA_HSCX_ADR;
}
goto ready;
} else { } else {
printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
return(0); return(0);
...@@ -652,111 +767,29 @@ setup_diva(struct IsdnCard *card) ...@@ -652,111 +767,29 @@ setup_diva(struct IsdnCard *card)
printk(KERN_INFO "Diva PnP: no ISAPnP card found\n"); printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
} }
} }
}
#endif #endif
#if CONFIG_PCI #if CONFIG_PCI
cs->subtyp = 0; if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20,
PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { dev_diva))) {
if (pci_enable_device(dev_diva)) if (diva_pci_probe(card->cs, dev_diva))
return(0);
cs->subtyp = DIVA_PCI;
cs->irq = dev_diva->irq;
cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
if (pci_enable_device(dev_diva_u))
return(0);
cs->subtyp = DIVA_PCI;
cs->irq = dev_diva_u->irq;
cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
if (pci_enable_device(dev_diva201))
return(0);
cs->subtyp = DIVA_IPAC_PCI;
cs->irq = dev_diva201->irq;
cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva");
cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva");
} else {
printk(KERN_WARNING "Diva: No PCI card found\n");
return(0);
}
if (!cs->irq) {
printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
goto err;
}
if (!cs->hw.diva.cfg_reg) {
printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
goto err;
}
cs->irq_flags |= SA_SHIRQ;
#endif /* CONFIG_PCI */
if ((cs->subtyp == DIVA_IPAC_PCI) ||
(cs->subtyp == DIVA_IPACX_PCI) ) {
cs->hw.diva.ctrl = 0;
cs->hw.diva.isac = 0;
cs->hw.diva.hscx = 0;
cs->hw.diva.isac_adr = 0;
cs->hw.diva.hscx_adr = 0;
bytecnt = 0;
} else {
cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
bytecnt = 32;
}
}
ready:
printk(KERN_INFO
"Diva: %s card configured at %#lx IRQ %d\n",
(cs->subtyp == DIVA_PCI) ? "PCI" :
(cs->subtyp == DIVA_ISA) ? "ISA" :
(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
cs->hw.diva.cfg_reg, cs->irq);
if ((cs->subtyp == DIVA_IPAC_PCI) ||
(cs->subtyp == DIVA_IPACX_PCI) ||
(cs->subtyp == DIVA_PCI) )
printk(KERN_INFO "Diva: %s space at %#lx\n",
(cs->subtyp == DIVA_PCI) ? "PCI" :
(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
cs->hw.diva.pci_cfg);
if ((cs->subtyp != DIVA_IPAC_PCI) &&
(cs->subtyp != DIVA_IPACX_PCI) ) {
if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn"))
return 0; return 0;
return 1;
} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_DIVA20_U,
dev_diva_u))) {
if (diva_pci_probe(card->cs, dev_diva_u))
return 0;
return 1;
} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_DIVA201,
dev_diva201))) {
if (diva_ipac_pci_probe(card->cs, dev_diva201))
return 0;
return 1;
} }
if (cs->subtyp == DIVA_IPAC_ISA) { printk(KERN_WARNING "Diva: No PCI card found\n");
diva_ipac_isa_reset(cs); #endif /* CONFIG_PCI */
cs->card_ops = &diva_ipac_isa_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
} else if (cs->subtyp == DIVA_IPAC_PCI) {
diva_ipac_pci_reset(cs);
cs->card_ops = &diva_ipac_pci_ops;
if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops))
goto err;
} else if (cs->subtyp == DIVA_IPACX_PCI) {
diva_ipacx_pci_reset(cs);
cs->card_ops = &diva_ipacx_pci_ops;
if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops))
goto err;
} else { /* DIVA 2.0 */
diva_reset(cs);
cs->hw.diva.tl.function = (void *) diva_led_handler;
cs->hw.diva.tl.data = (long) cs;
init_timer(&cs->hw.diva.tl);
cs->card_ops = &diva_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
}
return 1;
err:
diva_release(cs);
return 0; return 0;
} }
...@@ -690,7 +690,47 @@ static struct card_ops elsa_ipac_ops = { ...@@ -690,7 +690,47 @@ static struct card_ops elsa_ipac_ops = {
.irq_func = elsa_interrupt_ipac, .irq_func = elsa_interrupt_ipac,
}; };
static unsigned char static void __init
elsa_arcofi_init(struct IsdnCardState *cs)
{
#if ARCOFI_USE
init_arcofi(cs);
#endif
}
static void __init
elsa_timer_init(struct IsdnCardState *cs)
{
cs->hw.elsa.tl.function = (void *) elsa_led_handler;
cs->hw.elsa.tl.data = (long) cs;
init_timer(&cs->hw.elsa.tl);
}
static int __init
elsa_timer_test(struct IsdnCardState *cs)
{
/* test timer */
byteout(cs->hw.elsa.trig, 0xff);
byteout(cs->hw.elsa.timer, 0);
if (!TimerRun(cs)) {
byteout(cs->hw.elsa.timer, 0); /* second attempt */
if (!TimerRun(cs)) {
printk(KERN_WARNING "Elsa: timer does not start\n");
goto err;
}
}
HZDELAY(10 * HZ / 1000); /* wait >=10 ms */
if (TimerRun(cs)) {
printk(KERN_WARNING "Elsa: timer does not run\n");
goto err;
}
printk(KERN_INFO "Elsa: timer OK; resetting card\n");
return 0;
err:
return -EBUSY;
}
static unsigned char __init
probe_elsa_adr(unsigned int adr, int typ) probe_elsa_adr(unsigned int adr, int typ)
{ {
int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0, int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0,
...@@ -699,15 +739,13 @@ probe_elsa_adr(unsigned int adr, int typ) ...@@ -699,15 +739,13 @@ probe_elsa_adr(unsigned int adr, int typ)
/* In case of the elsa pcmcia card, this region is in use, /* In case of the elsa pcmcia card, this region is in use,
reserved for us by the card manager. So we do not check it reserved for us by the card manager. So we do not check it
here, it would fail. */ here, it would fail. */
if (typ != ISDN_CTYPE_ELSA_PCMCIA && check_region(adr, 8)) { if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) {
printk(KERN_WARNING printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n", adr);
"Elsa: Probing Port 0x%x: already in use\n", return 0;
adr);
return (0);
} }
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
in1 = inb(adr + ELSA_CONFIG); /* 'toggelt' bei */ in1 = inb(adr + ELSA_CONFIG); /* 'toggels' at */
in2 = inb(adr + ELSA_CONFIG); /* jedem Zugriff */ in2 = inb(adr + ELSA_CONFIG); /* each access */
p16_1 += 0x04 & in1; p16_1 += 0x04 & in1;
p16_2 += 0x04 & in2; p16_2 += 0x04 & in2;
p8_1 += 0x02 & in1; p8_1 += 0x02 & in1;
...@@ -717,6 +755,7 @@ probe_elsa_adr(unsigned int adr, int typ) ...@@ -717,6 +755,7 @@ probe_elsa_adr(unsigned int adr, int typ)
pfp_1 += 0x40 & in1; pfp_1 += 0x40 & in1;
pfp_2 += 0x40 & in2; pfp_2 += 0x40 & in2;
} }
release_region(adr, 8);
printk(KERN_INFO "Elsa: Probing IO 0x%x", adr); printk(KERN_INFO "Elsa: Probing IO 0x%x", adr);
if (65 == ++p16_1 * ++p16_2) { if (65 == ++p16_1 * ++p16_2) {
printk(" PCC-16/PCF found\n"); printk(" PCC-16/PCF found\n");
...@@ -736,18 +775,227 @@ probe_elsa_adr(unsigned int adr, int typ) ...@@ -736,18 +775,227 @@ probe_elsa_adr(unsigned int adr, int typ)
} }
} }
static unsigned int static int __init
probe_elsa(struct IsdnCardState *cs) elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
int i; u8 val;
unsigned int CARD_portlist[] = int i, bytecnt = 8;
{0x160, 0x170, 0x260, 0x360, 0}; unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0};
for (i = 0; CARD_portlist[i]; i++) { cs->hw.elsa.base = card->para[0];
if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ))) printk(KERN_INFO "Elsa: Microlink IO probing\n");
if (cs->hw.elsa.base) {
cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ);
if (!cs->subtyp) {
printk(KERN_WARNING "Elsa: no Microlink at %#lx\n",
cs->hw.elsa.base);
goto err;
}
} else {
for (i = 0; CARD_portlist[i]; i++) {
cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ);
if (cs->subtyp)
cs->hw.elsa.base = CARD_portlist[i];
break; break;
}
}
if (!cs->hw.elsa.base)
goto err;
cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
val = bytein(cs->hw.elsa.cfg);
if (cs->subtyp == ELSA_PC) {
const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
} else if (cs->subtyp == ELSA_PCC8) {
const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0};
cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
} else {
const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9};
cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
}
val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
if (val < 3)
val |= 8;
val += 'A' - 3;
if (val == 'B' || val == 'C')
val ^= 1;
if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
val = 'C';
printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq);
val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
if (val) {
printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n");
cs->hw.elsa.status |= ELSA_BAD_PWR;
} }
return (CARD_portlist[i]); switch (cs->subtyp) {
case ELSA_PCFPRO: bytecnt = 16; break;
}
if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
goto err;
elsa_arcofi_init(cs);
elsa_timer_init(cs);
if (elsa_timer_test(cs))
goto err;
elsa_reset(cs);
cs->card_ops = &elsa_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
if (cs->subtyp == ELSA_PC) {
val = readitac(cs, ITAC_SYS);
printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
writeitac(cs, ITAC_ISEN, 0);
writeitac(cs, ITAC_RFIE, 0);
writeitac(cs, ITAC_XFIE, 0);
writeitac(cs, ITAC_SCIE, 0);
writeitac(cs, ITAC_STIE, 0);
}
return 0;
err:
elsa_release(cs);
return -EBUSY;
}
static int __init
elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
int bytecnt = 8;
cs->irq = card->para[0];
cs->hw.elsa.base = card->para[1];
cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
switch (cs->subtyp) {
case ELSA_QS3000: bytecnt = 16; break;
}
if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
goto err;
elsa_arcofi_init(cs);
elsa_timer_init(cs);
if (elsa_timer_test(cs))
goto err;
elsa_reset(cs);
cs->card_ops = &elsa_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
return 0;
err:
elsa_release(cs);
return -EBUSY;
}
static int __init
elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->subtyp = ELSA_QS1000;
return elsa_qs_probe(cs, card);
}
static int __init
elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->subtyp = ELSA_QS3000;
return elsa_qs_probe(cs, card);
}
static int __init
elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
u8 val;
cs->irq = card->para[0];
cs->hw.elsa.base = card->para[1];
cs->hw.elsa.ale = cs->hw.elsa.base + 0;
val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
cs->subtyp = ELSA_PCMCIA_IPAC;
cs->hw.elsa.isac = cs->hw.elsa.base + 2;
} else {
cs->subtyp = ELSA_PCMCIA;
cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
}
cs->hw.elsa.timer = 0;
cs->hw.elsa.trig = 0;
cs->hw.elsa.ctrl = 0;
printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n",
Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq);
elsa_arcofi_init(cs);
elsa_reset(cs);
if (cs->subtyp == ELSA_PCMCIA_IPAC) {
cs->card_ops = &elsa_ipac_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
} else {
cs->card_ops = &elsa_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
}
return 0;
err:
elsa_release(cs);
return -EBUSY;
}
static int __init
elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev,
int subtyp)
{
int bytecnt = 2;
u8 pci_rev;
if (pci_enable_device(pdev))
goto err;
cs->subtyp = subtyp;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.elsa.cfg = pci_resource_start(pdev, 1);
cs->hw.elsa.base = pci_resource_start(pdev, 3);
pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
}
cs->hw.elsa.ale = cs->hw.elsa.base;
cs->hw.elsa.isac = cs->hw.elsa.base +1;
cs->hw.elsa.hscx = cs->hw.elsa.base +1;
printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n",
Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg,
cs->irq);
switch (cs->subtyp) {
case ELSA_QS3000PCI: bytecnt = 16; break;
}
if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
goto err;
if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
goto err;
elsa_arcofi_init(cs);
elsa_timer_init(cs);
elsa_reset(cs);
cs->card_ops = &elsa_ipac_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
return 0;
err:
elsa_release(cs);
return -EBUSY;
} }
static struct pci_dev *dev_qs1000 __devinitdata = NULL; static struct pci_dev *dev_qs1000 __devinitdata = NULL;
...@@ -771,83 +1019,21 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -771,83 +1019,21 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __devinit int __devinit
setup_elsa(struct IsdnCard *card) setup_elsa(struct IsdnCard *card)
{ {
int bytecnt;
u8 val, pci_rev;
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, Elsa_revision); strcpy(tmp, Elsa_revision);
printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
cs->hw.elsa.ctrl_reg = 0;
cs->hw.elsa.status = 0; if (card->typ == ISDN_CTYPE_ELSA) {
cs->hw.elsa.MFlag = 0; if (elsa_probe(card->cs, card))
cs->subtyp = 0; return 0;
if (cs->typ == ISDN_CTYPE_ELSA) { return 1;
cs->hw.elsa.base = card->para[0]; } else if (card->typ == ISDN_CTYPE_ELSA_PNP) {
printk(KERN_INFO "Elsa: Microlink IO probing\n");
if (cs->hw.elsa.base) {
if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base,
cs->typ))) {
printk(KERN_WARNING
"Elsa: no Elsa Microlink at %#lx\n",
cs->hw.elsa.base);
return (0);
}
} else
cs->hw.elsa.base = probe_elsa(cs);
if (cs->hw.elsa.base) {
cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC;
cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
val = bytein(cs->hw.elsa.cfg);
if (cs->subtyp == ELSA_PC) {
const u8 CARD_IrqTab[8] =
{7, 3, 5, 9, 0, 0, 0, 0};
cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2];
} else if (cs->subtyp == ELSA_PCC8) {
const u8 CARD_IrqTab[8] =
{7, 3, 5, 9, 0, 0, 0, 0};
cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4];
} else {
const u8 CARD_IrqTab[8] =
{15, 10, 15, 3, 11, 5, 11, 9};
cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3];
}
val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE;
if (val < 3)
val |= 8;
val += 'A' - 3;
if (val == 'B' || val == 'C')
val ^= 1;
if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G'))
val = 'C';
printk(KERN_INFO
"Elsa: %s found at %#lx Rev.:%c IRQ %d\n",
Elsa_Types[cs->subtyp],
cs->hw.elsa.base,
val, cs->irq);
val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD;
if (val) {
printk(KERN_WARNING
"Elsa: Microlink S0 bus power bad\n");
cs->hw.elsa.status |= ELSA_BAD_PWR;
}
} else {
printk(KERN_WARNING
"No Elsa Microlink found\n");
return (0);
}
} else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) { if (!card->para[1] && isapnp_present()) {
struct pnp_card *pb; struct pnp_card *pb;
struct pnp_dev *pd; struct pnp_dev *pd;
while(pdev->card_vendor) { while(pdev->card_vendor) {
if ((pb = pnp_find_card(pdev->card_vendor, if ((pb = pnp_find_card(pdev->card_vendor,
pdev->card_device, pdev->card_device,
...@@ -878,10 +1064,15 @@ setup_elsa(struct IsdnCard *card) ...@@ -878,10 +1064,15 @@ setup_elsa(struct IsdnCard *card)
} }
card->para[1] = pnp_port_start(pd, 0); card->para[1] = pnp_port_start(pd, 0);
card->para[0] = pnp_irq(pd, 0); card->para[0] = pnp_irq(pd, 0);
if (pdev->function == ISAPNP_FUNCTION(0x133)) if (pdev->function == ISAPNP_FUNCTION(0x133)) {
cs->subtyp = ELSA_QS1000; if (elsa_qs1000_probe(card->cs, card))
else return 0;
cs->subtyp = ELSA_QS3000; return 1;
} else {
if (elsa_qs3000_probe(card->cs, card))
return 0;
return 1;
}
break; break;
} else { } else {
printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
...@@ -897,184 +1088,33 @@ setup_elsa(struct IsdnCard *card) ...@@ -897,184 +1088,33 @@ setup_elsa(struct IsdnCard *card)
} }
} }
#endif #endif
if (card->para[1] && card->para[0]) { if (elsa_qs1000_probe(card->cs, card))
cs->hw.elsa.base = card->para[1]; return 0;
cs->irq = card->para[0]; return 1;
if (!cs->subtyp)
cs->subtyp = ELSA_QS1000; } else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) {
} else { if (elsa_pcmcia_probe(card->cs, card))
printk(KERN_ERR "Elsa PnP: no parameter\n"); return 0;
} return 1;
cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; } else if (card->typ == ISDN_CTYPE_ELSA_PCI) {
cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ;
cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER;
cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL;
printk(KERN_INFO
"Elsa: %s defined at %#lx IRQ %d\n",
Elsa_Types[cs->subtyp],
cs->hw.elsa.base,
cs->irq);
} else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) {
cs->hw.elsa.base = card->para[1];
cs->irq = card->para[0];
cs->hw.elsa.ale = cs->hw.elsa.base + 0;
val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID);
if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */
cs->subtyp = ELSA_PCMCIA_IPAC;
cs->hw.elsa.isac = cs->hw.elsa.base + 2;
cs->hw.elsa.hscx = cs->hw.elsa.base + 2;
} else {
cs->subtyp = ELSA_PCMCIA;
cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM;
cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM;
cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX;
}
cs->hw.elsa.timer = 0;
cs->hw.elsa.trig = 0;
cs->hw.elsa.ctrl = 0;
printk(KERN_INFO
"Elsa: %s defined at %#lx IRQ %d\n",
Elsa_Types[cs->subtyp],
cs->hw.elsa.base,
cs->irq);
} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
#if CONFIG_PCI #if CONFIG_PCI
cs->subtyp = 0;
if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
if (pci_enable_device(dev_qs1000)) if (elsa_qs_pci_probe(card->cs, dev_qs1000,
return(0); ELSA_QS1000PCI))
cs->subtyp = ELSA_QS1000PCI; return 0;
cs->irq = dev_qs1000->irq; return 1;
cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
if (pci_enable_device(dev_qs3000)) if (elsa_qs_pci_probe(card->cs, dev_qs3000,
return(0); ELSA_QS3000PCI))
cs->subtyp = ELSA_QS3000PCI; return 0;
cs->irq = dev_qs3000->irq; return 1;
cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev);
} else { } else {
printk(KERN_WARNING "Elsa: No PCI card found\n"); printk(KERN_WARNING "Elsa: No PCI card found\n");
return(0); return 0;
}
if (!cs->irq) {
printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
return(0);
} }
if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
return(0);
}
if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) {
printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n");
set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
}
cs->hw.elsa.ale = cs->hw.elsa.base;
cs->hw.elsa.isac = cs->hw.elsa.base +1;
cs->hw.elsa.hscx = cs->hw.elsa.base +1;
cs->hw.elsa.timer = 0;
cs->hw.elsa.trig = 0;
cs->irq_flags |= SA_SHIRQ;
printk(KERN_INFO
"Elsa: %s defined at %#lx/0x%x IRQ %d\n",
Elsa_Types[cs->subtyp],
cs->hw.elsa.base,
cs->hw.elsa.cfg,
cs->irq);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
} else
return (0);
switch (cs->subtyp) {
case ELSA_PC:
case ELSA_PCC8:
case ELSA_PCC16:
case ELSA_QS1000:
case ELSA_PCMCIA:
case ELSA_PCMCIA_IPAC:
bytecnt = 8;
break;
case ELSA_PCFPRO:
case ELSA_PCF:
case ELSA_QS3000:
case ELSA_QS3000PCI:
bytecnt = 16;
break;
case ELSA_QS1000PCI:
bytecnt = 2;
break;
default:
printk(KERN_WARNING
"Unknown ELSA subtype %d\n", cs->subtyp);
return (0);
}
/* In case of the elsa pcmcia card, this region is in use,
reserved for us by the card manager. So we do not check it
here, it would fail. */
if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA)
if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn"))
goto err;
if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI))
if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci"))
goto err;
#if ARCOFI_USE
init_arcofi(cs);
#endif
cs->hw.elsa.tl.function = (void *) elsa_led_handler;
cs->hw.elsa.tl.data = (long) cs;
init_timer(&cs->hw.elsa.tl);
/* Teste Timer */
if (cs->hw.elsa.timer) {
byteout(cs->hw.elsa.trig, 0xff);
byteout(cs->hw.elsa.timer, 0);
if (!TimerRun(cs)) {
byteout(cs->hw.elsa.timer, 0); /* 2. Versuch */
if (!TimerRun(cs)) {
printk(KERN_WARNING
"Elsa: timer do not start\n");
goto err;
}
}
HZDELAY(1); /* wait >=10 ms */
if (TimerRun(cs)) {
printk(KERN_WARNING "Elsa: timer do not run down\n");
goto err;
}
printk(KERN_INFO "Elsa: timer OK; resetting card\n");
} }
elsa_reset(cs);
if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {
cs->card_ops = &elsa_ipac_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
} else {
cs->card_ops = &elsa_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
}
if (cs->subtyp == ELSA_PC) {
val = readitac(cs, ITAC_SYS);
printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]);
writeitac(cs, ITAC_ISEN, 0);
writeitac(cs, ITAC_RFIE, 0);
writeitac(cs, ITAC_XFIE, 0);
writeitac(cs, ITAC_SCIE, 0);
writeitac(cs, ITAC_STIE, 0);
}
return 1;
err:
elsa_release(cs);
return 0; return 0;
} }
...@@ -263,13 +263,65 @@ static struct card_ops enpci_ops = { ...@@ -263,13 +263,65 @@ static struct card_ops enpci_ops = {
.irq_func = enpci_interrupt, .irq_func = enpci_interrupt,
}; };
static int __init
enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.njet.base = pci_resource_start(pdev, 0);
if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
goto err;
cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
/* Reset an */
cs->hw.njet.ctrl_reg = 0x07; // gendert von 0xff
OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
/* 50 ms Pause */
schedule_timeout((50*HZ)/1000);
cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */
OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.auxd = 0x00; // war 0xc0
cs->hw.njet.dmactrl = 0;
OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
printk(KERN_INFO
"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
cs->hw.njet.base, cs->irq);
reset_enpci(cs);
cs->hw.njet.last_is0 = 0;
cs->hw.njet.bc_activate = enpci_bc_activate;
cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
cs->card_ops = &enpci_ops;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static struct pci_dev *dev_netjet __initdata = NULL; static struct pci_dev *dev_netjet __initdata = NULL;
/* called by config.c */ /* called by config.c */
int __init int __init
setup_enternow_pci(struct IsdnCard *card) setup_enternow_pci(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
...@@ -278,72 +330,22 @@ setup_enternow_pci(struct IsdnCard *card) ...@@ -278,72 +330,22 @@ setup_enternow_pci(struct IsdnCard *card)
strcpy(tmp, enternow_pci_rev); strcpy(tmp, enternow_pci_rev);
printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp));
for ( ;; ) { dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { if (dev_netjet) {
if (pci_enable_device(dev_netjet)) if (dev_netjet->subsystem_vendor != 0x55 ||
return(0); dev_netjet->subsystem_device != 0x02) {
cs->irq = dev_netjet->irq; printk(KERN_WARNING "enter:now: You tried to load "
if (!cs->irq) { "this driver with an incompatible "
printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n"); "TigerJet-card\n");
return(0); printk(KERN_WARNING "Use type=20 for Traverse "
} "NetJet PCI Card.\n");
cs->hw.njet.base = pci_resource_start(dev_netjet, 0); return 0;
if (!cs->hw.njet.base) {
printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n");
return(0);
}
/* checks Sub-Vendor ID because system crashes with Traverse-Card */
if ((dev_netjet->subsystem_vendor != 0x55) ||
(dev_netjet->subsystem_device != 0x02)) {
printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n");
printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n");
return(0);
}
} else {
printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
return(0);
} }
if (enpci_probe(card->cs, dev_netjet))
cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; return 1;
cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD
/* Reset an */
cs->hw.njet.ctrl_reg = 0x07; // gendert von 0xff
OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
/* 50 ms Pause */
schedule_timeout((50*HZ)/1000);
cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */
OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.auxd = 0x00; // war 0xc0
cs->hw.njet.dmactrl = 0;
OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
break;
}
printk(KERN_INFO
"enter:now PCI: PCI card configured at 0x%lx IRQ %d\n",
cs->hw.njet.base, cs->irq);
if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN"))
return 0; return 0;
reset_enpci(cs); }
cs->hw.njet.last_is0 = 0; printk(KERN_WARNING "enter:now PCI: No PCI card found\n");
cs->hw.njet.bc_activate = enpci_bc_activate; return 0;
cs->hw.njet.bc_deactivate = enpci_bc_deactivate;
amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask);
cs->irq_flags |= SA_SHIRQ;
cs->card_ops = &enpci_ops;
return 1;
} }
...@@ -294,60 +294,6 @@ gazel_init(struct IsdnCardState *cs) ...@@ -294,60 +294,6 @@ gazel_init(struct IsdnCardState *cs)
inithscxisac(cs); inithscxisac(cs);
} }
static int
r647_reserve_regions(struct IsdnCardState *cs)
{
int i, base = cs->hw.gazel.hscx[0];
for (i = 0; i < 0xc000; i += 0x1000) {
if (!request_io(&cs->rs, i + base, 16, "gazel"))
goto err;
}
if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int
r685_reserve_regions(struct IsdnCardState *cs)
{
if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
goto err;
if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int
r742_reserve_regions(struct IsdnCardState *cs)
{
if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int
r753_reserve_regions(struct IsdnCardState *cs)
{
if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
goto err;
if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static struct card_ops r647_ops = { static struct card_ops r647_ops = {
.init = gazel_init, .init = gazel_init,
.reset = r647_reset, .reset = r647_reset,
...@@ -377,194 +323,213 @@ static struct card_ops r753_ops = { ...@@ -377,194 +323,213 @@ static struct card_ops r753_ops = {
}; };
static int __init static int __init
setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); int i, base;
// we got an irq parameter, assume it is an ISA card
// R742 decodes address even in not started...
// R647 returns FF if not present or not started
// eventually needs improvment
cs->hw.gazel.ipac = card->para[1];
if (ipac_read(cs, IPAC_ID) == 1)
cs->subtyp = R742;
else
cs->subtyp = R647;
cs->subtyp = R647;
cs->irq = card->para[0];
cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
cs->dc.isac.adf2 = 0x87;
printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n",
cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
printk(KERN_INFO
"Gazel: hscx A:0x%X hscx B:0x%X\n",
cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
cs->hw.gazel.isac = card->para[1] + 0x8000; cs->hw.gazel.isac = card->para[1] + 0x8000;
cs->hw.gazel.hscx[0] = card->para[1]; cs->hw.gazel.hscx[0] = card->para[1];
cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
cs->irq = card->para[0];
cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
switch (cs->subtyp) { base = cs->hw.gazel.hscx[0];
case R647: for (i = 0; i < 0xc000; i += 0x1000) {
printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); if (!request_io(&cs->rs, base + i, 16, "gazel"))
cs->dc.isac.adf2 = 0x87; goto err;
printk(KERN_INFO
"Gazel: config irq:%d isac:0x%X cfg:0x%X\n",
cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
printk(KERN_INFO
"Gazel: hscx A:0x%X hscx B:0x%X\n",
cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
return r647_reserve_regions(cs);
case R742:
printk(KERN_INFO "Gazel: Card ISA R742 found\n");
printk(KERN_INFO
"Gazel: config irq:%d ipac:0x%X\n",
cs->irq, cs->hw.gazel.ipac);
return r742_reserve_regions(cs);
} }
if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel"))
goto err;
cs->card_ops = &r647_ops;
if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops))
goto err;
cs->card_ops->reset(cs);
return 0; return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
} }
static struct pci_dev *dev_tel __initdata = NULL;
static int __init static int __init
setup_gazelpci(struct IsdnCardState *cs) gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; cs->subtyp = R742;
u8 pci_irq = 0, found; cs->irq = card->para[0];
u_int nbseek, seekcard; cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
u8 pci_rev;
printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); printk(KERN_INFO "Gazel: Card ISA R742 found\n");
printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n",
cs->irq, cs->hw.gazel.ipac);
found = 0; if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
if (!pci_present()) { goto err;
printk(KERN_WARNING "Gazel: No PCI bus present\n");
return 1; cs->card_ops = &r742_ops;
} if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
seekcard = PCI_DEVICE_ID_PLX_R685; goto err;
for (nbseek = 0; nbseek < 3; nbseek++) {
if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) { cs->card_ops->reset(cs);
if (pci_enable_device(dev_tel)) return 0;
return 1; err:
pci_irq = dev_tel->irq; hisax_release_resources(cs);
pci_ioaddr0 = pci_resource_start(dev_tel, 1); return -EBUSY;
pci_ioaddr1 = pci_resource_start(dev_tel, 2); }
found = 1;
} static int __init
if (found) gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
break; {
else { if (pci_enable_device(pdev))
switch (seekcard) { goto err;
case PCI_DEVICE_ID_PLX_R685:
seekcard = PCI_DEVICE_ID_PLX_R753; cs->subtyp = R685;
break; cs->irq = pdev->irq;
case PCI_DEVICE_ID_PLX_R753: cs->irq_flags |= SA_SHIRQ;
seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
break; cs->hw.gazel.isac = pci_resource_start(pdev, 2) + 0x80;
} cs->hw.gazel.hscx[0] = pci_resource_start(pdev, 2);
} cs->hw.gazel.hscx[1] = pci_resource_start(pdev, 2) + 0x40;
} cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
if (!found) {
printk(KERN_WARNING "Gazel: No PCI card found\n");
return -ENODEV;
}
if (!pci_irq) {
printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
return -ENODEV;
}
cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
pci_ioaddr1 &= 0xfffe;
cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
cs->hw.gazel.ipac = pci_ioaddr1;
cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
cs->hw.gazel.hscx[0] = pci_ioaddr1;
cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
cs->irq = pci_irq; cs->dc.isac.adf2 = 0x87;
cs->irq_flags |= SA_SHIRQ;
if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel"))
switch (seekcard) { goto err;
case PCI_DEVICE_ID_PLX_R685: if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
printk(KERN_INFO "Gazel: Card PCI R685 found\n"); goto err;
cs->subtyp = R685;
cs->dc.isac.adf2 = 0x87; printk(KERN_INFO "Gazel: Card PCI R685 found\n");
printk(KERN_INFO printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n",
"Gazel: config irq:%d isac:0x%X cfg:0x%X\n", cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); printk(KERN_INFO "Gazel: hscx A:0x%X hscx B:0x%X\n",
printk(KERN_INFO cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
"Gazel: hscx A:0x%X hscx B:0x%X\n",
cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); cs->card_ops = &r685_ops;
return r685_reserve_regions(cs); if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops))
case PCI_DEVICE_ID_PLX_R753: goto err;
case PCI_DEVICE_ID_PLX_DJINN_ITOO:
printk(KERN_INFO "Gazel: Card PCI R753 found\n"); cs->card_ops->reset(cs);
cs->subtyp = R753; return 0;
printk(KERN_INFO err:
"Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", hisax_release_resources(cs);
cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); return -EBUSY;
/* }
* Erratum for PLX9050, revision 1:
* If bit 7 of BAR 0/1 is set, local config registers static int __init
* can not be read (write is okay) gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
*/ {
if (cs->hw.gazel.cfg_reg & 0x80) { u8 pci_rev;
pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev);
if (pci_rev == 1) { if (pci_enable_device(pdev))
printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n"); goto err;
set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
} cs->subtyp = R753;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1);
cs->hw.gazel.ipac = pci_resource_start(pdev, 2);
if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel"))
goto err;
if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel"))
goto err;
printk(KERN_INFO "Gazel: Card PCI R753 found\n");
printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n",
cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
/*
* Erratum for PLX9050, revision 1:
* If bit 7 of BAR 0/1 is set, local config registers
* can not be read (write is okay)
*/
if (cs->hw.gazel.cfg_reg & 0x80) {
pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
if (pci_rev == 1) {
printk(KERN_INFO "Gazel: PLX9050 rev1 workaround "
"activated\n");
__set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags);
} }
return r753_reserve_regions(cs);
} }
cs->card_ops = &r753_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
cs->card_ops->reset(cs);
return 0; return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
} }
static struct pci_dev *dev_tel __initdata = NULL;
static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685;
int __init int __init
setup_gazel(struct IsdnCard *card) setup_gazel(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, gazel_revision); strcpy(tmp, gazel_revision);
printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
if (card->para[0]) { if (card->para[0]) {
if (setup_gazelisa(card, cs)) printk(KERN_INFO "Gazel: ISA card automatic recognition\n");
return (0); // we got an irq parameter, assume it is an ISA card
} else { // R742 decodes address even in not started...
if (setup_gazelpci(cs)) // R647 returns FF if not present or not started
return (0); // eventually needs improvment
card->cs->hw.gazel.ipac = card->para[1];
if (ipac_read(card->cs, IPAC_ID) == 1) {
if (gazel742_probe(card->cs, card))
return 0;
} else {
if (gazel647_probe(card->cs, card))
return 0;
}
return 1;
} }
switch (cs->subtyp) { for (;;) {
case R647: dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel);
case R685: if (dev_tel) {
if (cs->subtyp == R647) { switch (dev_id) {
cs->card_ops = &r647_ops; case PCI_DEVICE_ID_PLX_R685:
if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) if (gazel685_probe(card->cs, dev_tel))
goto err; return 0;
} else { return 1;
cs->card_ops = &r685_ops; case PCI_DEVICE_ID_PLX_R753:
if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) case PCI_DEVICE_ID_PLX_DJINN_ITOO:
goto err; if (gazel753_probe(card->cs, dev_tel))
return 0;
return 1;
}
} }
cs->card_ops->reset(cs); switch (dev_id) {
break; case PCI_DEVICE_ID_PLX_R685:
case R742: dev_id = PCI_DEVICE_ID_PLX_R753;
case R753: case PCI_DEVICE_ID_PLX_R753:
if (cs->subtyp == R742) { dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO;
cs->card_ops = &r742_ops; default:
} else { break;
cs->card_ops = &r753_ops;
} }
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
cs->card_ops->reset(cs);
break;
} }
return 1; printk(KERN_WARNING "Gazel: No PCI card found\n");
err:
hisax_release_resources(cs);
return 0; return 0;
} }
...@@ -1382,72 +1382,41 @@ static struct card_ops hfcpci_ops = { ...@@ -1382,72 +1382,41 @@ static struct card_ops hfcpci_ops = {
}; };
/* this variable is used as card index when more than one cards are present */ static int __init
static struct pci_dev *dev_hfcpci __initdata = NULL; niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i)
int __init
setup_hfcpci(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs; int rc;
char tmp[64];
int i;
struct pci_dev *tmp_hfcpci = NULL;
strcpy(tmp, hfcpci_revision); rc = -EBUSY;
printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (pci_enable_device(pdev))
cs->hw.hfcpci.int_s1 = 0; goto err;
cs->dc.hfcpci.ph_state = 0;
cs->hw.hfcpci.fifo = 255;
i = 0; pci_set_master(pdev);
while (id_list[i].vendor_id) {
tmp_hfcpci = pci_find_device(id_list[i].vendor_id, cs->irq = pdev->irq;
id_list[i].device_id, cs->irq_flags |= SA_SHIRQ;
dev_hfcpci); cs->hw.hfcpci.pdev = pdev;
i++;
if (tmp_hfcpci) { cs->hw.hfcpci.pci_io = request_mmio(&cs->rs,
if (pci_enable_device(tmp_hfcpci)) pci_resource_start(pdev, 1), 128,
continue; "hfc_pci");
pci_set_master(tmp_hfcpci); if (!cs->hw.hfcpci.pci_io)
if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) goto err;
continue;
else
break;
}
}
if (tmp_hfcpci) {
i--;
dev_hfcpci = tmp_hfcpci; /* old device */
cs->irq = dev_hfcpci->irq;
cs->hw.hfcpci.pdev = tmp_hfcpci;
if (!cs->irq) {
printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
return (0);
}
printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
} else {
printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
return (0);
}
/* Allocate memory for FIFOS */ /* Allocate memory for FIFOS */
cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma); rc = -ENOMEM;
if (!cs->hw.hfcpci.fifos) { cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768,
printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); &cs->hw.hfcpci.fifos_dma);
return 0; if (!cs->hw.hfcpci.fifos)
} goto err;
pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80,
(u_int)cs->hw.hfcpci.fifos_dma); (u_int)cs->hw.hfcpci.fifos_dma);
cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci"); printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n",
if (!cs->hw.hfcpci.pci_io) id_list[i].vendor_name, id_list[i].card_name);
goto err; printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n",
(u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos,
printk(KERN_INFO (u_int) cs->hw.hfcpci.fifos_dma, cs->irq);
"HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
(u_int) cs->hw.hfcpci.pci_io,
(u_int) cs->hw.hfcpci.fifos,
(u_int) cs->hw.hfcpci.fifos_dma,
cs->irq, HZ);
printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID));
cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
cs->hw.hfcpci.int_m1 = 0; cs->hw.hfcpci.int_m1 = 0;
...@@ -1456,17 +1425,46 @@ setup_hfcpci(struct IsdnCard *card) ...@@ -1456,17 +1425,46 @@ setup_hfcpci(struct IsdnCard *card)
/* At this point the needed PCI config is done */ /* At this point the needed PCI config is done */
/* fifos are still not enabled */ /* fifos are still not enabled */
cs->irq_flags |= SA_SHIRQ; init_timer(&cs->hw.hfcpci.timer);
cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
cs->hw.hfcpci.timer.data = (long) cs; cs->hw.hfcpci.timer.data = (long) cs;
init_timer(&cs->hw.hfcpci.timer);
hfcpci_reset(cs); hfcpci_reset(cs);
cs->auxcmd = &hfcpci_auxcmd; cs->auxcmd = &hfcpci_auxcmd;
cs->card_ops = &hfcpci_ops; cs->card_ops = &hfcpci_ops;
return 1; return 0;
err: err:
hisax_release_resources(cs); hisax_release_resources(cs);
return -EBUSY;
}
/* this variable is used as card index when more than one cards are present */
static struct pci_dev *dev_hfcpci __initdata = NULL;
int __init
setup_hfcpci(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
int i;
struct pci_dev *tmp_hfcpci = NULL;
strcpy(tmp, hfcpci_revision);
printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
cs->hw.hfcpci.int_s1 = 0;
cs->dc.hfcpci.ph_state = 0;
cs->hw.hfcpci.fifo = 255;
for (i = 0; id_list[i].vendor_id; i++) {
tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
id_list[i].device_id,
dev_hfcpci);
if (!tmp_hfcpci)
continue;
if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0)
return 0;
return 1;
}
return 0; return 0;
} }
...@@ -1159,6 +1159,74 @@ static struct card_ops hfcsx_ops = { ...@@ -1159,6 +1159,74 @@ static struct card_ops hfcsx_ops = {
.irq_func = hfcsx_interrupt, .irq_func = hfcsx_interrupt,
}; };
static int __init
hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
int rc;
char c;
cs->irq = card->para[0];
cs->hw.hfcsx.base = card->para[1] & 0xfffe;
cs->hw.hfcsx.fifo = 255;
cs->hw.hfcsx.int_s1 = 0;
cs->dc.hfcsx.ph_state = 0;
rc = -EBUSY;
if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
goto err;
rc = -ENODEV;
byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
udelay(10);
cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
switch (cs->hw.hfcsx.chip >> 4) {
case 1:
c ='+';
break;
case 9:
c ='P';
break;
default:
printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
cs->hw.hfcsx.chip >> 4);
goto err;
}
if (!ccd_sp_irqtab[cs->irq & 0xF]) {
printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
cs->irq & 0xF);
goto err;
}
rc = -ENOMEM;
cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC);
if (!cs->hw.hfcsx.extra) {
printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
goto err;
}
printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n",
c, (u_int) cs->hw.hfcsx.base, cs->irq);
cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */
cs->hw.hfcsx.int_m1 = 0;
Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
init_timer(&cs->hw.hfcsx.timer);
cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
cs->hw.hfcsx.timer.data = (long) cs;
cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */
hfcsx_reset(cs);
cs->auxcmd = &hfcsx_auxcmd;
cs->card_ops = &hfcsx_ops;
return 0;
err:
hisax_release_resources(cs);
return rc;
}
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct isapnp_device_id hfc_ids[] __initdata = { static struct isapnp_device_id hfc_ids[] __initdata = {
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
...@@ -1174,7 +1242,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -1174,7 +1242,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __devinit int __devinit
setup_hfcsx(struct IsdnCard *card) setup_hfcsx(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, hfcsx_revision); strcpy(tmp, hfcsx_revision);
...@@ -1227,62 +1294,7 @@ setup_hfcsx(struct IsdnCard *card) ...@@ -1227,62 +1294,7 @@ setup_hfcsx(struct IsdnCard *card)
} }
} }
#endif #endif
cs->hw.hfcsx.base = card->para[1] & 0xfffe; if (hfcsx_probe(card->cs, card) < 0)
cs->irq = card->para[0];
cs->hw.hfcsx.int_s1 = 0;
cs->dc.hfcsx.ph_state = 0;
cs->hw.hfcsx.fifo = 255;
if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn"))
return 0; return 0;
byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF);
byteout(cs->hw.hfcsx.base + 1,
((cs->hw.hfcsx.base >> 8) & 3) | 0x54);
udelay(10);
cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID);
switch (cs->hw.hfcsx.chip >> 4) {
case 1:
tmp[0] ='+';
break;
case 9:
tmp[0] ='P';
break;
default:
printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n",
cs->hw.hfcsx.chip >> 4);
hisax_release_resources(cs);
return 0;
}
if (!ccd_sp_irqtab[cs->irq & 0xF]) {
printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n",
cs->irq & 0xF);
hisax_release_resources(cs);
return 0;
}
cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra),
GFP_ATOMIC);
if (!cs->hw.hfcsx.extra) {
hisax_release_resources(cs);
printk(KERN_WARNING "HFC-SX: unable to allocate memory\n");
return 0;
}
printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n",
tmp[0], (u_int) cs->hw.hfcsx.base,
cs->irq, HZ);
cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */
cs->hw.hfcsx.int_m1 = 0;
Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);
Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);
cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer;
cs->hw.hfcsx.timer.data = (long) cs;
cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */
cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */
init_timer(&cs->hw.hfcsx.timer);
hfcsx_reset(cs);
cs->auxcmd = &hfcsx_auxcmd;
cs->card_ops = &hfcsx_ops;
return 1; return 1;
} }
...@@ -133,6 +133,50 @@ static struct card_ops hfcs_ops = { ...@@ -133,6 +133,50 @@ static struct card_ops hfcs_ops = {
.irq_func = hfcs_interrupt, .irq_func = hfcs_interrupt,
}; };
static int __init
hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->irq = card->para[0];
cs->hw.hfcD.addr = card->para[1];
if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
goto err;
printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n",
cs->hw.hfcD.addr, cs->irq);
cs->hw.hfcD.cip = 0;
cs->hw.hfcD.int_s1 = 0;
cs->hw.hfcD.send = NULL;
cs->bcs[0].hw.hfc.send = NULL;
cs->bcs[1].hw.hfc.send = NULL;
cs->hw.hfcD.dfifosize = 512;
cs->dc.hfcd.ph_state = 0;
cs->hw.hfcD.fifo = 255;
if (cs->typ == ISDN_CTYPE_TELES3C) {
cs->hw.hfcD.bfifosize = 1024 + 512;
/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
outb(0x00, cs->hw.hfcD.addr);
outb(0x56, cs->hw.hfcD.addr | 1);
} else if (cs->typ == ISDN_CTYPE_ACERP10) {
cs->hw.hfcD.bfifosize = 7*1024 + 512;
/* Acer P10 IO ADR is 0x300 */
outb(0x00, cs->hw.hfcD.addr);
outb(0x57, cs->hw.hfcD.addr | 1);
}
set_cs_func(cs);
init_timer(&cs->hw.hfcD.timer);
cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
cs->hw.hfcD.timer.data = (long) cs;
hfcs_reset(cs);
cs->card_ops = &hfcs_ops;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct isapnp_device_id hfc_ids[] __initdata = { static struct isapnp_device_id hfc_ids[] __initdata = {
{ ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114), { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
...@@ -166,7 +210,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -166,7 +210,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __init int __init
setup_hfcs(struct IsdnCard *card) setup_hfcs(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, hfcs_revision); strcpy(tmp, hfcs_revision);
...@@ -220,42 +263,8 @@ setup_hfcs(struct IsdnCard *card) ...@@ -220,42 +263,8 @@ setup_hfcs(struct IsdnCard *card)
} }
} }
#endif #endif
cs->hw.hfcD.addr = card->para[1] & 0xfffe; if (hfcs_probe(card->cs, card) < 0)
cs->irq = card->para[0];
cs->hw.hfcD.cip = 0;
cs->hw.hfcD.int_s1 = 0;
cs->hw.hfcD.send = NULL;
cs->bcs[0].hw.hfc.send = NULL;
cs->bcs[1].hw.hfc.send = NULL;
cs->hw.hfcD.dfifosize = 512;
cs->dc.hfcd.ph_state = 0;
cs->hw.hfcD.fifo = 255;
if (cs->typ == ISDN_CTYPE_TELES3C) {
cs->hw.hfcD.bfifosize = 1024 + 512;
} else if (cs->typ == ISDN_CTYPE_ACERP10) {
cs->hw.hfcD.bfifosize = 7*1024 + 512;
} else
return (0);
if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn"))
return 0; return 0;
printk(KERN_INFO return 1;
"HFCS: defined at 0x%x IRQ %d HZ %d\n",
cs->hw.hfcD.addr,
cs->irq, HZ);
if (cs->typ == ISDN_CTYPE_TELES3C) {
/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
outb(0x00, cs->hw.hfcD.addr);
outb(0x56, cs->hw.hfcD.addr | 1);
} else if (cs->typ == ISDN_CTYPE_ACERP10) {
/* Acer P10 IO ADR is 0x300 */
outb(0x00, cs->hw.hfcD.addr);
outb(0x57, cs->hw.hfcD.addr | 1);
}
set_cs_func(cs);
cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
cs->hw.hfcD.timer.data = (long) cs;
init_timer(&cs->hw.hfcD.timer);
hfcs_reset(cs);
cs->card_ops = &hfcs_ops;
return (1);
} }
...@@ -782,7 +782,6 @@ struct bkm_hw { ...@@ -782,7 +782,6 @@ struct bkm_hw {
struct gazel_hw { struct gazel_hw {
unsigned int cfg_reg; unsigned int cfg_reg;
unsigned int pciaddr[2];
signed int ipac; signed int ipac;
signed int isac; signed int isac;
signed int hscx[2]; signed int hscx[2];
...@@ -1073,264 +1072,17 @@ hisax_release_resources(struct IsdnCardState *cs); ...@@ -1073,264 +1072,17 @@ hisax_release_resources(struct IsdnCardState *cs);
#define ISDN_CTYPE_COUNT 41 #define ISDN_CTYPE_COUNT 41
#ifdef ISDN_CHIP_ISAC
#undef ISDN_CHIP_ISAC
#endif
#ifdef CONFIG_HISAX_16_0
#define CARD_TELES0 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_TELES0 0
#endif
#ifdef CONFIG_HISAX_16_3
#define CARD_TELES3 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_TELES3 0
#endif
#ifdef CONFIG_HISAX_TELESPCI
#define CARD_TELESPCI 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_TELESPCI 0
#endif
#ifdef CONFIG_HISAX_AVM_A1
#define CARD_AVM_A1 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_AVM_A1 0
#endif
#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
#define CARD_AVM_A1_PCMCIA 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_AVM_A1_PCMCIA 0
#endif
#ifdef CONFIG_HISAX_FRITZPCI
#define CARD_FRITZPCI 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_FRITZPCI 0
#endif
#ifdef CONFIG_HISAX_ELSA
#define CARD_ELSA 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_ELSA 0
#endif
#ifdef CONFIG_HISAX_IX1MICROR2
#define CARD_IX1MICROR2 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_IX1MICROR2 0
#endif
#ifdef CONFIG_HISAX_DIEHLDIVA
#define CARD_DIEHLDIVA 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_DIEHLDIVA 0
#endif
#ifdef CONFIG_HISAX_ASUSCOM
#define CARD_ASUSCOM 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_ASUSCOM 0
#endif
#ifdef CONFIG_HISAX_TELEINT
#define CARD_TELEINT 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_TELEINT 0
#endif
#ifdef CONFIG_HISAX_SEDLBAUER
#define CARD_SEDLBAUER 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_SEDLBAUER 0
#endif
#ifdef CONFIG_HISAX_SPORTSTER
#define CARD_SPORTSTER 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_SPORTSTER 0
#endif
#ifdef CONFIG_HISAX_MIC
#define CARD_MIC 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_MIC 0
#endif
#ifdef CONFIG_HISAX_NETJET
#define CARD_NETJET_S 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_NETJET_S 0
#endif
#ifdef CONFIG_HISAX_HFCS
#define CARD_HFCS 1
#else
#define CARD_HFCS 0
#endif
#ifdef CONFIG_HISAX_HFC_PCI
#define CARD_HFC_PCI 1
#else
#define CARD_HFC_PCI 0
#endif
#ifdef CONFIG_HISAX_HFC_SX
#define CARD_HFC_SX 1
#else
#define CARD_HFC_SX 0
#endif
#ifdef CONFIG_HISAX_AMD7930
#define CARD_AMD7930 1
#else
#define CARD_AMD7930 0
#endif
#ifdef CONFIG_HISAX_NICCY
#define CARD_NICCY 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_NICCY 0
#endif
#ifdef CONFIG_HISAX_ISURF
#define CARD_ISURF 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_ISURF 0
#endif
#ifdef CONFIG_HISAX_S0BOX
#define CARD_S0BOX 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_S0BOX 0
#endif
#ifdef CONFIG_HISAX_HSTSAPHIR
#define CARD_HSTSAPHIR 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_HSTSAPHIR 0
#endif
#ifdef CONFIG_HISAX_TESTEMU #ifdef CONFIG_HISAX_TESTEMU
#define CARD_TESTEMU 1
#define ISDN_CTYPE_TESTEMU 99 #define ISDN_CTYPE_TESTEMU 99
#undef ISDN_CTYPE_COUNT #undef ISDN_CTYPE_COUNT
#define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU #define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
#else
#define CARD_TESTEMU 0
#endif
#ifdef CONFIG_HISAX_BKM_A4T
#define CARD_BKM_A4T 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_BKM_A4T 0
#endif
#ifdef CONFIG_HISAX_SCT_QUADRO
#define CARD_SCT_QUADRO 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_SCT_QUADRO 0
#endif
#ifdef CONFIG_HISAX_GAZEL
#define CARD_GAZEL 1
#ifndef ISDN_CHIP_ISAC
#define ISDN_CHIP_ISAC 1
#endif
#else
#define CARD_GAZEL 0
#endif
#ifdef CONFIG_HISAX_W6692
#define CARD_W6692 1
#ifndef ISDN_CHIP_W6692
#define ISDN_CHIP_W6692 1
#endif
#else
#define CARD_W6692 0
#endif #endif
#ifdef CONFIG_HISAX_NETJET_U #ifdef CONFIG_HISAX_NETJET_U
#define CARD_NETJET_U 1
#ifndef ISDN_CHIP_ICC
#define ISDN_CHIP_ICC 1
#endif
#ifndef HISAX_UINTERFACE #ifndef HISAX_UINTERFACE
#define HISAX_UINTERFACE 1 #define HISAX_UINTERFACE 1
#endif #endif
#else #else
#define CARD_NETJET_U 0
#endif
#ifdef CONFIG_HISAX_ENTERNOW_PCI
#define CARD_FN_ENTERNOW_PCI 1
#endif #endif
#define TEI_PER_CARD 1 #define TEI_PER_CARD 1
...@@ -1402,7 +1154,7 @@ int jiftime(char *s, long mark); ...@@ -1402,7 +1154,7 @@ int jiftime(char *s, long mark);
int HiSax_command(isdn_ctrl * ic); int HiSax_command(isdn_ctrl * ic);
int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args);
void HiSax_reportcard(int cardnr, int sel); void HiSax_reportcard(int cardnr, int sel);
int QuickHex(char *txt, u8 * p, int cnt); int QuickHex(char *txt, u8 * p, int cnt);
void LogFrame(struct IsdnCardState *cs, u8 * p, int size); void LogFrame(struct IsdnCardState *cs, u8 * p, int size);
......
...@@ -231,7 +231,7 @@ fcclassic_setup(struct fritz_adapter *adapter) ...@@ -231,7 +231,7 @@ fcclassic_setup(struct fritz_adapter *adapter)
adapter->isac.write_isac = &fcclassic_write_isac; adapter->isac.write_isac = &fcclassic_write_isac;
adapter->isac.read_isac_fifo = &fcclassic_read_isac_fifo; adapter->isac.read_isac_fifo = &fcclassic_read_isac_fifo;
adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo; adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo;
isac_setup(&adapter->isac); hisax_isac_setup(&adapter->isac);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
hscx_init(&adapter->hscx[i]); hscx_init(&adapter->hscx[i]);
adapter->hscx[i].priv = adapter; adapter->hscx[i].priv = adapter;
......
...@@ -46,24 +46,22 @@ MODULE_PARM(debug, "i"); ...@@ -46,24 +46,22 @@ MODULE_PARM(debug, "i");
MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>"); MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver"); MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
// FIXME temporary hack until I sort out the new PnP stuff
#define __ISAPNP__
static struct pci_device_id fcpci_ids[] __devinitdata = { static struct pci_device_id fcpci_ids[] __devinitdata = {
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1 , PCI_ANY_ID, PCI_ANY_ID, { .vendor = PCI_VENDOR_ID_AVM,
0, 0, (unsigned long) "Fritz!Card PCI" }, .device = PCI_DEVICE_ID_AVM_A1,
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID, .subvendor = PCI_ANY_ID,
0, 0, (unsigned long) "Fritz!Card PCI v2" }, .subdevice = PCI_ANY_ID,
{ } .driver_data = (unsigned long) "Fritz!Card PCI",
},
{ .vendor = PCI_VENDOR_ID_AVM,
.device = PCI_DEVICE_ID_AVM_A1_V2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (unsigned long) "Fritz!Card PCI v2" },
{}
}; };
MODULE_DEVICE_TABLE(pci, fcpci_ids);
static struct pnp_card_device_id fcpnp_ids[] __devinitdata = { MODULE_DEVICE_TABLE(pci, fcpci_ids);
{ .id = "AVM0900",
.driver_data = (unsigned long) "Fritz!Card PnP",
.devs = { { "AVM0900" } } }
};
MODULE_DEVICE_TABLE(pnp_card, fcpnp_ids);
static int protocol = 2; /* EURO-ISDN Default */ static int protocol = 2; /* EURO-ISDN Default */
MODULE_PARM(protocol, "i"); MODULE_PARM(protocol, "i");
...@@ -782,7 +780,7 @@ static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter) ...@@ -782,7 +780,7 @@ static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter)
case AVM_FRITZ_PCI: case AVM_FRITZ_PCI:
case AVM_FRITZ_PNP: case AVM_FRITZ_PNP:
fcpci_init(adapter); fcpci_init(adapter);
isac_setup(&adapter->isac); hisax_isac_setup(&adapter->isac);
break; break;
} }
val = adapter->read_hdlc_status(adapter, 0); val = adapter->read_hdlc_status(adapter, 0);
...@@ -908,10 +906,10 @@ static struct pci_driver fcpci_driver = { ...@@ -908,10 +906,10 @@ static struct pci_driver fcpci_driver = {
.id_table = fcpci_ids, .id_table = fcpci_ids,
}; };
#ifdef __ISAPNP__ #ifdef CONFIG_PNP_CARD
static int __devinit fcpnp_probe(struct pnp_card *card, static int __devinit fcpnp_probe(struct pnp_card *card,
const struct pnp_card_device_id *card_id) const struct pnp_card_id *card_id)
{ {
struct fritz_adapter *adapter; struct fritz_adapter *adapter;
struct pnp_dev *pnp_dev; struct pnp_dev *pnp_dev;
...@@ -957,6 +955,14 @@ static void __devexit fcpnp_remove(struct pnp_card *pcard) ...@@ -957,6 +955,14 @@ static void __devexit fcpnp_remove(struct pnp_card *pcard)
delete_adapter(adapter); delete_adapter(adapter);
} }
static struct pnp_card_id fcpnp_ids[] __devinitdata = {
{ .id = "AVM0900",
.driver_data = (unsigned long) "Fritz!Card PnP",
.devs = { { "AVM0900" } },
},
{}
};
static struct pnpc_driver fcpnp_driver = { static struct pnpc_driver fcpnp_driver = {
.name = "fcpnp", .name = "fcpnp",
.probe = fcpnp_probe, .probe = fcpnp_probe,
...@@ -968,7 +974,7 @@ static struct pnpc_driver fcpnp_driver = { ...@@ -968,7 +974,7 @@ static struct pnpc_driver fcpnp_driver = {
static int __init hisax_fcpcipnp_init(void) static int __init hisax_fcpcipnp_init(void)
{ {
int retval, pci_nr_found; int retval = 0, pci_nr_found;
printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n"); printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
...@@ -977,10 +983,8 @@ static int __init hisax_fcpcipnp_init(void) ...@@ -977,10 +983,8 @@ static int __init hisax_fcpcipnp_init(void)
goto out; goto out;
pci_nr_found = retval; pci_nr_found = retval;
#ifdef __ISAPNP__ #ifdef CONFIG_PNP_CARD
retval = pnpc_register_driver(&fcpnp_driver); retval = pnpc_register_driver(&fcpnp_driver);
#else
retval = 0;
#endif #endif
if (retval < 0) if (retval < 0)
goto out_unregister_pci; goto out_unregister_pci;
...@@ -988,14 +992,14 @@ static int __init hisax_fcpcipnp_init(void) ...@@ -988,14 +992,14 @@ static int __init hisax_fcpcipnp_init(void)
#if !defined(CONFIG_HOTPLUG) || defined(MODULE) #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
if (pci_nr_found + retval == 0) { if (pci_nr_found + retval == 0) {
retval = -ENODEV; retval = -ENODEV;
goto out_unregister_isapnp; goto out_unregister_pnp;
} }
#endif #endif
return 0; return 0;
#if !defined(CONFIG_HOTPLUG) || defined(MODULE) #if !defined(CONFIG_HOTPLUG) || defined(MODULE)
out_unregister_isapnp: out_unregister_pnp:
#ifdef __ISAPNP__ #ifdef CONFIG_PNP_CARD
pnpc_unregister_driver(&fcpnp_driver); pnpc_unregister_driver(&fcpnp_driver);
#endif #endif
#endif #endif
...@@ -1007,7 +1011,7 @@ static int __init hisax_fcpcipnp_init(void) ...@@ -1007,7 +1011,7 @@ static int __init hisax_fcpcipnp_init(void)
static void __exit hisax_fcpcipnp_exit(void) static void __exit hisax_fcpcipnp_exit(void)
{ {
#ifdef __ISAPNP__ #ifdef CONFIG_PNP_CARD
pnpc_unregister_driver(&fcpnp_driver); pnpc_unregister_driver(&fcpnp_driver);
#endif #endif
pci_unregister_driver(&fcpci_driver); pci_unregister_driver(&fcpci_driver);
......
...@@ -770,7 +770,7 @@ void isac_init(struct isac *isac) ...@@ -770,7 +770,7 @@ void isac_init(struct isac *isac)
FsmInitTimer(&isac->l1m, &isac->timer); FsmInitTimer(&isac->l1m, &isac->timer);
} }
void isac_setup(struct isac *isac) void hisax_isac_setup(struct isac *isac)
{ {
int val, eval; int val, eval;
...@@ -890,7 +890,7 @@ EXPORT_SYMBOL(isac_d_l2l1); ...@@ -890,7 +890,7 @@ EXPORT_SYMBOL(isac_d_l2l1);
EXPORT_SYMBOL(isacsx_setup); EXPORT_SYMBOL(isacsx_setup);
EXPORT_SYMBOL(isacsx_irq); EXPORT_SYMBOL(isacsx_irq);
EXPORT_SYMBOL(isac_setup); EXPORT_SYMBOL(hisax_isac_setup);
EXPORT_SYMBOL(isac_irq); EXPORT_SYMBOL(isac_irq);
module_init(hisax_isac_init); module_init(hisax_isac_init);
......
...@@ -36,7 +36,7 @@ struct isac { ...@@ -36,7 +36,7 @@ struct isac {
void isac_init(struct isac *isac); void isac_init(struct isac *isac);
void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
void isac_setup(struct isac *isac); void hisax_isac_setup(struct isac *isac);
void isac_irq(struct isac *isac); void isac_irq(struct isac *isac);
void isacsx_setup(struct isac *isac); void isacsx_setup(struct isac *isac);
......
...@@ -126,7 +126,7 @@ static char *strL1Event[] = ...@@ -126,7 +126,7 @@ static char *strL1Event[] =
}; };
void void
debugl1(struct IsdnCardState *cs, char *fmt, ...) debugl1(struct IsdnCardState *cs, const char *fmt, ...)
{ {
va_list args; va_list args;
char tmp[8]; char tmp[8];
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define B_LL_CONNECT 9 #define B_LL_CONNECT 9
#define B_LL_OK 10 #define B_LL_OK 10
extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...);
extern void DChannel_proc_xmt(struct IsdnCardState *cs); extern void DChannel_proc_xmt(struct IsdnCardState *cs);
extern void DChannel_proc_rcv(struct IsdnCardState *cs); extern void DChannel_proc_rcv(struct IsdnCardState *cs);
extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg); extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
......
...@@ -187,95 +187,92 @@ static struct card_ops isurf_ops = { ...@@ -187,95 +187,92 @@ static struct card_ops isurf_ops = {
static struct pnp_card *pnp_surf __devinitdata = NULL; static struct pnp_card *pnp_surf __devinitdata = NULL;
#endif #endif
int __init static int __init
setup_isurf(struct IsdnCard *card) isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
unsigned long phymem; unsigned long phymem;
char tmp[64];
strcpy(tmp, ISurf_revision); phymem = card->para[2];
printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); cs->hw.isurf.reset = card->para[1];
cs->irq = card->para[0];
if (card->para[1] && card->para[2]) {
cs->hw.isurf.reset = card->para[1];
phymem = card->para[2];
cs->irq = card->para[0];
} else {
#ifdef __ISAPNP__
struct pnp_card *pb;
struct pnp_dev *pd;
if (isapnp_present()) {
cs->subtyp = 0;
if ((pb = pnp_find_card(
ISAPNP_VENDOR('S', 'I', 'E'),
ISAPNP_FUNCTION(0x0010), pnp_surf))) {
pnp_surf = pb;
pd = NULL;
if (!(pd = pnp_find_dev(pnp_surf,
ISAPNP_VENDOR('S', 'I', 'E'),
ISAPNP_FUNCTION(0x0010), pd))) {
printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
return (0);
}
if (pnp_device_attach(pd) < 0) {
printk(KERN_ERR "ISurfPnP: attach failed\n");
return 0;
}
if (pnp_activate_dev(pd) < 0) {
printk(KERN_ERR "ISurfPnP: activate failed\n");
pnp_device_detach(pd);
return 0;
}
if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
pnp_device_detach(pd);
return(0);
}
cs->hw.isurf.reset = pnp_port_start(pd, 0);
phymem = pnp_port_start(pd, 1);
cs->irq = pnp_irq(pd, 0);
} else {
printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
return(0);
}
} else {
printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
return(0);
}
#else
printk(KERN_WARNING "HiSax: %s port/mem not set\n",
CardType[card->typ]);
return (0);
#endif
}
if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn")) if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn"))
goto err; goto err;
cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem");
cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE,
"isurf iomem");
if (!cs->hw.isurf.isar) if (!cs->hw.isurf.isar)
goto err; goto err;
cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
printk(KERN_INFO printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
"ISurf: defined at 0x%x 0x%lx IRQ %d\n", cs->hw.isurf.reset, phymem, cs->irq);
cs->hw.isurf.reset,
card->para[2],
cs->irq);
cs->auxcmd = &isurf_auxcmd; cs->auxcmd = &isurf_auxcmd;
cs->card_ops = &isurf_ops; cs->card_ops = &isurf_ops;
cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
reset_isurf(cs, ISURF_RESET); reset_isurf(cs, ISURF_RESET);
test_and_set_bit(HW_ISAR, &cs->HW_Flags); __set_bit(HW_ISAR, &cs->HW_Flags);
isac_setup(cs, &isac_ops); isac_setup(cs, &isac_ops);
if (isar_setup(cs, &isar_ops)) if (isar_setup(cs, &isar_ops))
goto err; goto err;
return 1; return 0;
err: err:
hisax_release_resources(cs); hisax_release_resources(cs);
return 0; return -EBUSY;
}
int __init
setup_isurf(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, ISurf_revision);
printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
#ifdef __ISAPNP__
if (!card->para[1] || !card->para[2]) {
struct pnp_card *pb;
struct pnp_dev *pd;
cs->subtyp = 0;
if ((pb = pnp_find_card(
ISAPNP_VENDOR('S', 'I', 'E'),
ISAPNP_FUNCTION(0x0010), pnp_surf))) {
pnp_surf = pb;
pd = NULL;
if (!(pd = pnp_find_dev(pnp_surf,
ISAPNP_VENDOR('S', 'I', 'E'),
ISAPNP_FUNCTION(0x0010), pd))) {
printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
return (0);
}
if (pnp_device_attach(pd) < 0) {
printk(KERN_ERR "ISurfPnP: attach failed\n");
return 0;
}
if (pnp_activate_dev(pd) < 0) {
printk(KERN_ERR "ISurfPnP: activate failed\n");
pnp_device_detach(pd);
return 0;
}
if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) {
printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n",
pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1));
pnp_device_detach(pd);
return(0);
}
card->para[1] = pnp_port_start(pd, 0);
card->para[2] = pnp_port_start(pd, 1);
card->para[0] = pnp_irq(pd, 0);
} else {
printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
return 0;
}
}
#endif
if (isurf_probe(card->cs, card) < 0)
return 0;
return 1;
} }
...@@ -162,6 +162,29 @@ static struct card_ops ix1_ops = { ...@@ -162,6 +162,29 @@ static struct card_ops ix1_ops = {
.irq_func = hscxisac_irq, .irq_func = hscxisac_irq,
}; };
static int __init
ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->irq = card->para[0];
cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET;
cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
cs->hw.ix1.cfg_reg = card->para[1];
if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
goto err;
printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
ix1_reset(cs);
cs->card_ops = &ix1_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct isapnp_device_id itk_ids[] __initdata = { static struct isapnp_device_id itk_ids[] __initdata = {
{ ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25), { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
...@@ -181,14 +204,18 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -181,14 +204,18 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __init int __init
setup_ix1micro(struct IsdnCard *card) setup_ix1micro(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, ix1_revision); strcpy(tmp, ix1_revision);
printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp));
if (card->para[1]) {
if (ix1_probe(card->cs, card))
return 0;
return 1;
}
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) { if (isapnp_present()) {
struct pnp_card *pb; struct pnp_card *pb;
struct pnp_dev *pd; struct pnp_dev *pd;
...@@ -221,7 +248,9 @@ setup_ix1micro(struct IsdnCard *card) ...@@ -221,7 +248,9 @@ setup_ix1micro(struct IsdnCard *card)
} }
card->para[1] = pnp_port_start(pd, 0); card->para[1] = pnp_port_start(pd, 0);
card->para[0] = pnp_irq(pd, 0); card->para[0] = pnp_irq(pd, 0);
break; if (ix1_probe(card->cs, card))
return 0;
return 1;
} else { } else {
printk(KERN_ERR "ITK PnP: PnP error card found, no device\n"); printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
} }
...@@ -231,27 +260,8 @@ setup_ix1micro(struct IsdnCard *card) ...@@ -231,27 +260,8 @@ setup_ix1micro(struct IsdnCard *card)
} }
if (!idev->card_vendor) { if (!idev->card_vendor) {
printk(KERN_INFO "ITK PnP: no ISAPnP card found\n"); printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
return(0);
} }
} }
#endif #endif
/* IO-Ports */
cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET;
cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET;
cs->hw.ix1.cfg_reg = card->para[1];
cs->irq = card->para[0];
if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg"))
goto err;
printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg);
ix1_reset(cs);
cs->card_ops = &ix1_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
return 1;
err:
hisax_release_resources(cs);
return 0; return 0;
} }
...@@ -138,17 +138,11 @@ static struct card_ops mic_ops = { ...@@ -138,17 +138,11 @@ static struct card_ops mic_ops = {
.irq_func = hscxisac_irq, .irq_func = hscxisac_irq,
}; };
int __init static int __init
setup_mic(struct IsdnCard *card) mic_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, mic_revision);
printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
cs->hw.mic.cfg_reg = card->para[1];
cs->irq = card->para[0]; cs->irq = card->para[0];
cs->hw.mic.cfg_reg = card->para[1];
cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR;
cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC;
cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX;
...@@ -158,11 +152,25 @@ setup_mic(struct IsdnCard *card) ...@@ -158,11 +152,25 @@ setup_mic(struct IsdnCard *card)
printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n",
cs->hw.mic.cfg_reg, cs->irq); cs->hw.mic.cfg_reg, cs->irq);
cs->card_ops = &mic_ops; cs->card_ops = &mic_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err; goto err;
return 1; return 0;
err: err:
hisax_release_resources(cs); hisax_release_resources(cs);
return 0; return -EBUSY;
}
int __init
setup_mic(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, mic_revision);
printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp));
if (mic_probe(card->cs, card) < 0)
return 0;
return 1;
} }
...@@ -199,6 +199,70 @@ static struct card_ops niccy_ops = { ...@@ -199,6 +199,70 @@ static struct card_ops niccy_ops = {
.irq_func = niccy_interrupt, .irq_func = niccy_interrupt,
}; };
static int __init
niccy_probe(struct IsdnCardState *cs)
{
printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
cs->card_ops = &niccy_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
return -EBUSY;
return 0;
}
static int __init
niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->subtyp = NICCY_PNP;
cs->irq = card->para[0];
cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP;
cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
cs->hw.niccy.cfg_reg = 0;
if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
goto err;
if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
goto err;
if (niccy_probe(cs) < 0)
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
u32 pci_ioaddr;
if (pci_enable_device(pdev))
goto err;
cs->subtyp = NICCY_PCI;
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0);
pci_ioaddr = pci_resource_start(pdev, 1);
cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
goto err;
if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
goto err;
if (niccy_probe(cs) < 0)
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static struct pci_dev *niccy_dev __initdata = NULL; static struct pci_dev *niccy_dev __initdata = NULL;
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct pnp_card *pnp_c __devinitdata = NULL; static struct pnp_card *pnp_c __devinitdata = NULL;
...@@ -207,7 +271,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -207,7 +271,6 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __init int __init
setup_niccy(struct IsdnCard *card) setup_niccy(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, niccy_revision); strcpy(tmp, niccy_revision);
...@@ -252,66 +315,18 @@ setup_niccy(struct IsdnCard *card) ...@@ -252,66 +315,18 @@ setup_niccy(struct IsdnCard *card)
} }
#endif #endif
if (card->para[1]) { if (card->para[1]) {
cs->hw.niccy.isac = card->para[1] + ISAC_PNP; if (niccy_pnp_probe(card->cs, card) < 0)
cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; return 0;
cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; return 1;
cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP;
cs->hw.niccy.cfg_reg = 0;
cs->subtyp = NICCY_PNP;
cs->irq = card->para[0];
if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data"))
goto err;
if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr"))
goto err;
} else { } else {
#if CONFIG_PCI #if CONFIG_PCI
u_int pci_ioaddr;
cs->subtyp = 0;
if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) {
if (pci_enable_device(niccy_dev)) if (niccy_pci_probe(card->cs, niccy_dev) < 0)
return(0); return 0;
/* get IRQ */ return 1;
if (!niccy_dev->irq) {
printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
return(0);
}
cs->irq = niccy_dev->irq;
cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
if (!cs->hw.niccy.cfg_reg) {
printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
return(0);
}
pci_ioaddr = pci_resource_start(niccy_dev, 1);
if (!pci_ioaddr) {
printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
return(0);
}
cs->subtyp = NICCY_PCI;
} else {
printk(KERN_WARNING "Niccy: No PCI card found\n");
return(0);
} }
cs->irq_flags |= SA_SHIRQ;
cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy"))
goto err;
if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci"))
goto err;
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
} }
printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
cs->card_ops = &niccy_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
return 1;
err:
niccy_release(cs);
return 0; return 0;
} }
...@@ -106,96 +106,99 @@ static struct card_ops nj_s_ops = { ...@@ -106,96 +106,99 @@ static struct card_ops nj_s_ops = {
.irq_func = nj_s_interrupt, .irq_func = nj_s_interrupt,
}; };
static struct pci_dev *dev_netjet __initdata = NULL; static int __init
nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
int __init
setup_netjet_s(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs; if (pci_enable_device(pdev))
char tmp[64]; goto err;
#ifdef __BIG_ENDIAN pci_set_master(pdev);
#error "not running on big endian machines now"
#endif
strcpy(tmp, NETjet_S_revision);
printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
for ( ;; ) {
if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
if (pci_enable_device(dev_netjet))
return(0);
pci_set_master(dev_netjet);
cs->irq = dev_netjet->irq;
if (!cs->irq) {
printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
return(0);
}
cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
if (!cs->hw.njet.base) {
printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
return(0);
}
/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
if ((dev_netjet->subsystem_vendor == 0x55) &&
(dev_netjet->subsystem_device == 0x02)) {
printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
return(0);
}
/* end new code */
cs->hw.njet.pdev = dev_netjet;
} else {
printk(KERN_WARNING "NETjet-S: No PCI card found\n");
return(0);
}
cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE); cs->irq = pdev->irq;
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ cs->irq_flags |= SA_SHIRQ;
cs->hw.njet.pdev = pdev;
cs->hw.njet.auxd = 0xC0; cs->hw.njet.base = pci_resource_start(pdev, 0);
cs->hw.njet.dmactrl = 0; if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
return 0;
byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) ) cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
{ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
case 0 :
break;
case 3 : set_current_state(TASK_UNINTERRUPTIBLE);
printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
continue;
cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.auxd = 0xC0;
cs->hw.njet.dmactrl = 0;
byteout(cs->hw.njet.auxa, 0);
byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
default : switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) {
printk( KERN_WARNING "NETjet-S: No PCI card found\n" ); case 0 :
return 0; break;
} case 3 :
break; printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" );
goto err;
default :
printk(KERN_WARNING "NETjet-S: No PCI card found\n" );
goto err;
} }
printk(KERN_INFO printk(KERN_INFO
"NETjet-S: PCI card configured at %#lx IRQ %d\n", "NETjet-S: PCI card configured at %#lx IRQ %d\n",
cs->hw.njet.base, cs->irq); cs->hw.njet.base, cs->irq);
if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
return 0;
nj_s_reset(cs); nj_s_reset(cs);
cs->irq_flags |= SA_SHIRQ; cs->irq_flags |= SA_SHIRQ;
cs->card_ops = &nj_s_ops; cs->card_ops = &nj_s_ops;
isac_setup(cs, &netjet_dc_ops); isac_setup(cs, &netjet_dc_ops);
return 1; return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static struct pci_dev *dev_netjet __initdata = NULL;
int __init
setup_netjet_s(struct IsdnCard *card)
{
char tmp[64];
#ifdef __BIG_ENDIAN
#error "not running on big endian machines now"
#endif
strcpy(tmp, NETjet_S_revision);
printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n",
HiSax_getrev(tmp));
dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
if (dev_netjet) {
/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
if (dev_netjet->subsystem_vendor == 0x55 &&
dev_netjet->subsystem_device == 0x02) {
printk(KERN_WARNING "Netjet: You tried to load this "
"driver with an incompatible TigerJet-card\n");
printk(KERN_WARNING "Use type=41 for Formula-n "
"enter:now ISDN PCI and compatible\n");
return 0;
}
if (nj_s_probe(card->cs, dev_netjet))
return 1;
return 0;
}
printk(KERN_WARNING "NETjet-S: No PCI card found\n");
return 0;
} }
...@@ -110,88 +110,85 @@ static struct card_ops nj_u_ops = { ...@@ -110,88 +110,85 @@ static struct card_ops nj_u_ops = {
.irq_func = nj_u_interrupt, .irq_func = nj_u_interrupt,
}; };
static int __init
nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
pci_set_master(pdev);
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.njet.pdev = pdev;
cs->hw.njet.base = pci_resource_start(pdev, 0);
if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn"))
goto err;
cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.auxd = 0xC0;
cs->hw.njet.dmactrl = 0;
byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3) {
case 3:
break;
case 0:
printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
goto err;
default:
printk(KERN_WARNING "NETspider-U: No PCI card found\n" );
goto err;
}
printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n",
cs->hw.njet.base, cs->irq);
nj_u_reset(cs);
cs->card_ops = &nj_u_ops;
icc_setup(cs, &netjet_dc_ops);
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static struct pci_dev *dev_netjet __initdata = NULL; static struct pci_dev *dev_netjet __initdata = NULL;
int __init int __init
setup_netjet_u(struct IsdnCard *card) setup_netjet_u(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
#error "not running on big endian machines now" #error "not running on big endian machines now"
#endif #endif
strcpy(tmp, NETjet_U_revision); strcpy(tmp, NETjet_U_revision);
printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n",
HiSax_getrev(tmp));
for ( ;; ) {
if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
if (pci_enable_device(dev_netjet))
return(0);
pci_set_master(dev_netjet);
cs->irq = dev_netjet->irq;
if (!cs->irq) {
printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
return(0);
}
cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
if (!cs->hw.njet.base) {
printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
return(0);
}
cs->hw.njet.pdev = dev_netjet;
} else {
printk(KERN_WARNING "NETspider-U: No PCI card found\n");
return(0);
}
cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
cs->hw.njet.auxd = 0xC0;
cs->hw.njet.dmactrl = 0;
byteout(cs->hw.njet.auxa, 0);
byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) )
{
case 3 :
break;
case 0 :
printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" );
continue;
default :
printk( KERN_WARNING "NETspider-U: No PCI card found\n" );
return 0;
}
break;
}
printk(KERN_INFO
"NETspider-U: PCI card configured at %#lx IRQ %d\n",
cs->hw.njet.base, cs->irq);
if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn"))
return 0;
nj_u_reset(cs); dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET,
cs->irq_flags |= SA_SHIRQ; PCI_DEVICE_ID_TIGERJET_300, dev_netjet);
cs->card_ops = &nj_u_ops; if (dev_netjet) {
icc_setup(cs, &netjet_dc_ops); if (nj_u_probe(card->cs, dev_netjet))
return 1; return 1;
return 0;
}
printk(KERN_WARNING "NETspider-U: No PCI card found\n");
return 0;
} }
...@@ -172,14 +172,9 @@ static struct card_ops s0box_ops = { ...@@ -172,14 +172,9 @@ static struct card_ops s0box_ops = {
.irq_func = hscxisac_irq, .irq_func = hscxisac_irq,
}; };
int __init static int __init
setup_s0box(struct IsdnCard *card) s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, s0box_revision);
printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
cs->hw.teles3.cfg_reg = card->para[1]; cs->hw.teles3.cfg_reg = card->para[1];
cs->hw.teles3.hscx[0] = -0x20; cs->hw.teles3.hscx[0] = -0x20;
cs->hw.teles3.hscx[1] = 0x0; cs->hw.teles3.hscx[1] = 0x0;
...@@ -200,8 +195,20 @@ setup_s0box(struct IsdnCard *card) ...@@ -200,8 +195,20 @@ setup_s0box(struct IsdnCard *card)
cs->card_ops = &s0box_ops; cs->card_ops = &s0box_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err; goto err;
return 1; return 0;
err: err:
hisax_release_resources(cs); hisax_release_resources(cs);
return 0; return -EBUSY;
}
int __init
setup_s0box(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, s0box_revision);
printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
if (s0box_probe(card->cs, card))
return 0;
return 1;
} }
...@@ -201,36 +201,21 @@ static struct card_ops saphir_ops = { ...@@ -201,36 +201,21 @@ static struct card_ops saphir_ops = {
.irq_func = saphir_interrupt, .irq_func = saphir_interrupt,
}; };
int __init static int __init
setup_saphir(struct IsdnCard *card) saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, saphir_rev);
printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
return (0);
init_timer(&cs->hw.saphir.timer);
/* IO-Ports */
cs->hw.saphir.cfg_reg = card->para[1]; cs->hw.saphir.cfg_reg = card->para[1];
cs->hw.saphir.isac = card->para[1] + ISAC_DATA; cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
cs->hw.saphir.hscx = card->para[1] + HSCX_DATA; cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
cs->hw.saphir.ale = card->para[1] + ADDRESS_REG; cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
cs->irq = card->para[0]; cs->irq = card->para[0];
if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir")) if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir"))
goto err; goto err;
printk(KERN_INFO printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n",
"HiSax: %s config irq:%d io:0x%X\n", CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg);
CardType[cs->typ], cs->irq,
cs->hw.saphir.cfg_reg);
cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
cs->hw.saphir.timer.data = (long) cs;
cs->hw.saphir.timer.expires = jiffies + 4*HZ;
add_timer(&cs->hw.saphir.timer);
if (saphir_reset(cs)) if (saphir_reset(cs))
goto err; goto err;
...@@ -238,8 +223,27 @@ setup_saphir(struct IsdnCard *card) ...@@ -238,8 +223,27 @@ setup_saphir(struct IsdnCard *card)
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err; goto err;
return 1; init_timer(&cs->hw.saphir.timer);
err: cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
saphir_release(cs); cs->hw.saphir.timer.data = (long) cs;
cs->hw.saphir.timer.expires = jiffies + 4*HZ;
add_timer(&cs->hw.saphir.timer);
return 0; return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
int __init
setup_saphir(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, saphir_rev);
printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n",
HiSax_getrev(tmp));
if (saphir_probe(card->cs, card) < 0)
return 0;
return 1;
} }
...@@ -73,7 +73,6 @@ const char *Sedlbauer_Types[] = ...@@ -73,7 +73,6 @@ const char *Sedlbauer_Types[] =
#define SEDL_SPEEDFAX_PYRAMID 7 #define SEDL_SPEEDFAX_PYRAMID 7
#define SEDL_SPEEDFAX_PCI 8 #define SEDL_SPEEDFAX_PCI 8
#define SEDL_CHIP_TEST 0
#define SEDL_CHIP_ISAC_HSCX 1 #define SEDL_CHIP_ISAC_HSCX 1
#define SEDL_CHIP_ISAC_ISAR 2 #define SEDL_CHIP_ISAC_ISAR 2
#define SEDL_CHIP_IPAC 3 #define SEDL_CHIP_IPAC 3
...@@ -452,6 +451,241 @@ static struct card_ops sedlbauer_isar_ops = { ...@@ -452,6 +451,241 @@ static struct card_ops sedlbauer_isar_ops = {
.irq_func = sedlbauer_isar_interrupt, .irq_func = sedlbauer_isar_interrupt,
}; };
static int __init
sedl_ipac_probe(struct IsdnCardState *cs)
{
u8 val;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
return (val == 1 || val == 2);
}
static int __init
sedl_ipac_init(struct IsdnCardState *cs)
{
cs->card_ops = &sedlbauer_ipac_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
return -ENODEV;
sedlbauer_reset(cs);
return 0;
}
static int __init
sedl_isac_isar_init(struct IsdnCardState *cs)
{
cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
__set_bit(HW_ISAR, &cs->HW_Flags);
cs->card_ops = &sedlbauer_isar_ops;
cs->auxcmd = &isar_auxcmd;
isac_setup(cs, &isac_ops);
return isar_setup(cs, &isar_ops);
}
static int __init
sedl_isac_hscx_init(struct IsdnCardState *cs)
{
cs->card_ops = &sedlbauer_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
return -ENODEV;
sedlbauer_reset(cs);
return 0;
}
static int __init
sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->irq = card->para[0];
cs->hw.sedl.cfg_reg = card->para[1];
cs->hw.sedl.bus = SEDL_BUS_ISA;
if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn"))
goto err;
if (sedl_ipac_probe(cs)) {
cs->subtyp = SEDL_SPEED_WIN2_PC104;
cs->hw.sedl.chip = SEDL_CHIP_IPAC;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
if (sedl_ipac_init(cs))
goto err;
} else {
cs->subtyp = SEDL_SPEED_CARD_WIN;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
if (sedl_isac_hscx_init(cs))
goto err;
}
printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
Sedlbauer_Types[cs->subtyp],
cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
if (sedl_ipac_probe(cs)) {
cs->subtyp = SEDL_SPEED_STAR2;
cs->hw.sedl.chip = SEDL_CHIP_IPAC;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
if (sedl_ipac_init(cs))
goto err;
} else {
cs->subtyp = SEDL_SPEED_STAR;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
if (sedl_isac_hscx_init(cs))
goto err;
}
printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
Sedlbauer_Types[cs->subtyp],
cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq);
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->subtyp = SEDL_SPEED_FAX;
cs->hw.sedl.bus = SEDL_BUS_ISA;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn"))
goto err;
printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
Sedlbauer_Types[cs->subtyp],
cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq);
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
if (sedl_isac_isar_init(cs))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev)
{
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0);
cs->hw.sedl.bus = SEDL_BUS_PCI;
if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn"))
return -EBUSY;
printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n",
Sedlbauer_Types[cs->subtyp],
cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq);
cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
byteout(cs->hw.sedl.cfg_reg, 0xff);
byteout(cs->hw.sedl.cfg_reg, 0x00);
byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout((10*HZ)/1000);
byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
return 0;
}
static int __init
sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
cs->subtyp = SEDL_SPEEDFAX_PYRAMID;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
if (sedl_pci_init(cs, pdev))
goto err;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
if (sedl_isac_isar_init(cs))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
cs->subtyp = SEDL_SPEEDFAX_PCI;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
if (sedl_pci_init(cs, pdev))
goto err;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR;
if (sedl_isac_isar_init(cs))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
if (pci_enable_device(pdev))
goto err;
cs->subtyp = SEDL_SPEED_PCI;
cs->hw.sedl.chip = SEDL_CHIP_IPAC;
if (sedl_pci_init(cs, pdev))
goto err;
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
if (sedl_ipac_init(cs))
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static struct pci_dev *dev_sedl __devinitdata = NULL; static struct pci_dev *dev_sedl __devinitdata = NULL;
#ifdef __ISAPNP__ #ifdef __ISAPNP__
...@@ -472,265 +706,117 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -472,265 +706,117 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __devinit int __devinit
setup_sedlbauer(struct IsdnCard *card) setup_sedlbauer(struct IsdnCard *card)
{ {
int bytecnt, val;
struct IsdnCardState *cs = card->cs; struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
u16 sub_vendor_id, sub_id; u16 sub_vendor_id, sub_id;
strcpy(tmp, Sedlbauer_revision); strcpy(tmp, Sedlbauer_revision);
printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n",
HiSax_getrev(tmp));
if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
cs->subtyp = SEDL_SPEED_CARD_WIN;
cs->hw.sedl.bus = SEDL_BUS_ISA;
cs->hw.sedl.chip = SEDL_CHIP_TEST;
} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
cs->subtyp = SEDL_SPEED_STAR;
cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
cs->hw.sedl.chip = SEDL_CHIP_TEST;
} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
cs->subtyp = SEDL_SPEED_FAX;
cs->hw.sedl.bus = SEDL_BUS_ISA;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
} else
return (0);
bytecnt = 8;
if (card->para[1]) { if (card->para[1]) {
cs->hw.sedl.cfg_reg = card->para[1]; if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
cs->irq = card->para[0]; if (sedl_card_win_probe(card->cs, card) < 0)
if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { return 0;
bytecnt = 16; return 1;
} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
if (sedl_star_probe(card->cs, card) < 0)
return 0;
return 1;
} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
if (sedl_fax_probe(card->cs, card) < 0)
return 0;
return 1;
} }
} else { }
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (isapnp_present()) { if (isapnp_present()) {
struct pnp_card *pb; struct pnp_card *pb;
struct pnp_dev *pd; struct pnp_dev *pd;
while(pdev->card_vendor) { while(pdev->card_vendor) {
if ((pb = pnp_find_card(pdev->card_vendor, if ((pb = pnp_find_card(pdev->card_vendor,
pdev->card_device, pdev->card_device,
pnp_c))) { pnp_c))) {
pnp_c = pb; pnp_c = pb;
pd = NULL; pd = NULL;
if ((pd = pnp_find_dev(pnp_c, if ((pd = pnp_find_dev(pnp_c,
pdev->vendor, pdev->vendor,
pdev->function, pdev->function,
pd))) { pd))) {
printk(KERN_INFO "HiSax: %s detected\n", printk(KERN_INFO "HiSax: %s detected\n",
(char *)pdev->driver_data); (char *)pdev->driver_data);
if (pnp_device_attach(pd) < 0) { if (pnp_device_attach(pd) < 0) {
printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); printk(KERN_ERR "Sedlbauer PnP: attach failed\n");
return 0; return 0;
} }
if (pnp_activate_dev(pd) < 0) { if (pnp_activate_dev(pd) < 0) {
printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); printk(KERN_ERR "Sedlbauer PnP: activate failed\n");
pnp_device_detach(pd); pnp_device_detach(pd);
return 0;
}
if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
pnp_irq(pd, 0), pnp_port_start(pd, 0));
pnp_device_detach(pd);
goto err;
}
card->para[1] = pnp_port_start(pd, 0);
card->para[0] = pnp_irq(pd, 0);
cs->hw.sedl.cfg_reg = card->para[1];
cs->irq = card->para[0];
if (pdev->function == ISAPNP_FUNCTION(0x2)) {
if (sedl_fax_probe(card->cs, card))
return 0; return 0;
} return 1;
if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) {
printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
pnp_irq(pd, 0), pnp_port_start(pd, 0));
pnp_device_detach(pd);
goto err;
}
card->para[1] = pnp_port_start(pd, 0);
card->para[0] = pnp_irq(pd, 0);
cs->hw.sedl.cfg_reg = card->para[1];
cs->irq = card->para[0];
if (pdev->function == ISAPNP_FUNCTION(0x2)) {
cs->subtyp = SEDL_SPEED_FAX;
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
bytecnt = 16;
} else {
cs->subtyp = SEDL_SPEED_CARD_WIN;
cs->hw.sedl.chip = SEDL_CHIP_TEST;
}
goto ready;
} else { } else {
printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); if (sedl_card_win_probe(card->cs, card))
goto err; return 0;
return 1;
} }
} else {
printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
goto err;
} }
pdev++;
pnp_c=NULL;
}
if (!pdev->card_vendor) {
printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
} }
pdev++;
pnp_c=NULL;
}
if (!pdev->card_vendor) {
printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
} }
}
#endif #endif
/* Probe for Sedlbauer speed pci */ /* Probe for Sedlbauer speed pci */
#if CONFIG_PCI #if CONFIG_PCI
if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { PCI_DEVICE_ID_TIGERJET_100, dev_sedl);
if (pci_enable_device(dev_sedl)) if (dev_sedl) {
goto err;
cs->irq = dev_sedl->irq;
if (!cs->irq) {
printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
goto err;
}
cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
} else {
printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
goto err;
}
cs->irq_flags |= SA_SHIRQ;
cs->hw.sedl.bus = SEDL_BUS_PCI;
sub_vendor_id = dev_sedl->subsystem_vendor; sub_vendor_id = dev_sedl->subsystem_vendor;
sub_id = dev_sedl->subsystem_device; sub_id = dev_sedl->subsystem_device;
printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
sub_vendor_id, sub_id); sub_vendor_id, sub_id);
printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
cs->hw.sedl.cfg_reg);
if (sub_id != PCI_SUB_ID_SEDLBAUER) { if (sub_id != PCI_SUB_ID_SEDLBAUER) {
printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id);
goto err; return 0;
} }
if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) {
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; if (sedl_fax_pyramid_probe(cs, dev_sedl))
cs->subtyp = SEDL_SPEEDFAX_PYRAMID; return 0;
return 1;
} else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; if (sedl_fax_pci_probe(cs, dev_sedl))
cs->subtyp = SEDL_SPEEDFAX_PCI; return 0;
return 1;
} else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
cs->hw.sedl.chip = SEDL_CHIP_IPAC; if (sedl_pci_probe(cs, dev_sedl))
cs->subtyp = SEDL_SPEED_PCI; return 0;
} else { return 1;
printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
sub_vendor_id);
goto err;
}
bytecnt = 256;
cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON;
cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
byteout(cs->hw.sedl.cfg_reg, 0xff);
byteout(cs->hw.sedl.cfg_reg, 0x00);
byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout((10*HZ)/1000);
byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off);
#endif /* CONFIG_PCI */
}
ready:
/* In case of the sedlbauer pcmcia card, this region is in use,
* reserved for us by the card manager. So we do not check it
* here, it would fail.
*/
if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) {
if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn"))
goto err;
}
printk(KERN_INFO
"Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
cs->hw.sedl.cfg_reg,
cs->hw.sedl.cfg_reg + bytecnt,
cs->irq);
/*
* testing ISA and PCMCIA Cards for IPAC, default is ISAC
* do not test for PCI card, because ports are different
* and PCI card uses only IPAC (for the moment)
*/
if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC,
IPAC_ID);
printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val);
if ((val == 1) || (val == 2)) {
/* IPAC */
cs->subtyp = SEDL_SPEED_WIN2_PC104;
if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
cs->subtyp = SEDL_SPEED_STAR2;
}
cs->hw.sedl.chip = SEDL_CHIP_IPAC;
} else {
/* ISAC_HSCX oder ISAC_ISAR */
if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
}
}
}
/*
* hw.sedl.chip is now properly set
*/
printk(KERN_INFO "Sedlbauer: %s detected\n",
Sedlbauer_Types[cs->subtyp]);
if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
} else {
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
}
cs->card_ops = &sedlbauer_ipac_ops;
if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops))
goto err;
sedlbauer_reset(cs);
} else {
/* ISAC_HSCX oder ISAC_ISAR */
if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
SEDL_ISAR_PCI_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
SEDL_ISAR_PCI_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
SEDL_ISAR_PCI_ISAR;
} else {
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg +
SEDL_ISAR_ISA_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg +
SEDL_ISAR_ISA_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg +
SEDL_ISAR_ISA_ISAR;
cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg +
SEDL_ISAR_ISA_ISAR_RESET_ON;
cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg +
SEDL_ISAR_ISA_ISAR_RESET_OFF;
}
cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
test_and_set_bit(HW_ISAR, &cs->HW_Flags);
cs->card_ops = &sedlbauer_isar_ops;
cs->auxcmd = &isar_auxcmd;
isac_setup(cs, &isac_ops);
if (isar_setup(cs, &isar_ops))
goto err;
} else {
if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
} else {
cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
}
cs->card_ops = &sedlbauer_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
sedlbauer_reset(cs);
} }
printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n",
sub_vendor_id);
return 0;
} }
return 1; #endif /* CONFIG_PCI */
err:
hisax_release_resources(cs);
return 0; return 0;
} }
...@@ -189,42 +189,29 @@ get_io_range(struct IsdnCardState *cs) ...@@ -189,42 +189,29 @@ get_io_range(struct IsdnCardState *cs)
} }
return 0; return 0;
} }
int __init
setup_sportster(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, sportster_revision);
printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp));
cs->hw.spt.cfg_reg = card->para[1]; static int __init
sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->irq = card->para[0]; cs->irq = card->para[0];
cs->hw.spt.cfg_reg = card->para[1];
if (!get_io_range(cs)) if (!get_io_range(cs))
return (0); return -EBUSY;
cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC; cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC;
cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA; cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA;
cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB; cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB;
switch(cs->irq) { switch(cs->irq) {
case 5: cs->hw.spt.res_irq = 1; case 5: cs->hw.spt.res_irq = 1; break;
break; case 7: cs->hw.spt.res_irq = 2; break;
case 7: cs->hw.spt.res_irq = 2; case 10:cs->hw.spt.res_irq = 3; break;
break; case 11:cs->hw.spt.res_irq = 4; break;
case 10:cs->hw.spt.res_irq = 3; case 12:cs->hw.spt.res_irq = 5; break;
break; case 14:cs->hw.spt.res_irq = 6; break;
case 11:cs->hw.spt.res_irq = 4; case 15:cs->hw.spt.res_irq = 7; break;
break; default:
case 12:cs->hw.spt.res_irq = 5; printk(KERN_WARNING "Sportster: wrong IRQ\n");
break; goto err;
case 14:cs->hw.spt.res_irq = 6;
break;
case 15:cs->hw.spt.res_irq = 7;
break;
default:sportster_release(cs);
printk(KERN_WARNING "Sportster: wrong IRQ\n");
return(0);
} }
sportster_reset(cs); sportster_reset(cs);
printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n", printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n",
...@@ -234,8 +221,22 @@ setup_sportster(struct IsdnCard *card) ...@@ -234,8 +221,22 @@ setup_sportster(struct IsdnCard *card)
cs->card_ops = &sportster_ops; cs->card_ops = &sportster_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err; goto err;
return 1;
err:
hisax_release_resources(cs);
return 0; return 0;
err:
sportster_release(cs);
return -EBUSY;
}
int __init
setup_sportster(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, sportster_revision);
printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n",
HiSax_getrev(tmp));
if (sportster_probe(card->cs, card) < 0)
return 0;
return 1;
} }
...@@ -256,15 +256,9 @@ static struct card_ops teleint_ops = { ...@@ -256,15 +256,9 @@ static struct card_ops teleint_ops = {
.irq_func = teleint_interrupt, .irq_func = teleint_interrupt,
}; };
int __init static int __init
setup_TeleInt(struct IsdnCard *card) teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, TeleInt_revision);
printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
cs->hw.hfc.addr = card->para[1] & 0x3fe; cs->hw.hfc.addr = card->para[1] & 0x3fe;
cs->irq = card->para[0]; cs->irq = card->para[0];
cs->hw.hfc.cirm = HFC_CIRM; cs->hw.hfc.cirm = HFC_CIRM;
...@@ -284,42 +278,54 @@ setup_TeleInt(struct IsdnCard *card) ...@@ -284,42 +278,54 @@ setup_TeleInt(struct IsdnCard *card)
byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff); byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54); byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
switch (cs->irq) { switch (cs->irq) {
case 3: case 3:
cs->hw.hfc.cirm |= HFC_INTA; cs->hw.hfc.cirm |= HFC_INTA;
break; break;
case 4: case 4:
cs->hw.hfc.cirm |= HFC_INTB; cs->hw.hfc.cirm |= HFC_INTB;
break; break;
case 5: case 5:
cs->hw.hfc.cirm |= HFC_INTC; cs->hw.hfc.cirm |= HFC_INTC;
break; break;
case 7: case 7:
cs->hw.hfc.cirm |= HFC_INTD; cs->hw.hfc.cirm |= HFC_INTD;
break; break;
case 10: case 10:
cs->hw.hfc.cirm |= HFC_INTE; cs->hw.hfc.cirm |= HFC_INTE;
break; break;
case 11: case 11:
cs->hw.hfc.cirm |= HFC_INTF; cs->hw.hfc.cirm |= HFC_INTF;
break; break;
default: default:
printk(KERN_WARNING "TeleInt: wrong IRQ\n"); printk(KERN_WARNING "TeleInt: wrong IRQ\n");
goto err; goto err;
} }
byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
printk(KERN_INFO printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
"TeleInt: defined at 0x%x IRQ %d\n", cs->hw.hfc.addr, cs->irq);
cs->hw.hfc.addr,
cs->irq);
cs->card_ops = &teleint_ops; cs->card_ops = &teleint_ops;
teleint_reset(cs); teleint_reset(cs);
isac_setup(cs, &isac_ops); isac_setup(cs, &isac_ops);
hfc_setup(cs, &hfc_ops); hfc_setup(cs, &hfc_ops);
return 1;
err:
teleint_release(cs);
return 0; return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
int __init
setup_TeleInt(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, TeleInt_revision);
printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
if (teleint_probe(card->cs, card) < 0)
return 0;
return 1;
} }
...@@ -165,72 +165,95 @@ static struct card_ops teles0_ops = { ...@@ -165,72 +165,95 @@ static struct card_ops teles0_ops = {
.irq_func = hscxisac_irq, .irq_func = hscxisac_irq,
}; };
int __init static int __init
setup_teles0(struct IsdnCard *card) teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{ {
u8 val;
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, teles0_revision);
printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp));
if (cs->typ == ISDN_CTYPE_16_0)
cs->hw.teles0.cfg_reg = card->para[2];
else /* 8.0 */
cs->hw.teles0.cfg_reg = 0;
if (card->para[1] < 0x10000) {
card->para[1] <<= 4;
printk(KERN_INFO
"Teles0: membase configured DOSish, assuming 0x%lx\n",
(unsigned long) card->para[1]);
}
cs->irq = card->para[0]; cs->irq = card->para[0];
if (cs->hw.teles0.cfg_reg) {
if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
goto err;
if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
cs->hw.teles0.cfg_reg + 0, val);
goto err;
}
if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
cs->hw.teles0.cfg_reg + 1, val);
goto err;
}
val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
* 0x1f=with AB
* 0x1c 16.3 ???
*/
if (val != 0x1e && val != 0x1f) {
printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
cs->hw.teles0.cfg_reg + 2, val);
goto err;
}
}
/* 16.0 and 8.0 designed for IOM1 */ /* 16.0 and 8.0 designed for IOM1 */
test_and_set_bit(HW_IOM1, &cs->HW_Flags); test_and_set_bit(HW_IOM1, &cs->HW_Flags);
cs->hw.teles0.phymem = card->para[1]; cs->hw.teles0.phymem = card->para[1];
cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem"); cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem,
TELES_IOMEM_SIZE, "teles iomem");
if (!cs->hw.teles0.membase) if (!cs->hw.teles0.membase)
goto err; return -EBUSY;
printk(KERN_INFO
"HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n",
CardType[cs->typ], cs->irq,
cs->hw.teles0.membase, cs->hw.teles0.cfg_reg);
if (teles0_reset(cs)) { if (teles0_reset(cs)) {
printk(KERN_WARNING "Teles0: wrong IRQ\n"); printk(KERN_WARNING "Teles0: wrong IRQ\n");
goto err; return -EBUSY;
} }
cs->card_ops = &teles0_ops; cs->card_ops = &teles0_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err; return -EBUSY;
return 1;
return 0;
}
static int __init
teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
u8 val;
cs->hw.teles0.cfg_reg = card->para[2];
if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg"))
goto err;
if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) {
printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
cs->hw.teles0.cfg_reg + 0, val);
goto err;
}
if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) {
printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
cs->hw.teles0.cfg_reg + 1, val);
goto err;
}
val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB
* 0x1f=with AB
* 0x1c 16.3 ???
*/
if (val != 0x1e && val != 0x1f) {
printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n",
cs->hw.teles0.cfg_reg + 2, val);
goto err;
}
if (teles0_probe(cs, card) < 0)
goto err;
return 0;
err: err:
hisax_release_resources(cs); hisax_release_resources(cs);
return -EBUSY;
}
static int __init
teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->hw.teles0.cfg_reg = 0;
if (teles0_probe(cs, card) < 0)
goto err;
return 0; return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
int __init
setup_teles0(struct IsdnCard *card)
{
char tmp[64];
strcpy(tmp, teles0_revision);
printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n",
HiSax_getrev(tmp));
if (card->cs->typ == ISDN_CTYPE_16_0) {
if (teles16_0_probe(card->cs, card) < 0)
return 0;
} else {
if (teles8_0_probe(card->cs, card) < 0)
return 0;
}
return 1;
} }
...@@ -176,6 +176,152 @@ static struct card_ops teles3_ops = { ...@@ -176,6 +176,152 @@ static struct card_ops teles3_ops = {
.irq_func = hscxisac_irq, .irq_func = hscxisac_irq,
}; };
static int
teles_hw_init(struct IsdnCardState *cs)
{
printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n",
CardType[cs->typ], cs->irq,
cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
printk(KERN_INFO "HiSax: hscx A:0x%X hscx B:0x%X\n",
cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
if (teles3_reset(cs)) {
printk(KERN_WARNING "Teles3: wrong IRQ\n");
return -EBUSY;
}
cs->card_ops = &teles3_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
return -EBUSY;
return 0;
}
static void __init
teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->irq = card->para[0];
cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
}
static int __init
telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->hw.teles3.cfg_reg = 0;
cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
cs->hw.teles3.hscx[1] = card->para[1];
cs->hw.teles3.isac = card->para[1] + 0x20;
teles_setup_io(cs, card);
if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96,
"HiSax Teles PCMCIA"))
goto err;
if (teles_hw_init(cs) < 0)
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
teles_request_io(struct IsdnCardState *cs)
{
if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
return -EBUSY;
if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A"))
return -EBUSY;
if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B"))
return -EBUSY;
return 0;
}
static int __init
teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
u8 val;
cs->hw.teles3.cfg_reg = card->para[1];
switch (cs->hw.teles3.cfg_reg) {
case 0x180:
case 0x280:
case 0x380:
cs->hw.teles3.cfg_reg |= 0xc00;
break;
}
cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
teles_setup_io(cs, card);
if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
goto err;
if (teles_request_io(cs) < 0)
goto err;
if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
cs->hw.teles3.cfg_reg + 0, val);
goto err;
}
if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
cs->hw.teles3.cfg_reg + 1, val);
goto err;
}
/* 0x1e without AB, 0x1f with AB, 0x1c 16.3 ???,
* 0x39 16.3 1.1, 0x38 16.3 1.3, 0x46 16.3 with AB + Video */
val = bytein(cs->hw.teles3.cfg_reg + 2);
if (val != 0x46 && val != 0x39 && val != 0x38 &&
val != 0x1c && val != 0x1e && val != 0x1f) {
printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
cs->hw.teles3.cfg_reg + 2, val);
goto err;
}
if (teles_hw_init(cs) < 0)
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->hw.teles3.cfg_reg = card->para[3];
cs->hw.teles3.isac = card->para[2] - 32;
cs->hw.teles3.hscx[0] = card->para[1] - 32;
cs->hw.teles3.hscx[1] = card->para[1];
teles_setup_io(cs, card);
if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
goto err;
if (teles_request_io(cs) < 0)
goto err;
if (teles_hw_init(cs) < 0)
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
static int __init
telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card)
{
cs->hw.teles3.cfg_reg = 0;
cs->hw.teles3.isac = card->para[1] - 32;
cs->hw.teles3.hscx[0] = card->para[2] - 32;
cs->hw.teles3.hscx[1] = card->para[2];
teles_setup_io(cs, card);
if (teles_request_io(cs) < 0)
goto err;
if (teles_hw_init(cs) < 0)
goto err;
return 0;
err:
hisax_release_resources(cs);
return -EBUSY;
}
#ifdef __ISAPNP__ #ifdef __ISAPNP__
static struct isapnp_device_id teles_ids[] __initdata = { static struct isapnp_device_id teles_ids[] __initdata = {
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
...@@ -197,16 +343,10 @@ static struct pnp_card *pnp_c __devinitdata = NULL; ...@@ -197,16 +343,10 @@ static struct pnp_card *pnp_c __devinitdata = NULL;
int __devinit int __devinit
setup_teles3(struct IsdnCard *card) setup_teles3(struct IsdnCard *card)
{ {
u8 val;
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
strcpy(tmp, teles3_revision); strcpy(tmp, teles3_revision);
printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp)); printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp));
if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP)
&& (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
return (0);
#ifdef __ISAPNP__ #ifdef __ISAPNP__
if (!card->para[1] && isapnp_present()) { if (!card->para[1] && isapnp_present()) {
struct pnp_card *pnp_card; struct pnp_card *pnp_card;
...@@ -258,100 +398,18 @@ setup_teles3(struct IsdnCard *card) ...@@ -258,100 +398,18 @@ setup_teles3(struct IsdnCard *card)
} }
} }
#endif #endif
if (cs->typ == ISDN_CTYPE_16_3) { if (card->cs->typ == ISDN_CTYPE_16_3) {
cs->hw.teles3.cfg_reg = card->para[1]; if (teles16_3_probe(card->cs, card) < 0)
switch (cs->hw.teles3.cfg_reg) { return 0;
case 0x180: } else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) {
case 0x280: if (telespcmcia_probe(card->cs, card) < 0)
case 0x380: return 0;
cs->hw.teles3.cfg_reg |= 0xc00; } else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
break; if (compaq_probe(card->cs, card) < 0)
} return 0;
cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420;
cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
cs->hw.teles3.cfg_reg = 0;
cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
cs->hw.teles3.hscx[1] = card->para[1];
cs->hw.teles3.isac = card->para[1] + 0x20;
} else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
cs->hw.teles3.cfg_reg = card->para[3];
cs->hw.teles3.isac = card->para[2] - 32;
cs->hw.teles3.hscx[0] = card->para[1] - 32;
cs->hw.teles3.hscx[1] = card->para[1];
} else { /* PNP */ } else { /* PNP */
cs->hw.teles3.cfg_reg = 0; if (telespnp_probe(card->cs, card) < 0)
cs->hw.teles3.isac = card->para[1] - 32; return 0;
cs->hw.teles3.hscx[0] = card->para[2] - 32;
cs->hw.teles3.hscx[1] = card->para[2];
}
cs->irq = card->para[0];
cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA"))
goto err;
} else {
if (cs->hw.teles3.cfg_reg) {
if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg"))
goto err;
} else {
if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg"))
goto err;
}
}
if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac"))
goto err;
if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A"))
goto err;
if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B"))
goto err;
}
if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) {
if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) {
printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
cs->hw.teles3.cfg_reg + 0, val);
goto err;
}
if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) {
printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
cs->hw.teles3.cfg_reg + 1, val);
goto err;
}
val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB
* 0x1f=with AB
* 0x1c 16.3 ???
* 0x39 16.3 1.1
* 0x38 16.3 1.3
* 0x46 16.3 with AB + Video (Teles-Vision)
*/
if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
cs->hw.teles3.cfg_reg + 2, val);
goto err;
}
}
printk(KERN_INFO
"HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n",
CardType[cs->typ], cs->irq,
cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg);
printk(KERN_INFO
"HiSax: hscx A:0x%X hscx B:0x%X\n",
cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32);
if (teles3_reset(cs)) {
printk(KERN_WARNING "Teles3: wrong IRQ\n");
goto err;
} }
cs->card_ops = &teles3_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err;
return 1; return 1;
err:
hisax_release_resources(cs);
return 0;
} }
...@@ -231,36 +231,23 @@ static struct card_ops telespci_ops = { ...@@ -231,36 +231,23 @@ static struct card_ops telespci_ops = {
.irq_func = telespci_interrupt, .irq_func = telespci_interrupt,
}; };
static struct pci_dev *dev_tel __initdata = NULL; static int __init
telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
int __init
setup_telespci(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs; int rc;
char tmp[64];
#ifdef __BIG_ENDIAN printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n",
#error "not running on big endian machines now" pci_resource_start(pdev, 0), pdev->irq);
#endif
strcpy(tmp, telespci_revision); rc = -EBUSY;
printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (pci_enable_device(pdev))
if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { goto err;
if (pci_enable_device(dev_tel))
return(0); cs->irq = pdev->irq;
cs->irq = dev_tel->irq; cs->irq_flags |= SA_SHIRQ;
if (!cs->irq) { cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci");
printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); if (!cs->hw.teles0.membase)
return(0); goto err;
}
cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci");
if (!cs->hw.teles0.membase)
goto err;
printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
pci_resource_start(dev_tel, 0), dev_tel->irq);
} else {
printk(KERN_WARNING "TelesPCI: No PCI card found\n");
return(0);
}
/* Initialize Zoran PCI controller */ /* Initialize Zoran PCI controller */
writel(0x00000000, cs->hw.teles0.membase + 0x28); writel(0x00000000, cs->hw.teles0.membase + 0x28);
...@@ -270,17 +257,36 @@ setup_telespci(struct IsdnCard *card) ...@@ -270,17 +257,36 @@ setup_telespci(struct IsdnCard *card)
writel(0x70000000, cs->hw.teles0.membase + 0x3C); writel(0x70000000, cs->hw.teles0.membase + 0x3C);
writel(0x61000000, cs->hw.teles0.membase + 0x40); writel(0x61000000, cs->hw.teles0.membase + 0x40);
/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
printk(KERN_INFO
"HiSax: %s config irq:%d mem:%p\n",
CardType[cs->typ], cs->irq,
cs->hw.teles0.membase);
cs->irq_flags |= SA_SHIRQ;
cs->card_ops = &telespci_ops; cs->card_ops = &telespci_ops;
if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) if (hscxisac_setup(cs, &isac_ops, &hscx_ops))
goto err; goto err;
return 1; return 0;
err: err:
hisax_release_resources(cs); hisax_release_resources(cs);
return rc;
}
static struct pci_dev *dev_tel __initdata = NULL;
int __init
setup_telespci(struct IsdnCard *card)
{
char tmp[64];
#ifdef __BIG_ENDIAN
#error "not running on big endian machines now"
#endif
strcpy(tmp, telespci_revision);
printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n",
HiSax_getrev(tmp));
dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN,
PCI_DEVICE_ID_ZORAN_36120, dev_tel);
if (dev_tel) {
if (telespci_probe(card->cs, dev_tel) < 0)
return 0;
return 1;
}
printk(KERN_WARNING "TelesPCI: No PCI card found\n");
return 0; return 0;
} }
...@@ -669,11 +669,11 @@ static int id_idx ; ...@@ -669,11 +669,11 @@ static int id_idx ;
static struct pci_dev *dev_w6692 __initdata = NULL; static struct pci_dev *dev_w6692 __initdata = NULL;
static int static int
w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops, w6692_hw_init(struct IsdnCardState *cs)
struct bc_hw_ops *bc_ops)
{ {
cs->dc_hw_ops = dc_ops; cs->card_ops = &w6692_ops;
cs->bc_hw_ops = bc_ops; cs->dc_hw_ops = &w6692_dc_hw_ops,
cs->bc_hw_ops = &w6692_bc_hw_ops;
dc_l1_init(cs, &w6692_dc_l1_ops); dc_l1_init(cs, &w6692_dc_l1_ops);
cs->bc_l1_ops = &w6692_bc_l1_ops; cs->bc_l1_ops = &w6692_bc_l1_ops;
W6692Version(cs, "W6692:"); W6692Version(cs, "W6692:");
...@@ -685,14 +685,45 @@ w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops, ...@@ -685,14 +685,45 @@ w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops,
return 0; return 0;
} }
static int __init
w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev)
{
int rc;
printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n",
id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
pci_resource_start(pdev, 1), pdev->irq);
rc = -EBUSY;
if (pci_enable_device(pdev))
goto err;
/* USR ISDN PCI card TA need some special handling */
if (cs->subtyp == W6692_WINBOND) {
if (pdev->subsystem_vendor == W6692_SV_USR &&
pdev->subsystem_device == W6692_SD_USR) {
cs->subtyp = W6692_USR;
}
}
cs->irq = pdev->irq;
cs->irq_flags |= SA_SHIRQ;
cs->hw.w6692.iobase = pci_resource_start(pdev, 1);
if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100,
id_list[cs->subtyp].card_name))
goto err;
w6692_hw_init(cs);
return 0;
err:
hisax_release_resources(cs);
return rc;
}
int __init int __init
setup_w6692(struct IsdnCard *card) setup_w6692(struct IsdnCard *card)
{ {
struct IsdnCardState *cs = card->cs;
char tmp[64]; char tmp[64];
u8 found = 0;
u8 pci_irq = 0;
u_int pci_ioaddr = 0;
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
#error "not running on big endian machines now" #error "not running on big endian machines now"
...@@ -704,54 +735,13 @@ setup_w6692(struct IsdnCard *card) ...@@ -704,54 +735,13 @@ setup_w6692(struct IsdnCard *card)
id_list[id_idx].device_id, id_list[id_idx].device_id,
dev_w6692); dev_w6692);
if (dev_w6692) { if (dev_w6692) {
if (pci_enable_device(dev_w6692)) card->cs->subtyp = id_idx;
continue; if (w6692_probe(card->cs, dev_w6692) < 0)
cs->subtyp = id_idx; return 0;
break; return 1;
} }
id_idx++; id_idx++;
} }
if (dev_w6692) { printk(KERN_WARNING "W6692: No PCI card found\n");
found = 1; return 0;
pci_irq = dev_w6692->irq;
/* I think address 0 is allways the configuration area */
/* and address 1 is the real IO space KKe 03.09.99 */
pci_ioaddr = pci_resource_start(dev_w6692, 1);
/* USR ISDN PCI card TA need some special handling */
if (cs->subtyp == W6692_WINBOND) {
if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
(W6692_SD_USR == dev_w6692->subsystem_device)) {
cs->subtyp = W6692_USR;
}
}
}
if (!found) {
printk(KERN_WARNING "W6692: No PCI card found\n");
return (0);
}
cs->irq = pci_irq;
if (!cs->irq) {
printk(KERN_WARNING "W6692: No IRQ for PCI card found\n");
return (0);
}
if (!pci_ioaddr) {
printk(KERN_WARNING "W6692: NO I/O Base Address found\n");
return (0);
}
cs->hw.w6692.iobase = pci_ioaddr;
printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
pci_ioaddr, pci_irq);
if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name))
return 0;
printk(KERN_INFO
"HiSax: %s config irq:%d I/O:%x\n",
id_list[cs->subtyp].card_name, cs->irq,
cs->hw.w6692.iobase);
cs->card_ops = &w6692_ops;
w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops);
cs->irq_flags |= SA_SHIRQ;
return (1);
} }
...@@ -85,7 +85,7 @@ config ISDN_TTY_FAX ...@@ -85,7 +85,7 @@ config ISDN_TTY_FAX
config ISDN_X25 config ISDN_X25
bool "X.25 PLP on top of ISDN" bool "X.25 PLP on top of ISDN"
depends on X25 depends on X25 && BROKEN
help help
This feature provides the X.25 protocol over ISDN connections. This feature provides the X.25 protocol over ISDN connections.
See <file:Documentation/isdn/README.x25> for more information See <file:Documentation/isdn/README.x25> for more information
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include "isdn_net.h" #include "isdn_net.h"
#include "isdn_ppp.h" #include "isdn_ppp.h"
#include "isdn_ciscohdlck.h" #include "isdn_ciscohdlck.h"
#include "isdn_concap.h"
#define ISDN_NET_TX_TIMEOUT (20*HZ) #define ISDN_NET_TX_TIMEOUT (20*HZ)
......
...@@ -867,7 +867,7 @@ isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto) ...@@ -867,7 +867,7 @@ isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto)
skb_pull(skb, 1); skb_pull(skb, 1);
} else { } else {
if (skb->len < 2) if (skb->len < 2)
return -1; return -EINVAL;
get_u16(skb->data, proto); get_u16(skb->data, proto);
skb_pull(skb, 2); skb_pull(skb, 2);
} }
...@@ -1037,7 +1037,7 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1037,7 +1037,7 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1); isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1);
ippp_push_proto(ind_ppp, skb, proto); ippp_push_proto(ind_ppp, skb, proto);
ippp_mp_xmit(idev, skb, proto); ippp_mp_xmit(idev, skb);
return 0; return 0;
drop: drop:
......
...@@ -91,12 +91,13 @@ ippp_mp_disconnected(isdn_net_dev *idev) ...@@ -91,12 +91,13 @@ ippp_mp_disconnected(isdn_net_dev *idev)
} }
void void
ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
{ {
struct ind_ppp *ind_ppp = idev->ind_priv; struct ind_ppp *ind_ppp = idev->ind_priv;
struct inl_ppp *inl_ppp = idev->mlp->inl_priv; struct inl_ppp *inl_ppp = idev->mlp->inl_priv;
unsigned char *p; unsigned char *p;
long txseq; u32 txseq;
u16 proto;
if (!(inl_ppp->mp_cfg & SC_MP_PROT)) { if (!(inl_ppp->mp_cfg & SC_MP_PROT)) {
return ippp_xmit(idev, skb); return ippp_xmit(idev, skb);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
int ippp_mp_bind(isdn_net_dev *idev); int ippp_mp_bind(isdn_net_dev *idev);
void ippp_mp_disconnected(isdn_net_dev *idev); void ippp_mp_disconnected(isdn_net_dev *idev);
int ippp_mp_bundle(isdn_net_dev *idev, int val); int ippp_mp_bundle(isdn_net_dev *idev, int val);
void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb);
void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto);
#else #else
...@@ -42,9 +42,9 @@ ippp_mp_bundle(isdn_net_dev *idev, int val) ...@@ -42,9 +42,9 @@ ippp_mp_bundle(isdn_net_dev *idev, int val)
} }
static inline void static inline void
ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb)
{ {
ippp_xmit(idev, skb, proto); ippp_xmit(idev, skb);
} }
static inline void static inline void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment