mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-15 09:34:17 +00:00
isdn: remove spellcaster driver
The 'sc' ISDN driver relies on using readl() to access ISA I/O memory. This has been deprecated and produced warnings since linux-2.3.23, disabled by default since 2.4.10 and finally removed in 2.6.5. I found this because the compiling the driver for ARM produces a warning: In file included from ../drivers/isdn/sc/includes.h:8:0, from ../drivers/isdn/sc/init.c:13: ../arch/arm/include/asm/io.h:115:21: note: expected 'const volatile void *' but argument is of type 'long unsigned int' It is pretty clear that this driver has not been used for a long time and there is no point fixing it now, so let's remove it. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2f7a791c92
commit
6cc5683401
@ -10,7 +10,6 @@ obj-$(CONFIG_ISDN_DIVERSION) += divert/
|
|||||||
obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/
|
obj-$(CONFIG_ISDN_DRV_HISAX) += hisax/
|
||||||
obj-$(CONFIG_ISDN_DRV_ICN) += icn/
|
obj-$(CONFIG_ISDN_DRV_ICN) += icn/
|
||||||
obj-$(CONFIG_ISDN_DRV_PCBIT) += pcbit/
|
obj-$(CONFIG_ISDN_DRV_PCBIT) += pcbit/
|
||||||
obj-$(CONFIG_ISDN_DRV_SC) += sc/
|
|
||||||
obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/
|
obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/
|
||||||
obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000/
|
obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000/
|
||||||
obj-$(CONFIG_HYSDN) += hysdn/
|
obj-$(CONFIG_HYSDN) += hysdn/
|
||||||
|
@ -130,8 +130,6 @@ source "drivers/isdn/icn/Kconfig"
|
|||||||
|
|
||||||
source "drivers/isdn/pcbit/Kconfig"
|
source "drivers/isdn/pcbit/Kconfig"
|
||||||
|
|
||||||
source "drivers/isdn/sc/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/isdn/act2000/Kconfig"
|
source "drivers/isdn/act2000/Kconfig"
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
config ISDN_DRV_SC
|
|
||||||
tristate "Spellcaster support"
|
|
||||||
depends on ISA
|
|
||||||
help
|
|
||||||
This enables support for the Spellcaster BRI ISDN boards. This
|
|
||||||
driver currently builds only in a modularized version.
|
|
||||||
To build it, choose M here: the module will be called sc.
|
|
||||||
See <file:Documentation/isdn/README.sc> for more information.
|
|
@ -1,10 +0,0 @@
|
|||||||
# Makefile for the sc ISDN device driver
|
|
||||||
|
|
||||||
# Each configuration option enables a list of files.
|
|
||||||
|
|
||||||
obj-$(CONFIG_ISDN_DRV_SC) += sc.o
|
|
||||||
|
|
||||||
# Multipart objects.
|
|
||||||
|
|
||||||
sc-y := shmem.o init.o packet.o command.o event.o \
|
|
||||||
ioctl.o interrupt.o message.o timer.o
|
|
@ -1,131 +0,0 @@
|
|||||||
/* $Id: card.h,v 1.1.10.1 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Driver parameters for SpellCaster ISA ISDN adapters
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CARD_H
|
|
||||||
#define CARD_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need these if they're not already included
|
|
||||||
*/
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/time.h>
|
|
||||||
#include <linux/isdnif.h>
|
|
||||||
#include <linux/irqreturn.h>
|
|
||||||
#include "message.h"
|
|
||||||
#include "scioc.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Amount of time to wait for a reset to complete
|
|
||||||
*/
|
|
||||||
#define CHECKRESET_TIME msecs_to_jiffies(4000)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Amount of time between line status checks
|
|
||||||
*/
|
|
||||||
#define CHECKSTAT_TIME msecs_to_jiffies(8000)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The maximum amount of time to wait for a message response
|
|
||||||
* to arrive. Use exclusively by send_and_receive
|
|
||||||
*/
|
|
||||||
#define SAR_TIMEOUT msecs_to_jiffies(10000)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macro to determine is a card id is valid
|
|
||||||
*/
|
|
||||||
#define IS_VALID_CARD(x) ((x >= 0) && (x <= cinst))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Per channel status and configuration
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int l2_proto;
|
|
||||||
int l3_proto;
|
|
||||||
char dn[50];
|
|
||||||
unsigned long first_sendbuf; /* Offset of first send buffer */
|
|
||||||
unsigned int num_sendbufs; /* Number of send buffers */
|
|
||||||
unsigned int free_sendbufs; /* Number of free sendbufs */
|
|
||||||
unsigned int next_sendbuf; /* Next sequential buffer */
|
|
||||||
char eazlist[50]; /* Set with SETEAZ */
|
|
||||||
char sillist[50]; /* Set with SETSIL */
|
|
||||||
int eazclear; /* Don't accept calls if TRUE */
|
|
||||||
} bchan;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Everything you want to know about the adapter ...
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
int model;
|
|
||||||
int driverId; /* LL Id */
|
|
||||||
char devicename[20]; /* The device name */
|
|
||||||
isdn_if *card; /* ISDN4Linux structure */
|
|
||||||
bchan *channel; /* status of the B channels */
|
|
||||||
char nChannels; /* Number of channels */
|
|
||||||
unsigned int interrupt; /* Interrupt number */
|
|
||||||
int iobase; /* I/O Base address */
|
|
||||||
int ioport[MAX_IO_REGS]; /* Index to I/O ports */
|
|
||||||
int shmem_pgport; /* port for the exp mem page reg. */
|
|
||||||
int shmem_magic; /* adapter magic number */
|
|
||||||
unsigned int rambase; /* Shared RAM base address */
|
|
||||||
unsigned int ramsize; /* Size of shared memory */
|
|
||||||
RspMessage async_msg; /* Async response message */
|
|
||||||
int want_async_messages; /* Snoop the Q ? */
|
|
||||||
unsigned char seq_no; /* Next send seq. number */
|
|
||||||
struct timer_list reset_timer; /* Check reset timer */
|
|
||||||
struct timer_list stat_timer; /* Check startproc timer */
|
|
||||||
unsigned char nphystat; /* Latest PhyStat info */
|
|
||||||
unsigned char phystat; /* Last PhyStat info */
|
|
||||||
HWConfig_pl hwconfig; /* Hardware config info */
|
|
||||||
char load_ver[11]; /* CommManage Version string */
|
|
||||||
char proc_ver[11]; /* CommEngine Version */
|
|
||||||
int StartOnReset; /* Indicates startproc after reset */
|
|
||||||
int EngineUp; /* Indicates CommEngine Up */
|
|
||||||
int trace_mode; /* Indicate if tracing is on */
|
|
||||||
spinlock_t lock; /* local lock */
|
|
||||||
} board;
|
|
||||||
|
|
||||||
|
|
||||||
extern board *sc_adapter[];
|
|
||||||
extern int cinst;
|
|
||||||
|
|
||||||
void memcpy_toshmem(int card, void *dest, const void *src, size_t n);
|
|
||||||
void memcpy_fromshmem(int card, void *dest, const void *src, size_t n);
|
|
||||||
int get_card_from_id(int driver);
|
|
||||||
int indicate_status(int card, int event, ulong Channel, char *Data);
|
|
||||||
irqreturn_t interrupt_handler(int interrupt, void *cardptr);
|
|
||||||
int sndpkt(int devId, int channel, int ack, struct sk_buff *data);
|
|
||||||
void rcvpkt(int card, RspMessage *rcvmsg);
|
|
||||||
int command(isdn_ctrl *cmd);
|
|
||||||
int reset(int card);
|
|
||||||
int startproc(int card);
|
|
||||||
int send_and_receive(int card, unsigned int procid, unsigned char type,
|
|
||||||
unsigned char class, unsigned char code,
|
|
||||||
unsigned char link, unsigned char data_len,
|
|
||||||
unsigned char *data, RspMessage *mesgdata, int timeout);
|
|
||||||
void flushreadfifo(int card);
|
|
||||||
int sendmessage(int card, unsigned int procid, unsigned int type,
|
|
||||||
unsigned int class, unsigned int code, unsigned int link,
|
|
||||||
unsigned int data_len, unsigned int *data);
|
|
||||||
int receivemessage(int card, RspMessage *rspmsg);
|
|
||||||
int sc_ioctl(int card, scs_ioctl *data);
|
|
||||||
int setup_buffers(int card, int c);
|
|
||||||
void sc_check_reset(unsigned long data);
|
|
||||||
void check_phystat(unsigned long data);
|
|
||||||
|
|
||||||
#endif /* CARD_H */
|
|
@ -1,363 +0,0 @@
|
|||||||
/* $Id: command.c,v 1.4.10.1 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include "includes.h" /* This must be first */
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "message.h"
|
|
||||||
#include "card.h"
|
|
||||||
#include "scioc.h"
|
|
||||||
|
|
||||||
static int dial(int card, unsigned long channel, setup_parm setup);
|
|
||||||
static int hangup(int card, unsigned long channel);
|
|
||||||
static int answer(int card, unsigned long channel);
|
|
||||||
static int clreaz(int card, unsigned long channel);
|
|
||||||
static int seteaz(int card, unsigned long channel, char *);
|
|
||||||
static int setl2(int card, unsigned long arg);
|
|
||||||
static int setl3(int card, unsigned long arg);
|
|
||||||
static int acceptb(int card, unsigned long channel);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
/*
|
|
||||||
* Translate command codes to strings
|
|
||||||
*/
|
|
||||||
static char *commands[] = { "ISDN_CMD_IOCTL",
|
|
||||||
"ISDN_CMD_DIAL",
|
|
||||||
"ISDN_CMD_ACCEPTB",
|
|
||||||
"ISDN_CMD_ACCEPTB",
|
|
||||||
"ISDN_CMD_HANGUP",
|
|
||||||
"ISDN_CMD_CLREAZ",
|
|
||||||
"ISDN_CMD_SETEAZ",
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
"ISDN_CMD_SETL2",
|
|
||||||
NULL,
|
|
||||||
"ISDN_CMD_SETL3",
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL, };
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Translates ISDN4Linux protocol codes to strings for debug messages
|
|
||||||
*/
|
|
||||||
static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" };
|
|
||||||
static char *l2protos[] = { "ISDN_PROTO_L2_X75I",
|
|
||||||
"ISDN_PROTO_L2_X75UI",
|
|
||||||
"ISDN_PROTO_L2_X75BUI",
|
|
||||||
"ISDN_PROTO_L2_HDLC",
|
|
||||||
"ISDN_PROTO_L2_TRANS" };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int get_card_from_id(int driver)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < cinst; i++) {
|
|
||||||
if (sc_adapter[i]->driverId == driver)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* command
|
|
||||||
*/
|
|
||||||
|
|
||||||
int command(isdn_ctrl *cmd)
|
|
||||||
{
|
|
||||||
int card;
|
|
||||||
|
|
||||||
card = get_card_from_id(cmd->driver);
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dispatch the command
|
|
||||||
*/
|
|
||||||
switch (cmd->command) {
|
|
||||||
case ISDN_CMD_IOCTL:
|
|
||||||
{
|
|
||||||
unsigned long cmdptr;
|
|
||||||
scs_ioctl ioc;
|
|
||||||
|
|
||||||
memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long));
|
|
||||||
if (copy_from_user(&ioc, (scs_ioctl __user *)cmdptr,
|
|
||||||
sizeof(scs_ioctl))) {
|
|
||||||
pr_debug("%s: Failed to verify user space 0x%lx\n",
|
|
||||||
sc_adapter[card]->devicename, cmdptr);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
return sc_ioctl(card, &ioc);
|
|
||||||
}
|
|
||||||
case ISDN_CMD_DIAL:
|
|
||||||
return dial(card, cmd->arg, cmd->parm.setup);
|
|
||||||
case ISDN_CMD_HANGUP:
|
|
||||||
return hangup(card, cmd->arg);
|
|
||||||
case ISDN_CMD_ACCEPTD:
|
|
||||||
return answer(card, cmd->arg);
|
|
||||||
case ISDN_CMD_ACCEPTB:
|
|
||||||
return acceptb(card, cmd->arg);
|
|
||||||
case ISDN_CMD_CLREAZ:
|
|
||||||
return clreaz(card, cmd->arg);
|
|
||||||
case ISDN_CMD_SETEAZ:
|
|
||||||
return seteaz(card, cmd->arg, cmd->parm.num);
|
|
||||||
case ISDN_CMD_SETL2:
|
|
||||||
return setl2(card, cmd->arg);
|
|
||||||
case ISDN_CMD_SETL3:
|
|
||||||
return setl3(card, cmd->arg);
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* start the onboard firmware
|
|
||||||
*/
|
|
||||||
int startproc(int card)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* send start msg
|
|
||||||
*/
|
|
||||||
status = sendmessage(card, CMPID, cmReqType2,
|
|
||||||
cmReqClass0,
|
|
||||||
cmReqStartProc,
|
|
||||||
0, 0, NULL);
|
|
||||||
pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dials the number passed in
|
|
||||||
*/
|
|
||||||
static int dial(int card, unsigned long channel, setup_parm setup)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
char Phone[48];
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*extract ISDN number to dial from eaz/msn string*/
|
|
||||||
strcpy(Phone, setup.phone);
|
|
||||||
|
|
||||||
/*send the connection message*/
|
|
||||||
status = sendmessage(card, CEPID, ceReqTypePhy,
|
|
||||||
ceReqClass1,
|
|
||||||
ceReqPhyConnect,
|
|
||||||
(unsigned char)channel + 1,
|
|
||||||
strlen(Phone),
|
|
||||||
(unsigned int *)Phone);
|
|
||||||
|
|
||||||
pr_debug("%s: Dialing %s on channel %lu\n",
|
|
||||||
sc_adapter[card]->devicename, Phone, channel + 1);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Answer an incoming call
|
|
||||||
*/
|
|
||||||
static int answer(int card, unsigned long channel)
|
|
||||||
{
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setup_buffers(card, channel + 1)) {
|
|
||||||
hangup(card, channel + 1);
|
|
||||||
return -ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
|
|
||||||
pr_debug("%s: Answered incoming call on channel %lu\n",
|
|
||||||
sc_adapter[card]->devicename, channel + 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hangup up the call on specified channel
|
|
||||||
*/
|
|
||||||
static int hangup(int card, unsigned long channel)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = sendmessage(card, CEPID, ceReqTypePhy,
|
|
||||||
ceReqClass1,
|
|
||||||
ceReqPhyDisconnect,
|
|
||||||
(unsigned char)channel + 1,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
pr_debug("%s: Sent HANGUP message to channel %lu\n",
|
|
||||||
sc_adapter[card]->devicename, channel + 1);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the layer 2 protocol (X.25, HDLC, Raw)
|
|
||||||
*/
|
|
||||||
static int setl2(int card, unsigned long arg)
|
|
||||||
{
|
|
||||||
int status = 0;
|
|
||||||
int protocol, channel;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
protocol = arg >> 8;
|
|
||||||
channel = arg & 0xff;
|
|
||||||
sc_adapter[card]->channel[channel].l2_proto = protocol;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check that the adapter is also set to the correct protocol
|
|
||||||
*/
|
|
||||||
pr_debug("%s: Sending GetFrameFormat for channel %d\n",
|
|
||||||
sc_adapter[card]->devicename, channel + 1);
|
|
||||||
status = sendmessage(card, CEPID, ceReqTypeCall,
|
|
||||||
ceReqClass0,
|
|
||||||
ceReqCallGetFrameFormat,
|
|
||||||
(unsigned char)channel + 1,
|
|
||||||
1,
|
|
||||||
(unsigned int *)protocol);
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the layer 3 protocol
|
|
||||||
*/
|
|
||||||
static int setl3(int card, unsigned long channel)
|
|
||||||
{
|
|
||||||
int protocol = channel >> 8;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_adapter[card]->channel[channel].l3_proto = protocol;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acceptb(int card, unsigned long channel)
|
|
||||||
{
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setup_buffers(card, channel + 1))
|
|
||||||
{
|
|
||||||
hangup(card, channel + 1);
|
|
||||||
return -ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: B-Channel connection accepted on channel %lu\n",
|
|
||||||
sc_adapter[card]->devicename, channel + 1);
|
|
||||||
indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int clreaz(int card, unsigned long arg)
|
|
||||||
{
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(sc_adapter[card]->channel[arg].eazlist, "");
|
|
||||||
sc_adapter[card]->channel[arg].eazclear = 1;
|
|
||||||
pr_debug("%s: EAZ List cleared for channel %lu\n",
|
|
||||||
sc_adapter[card]->devicename, arg + 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int seteaz(int card, unsigned long arg, char *num)
|
|
||||||
{
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(sc_adapter[card]->channel[arg].eazlist, num);
|
|
||||||
sc_adapter[card]->channel[arg].eazclear = 0;
|
|
||||||
pr_debug("%s: EAZ list for channel %lu set to: %s\n",
|
|
||||||
sc_adapter[card]->devicename, arg + 1,
|
|
||||||
sc_adapter[card]->channel[arg].eazlist);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int reset(int card)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
indicate_status(card, ISDN_STAT_STOP, 0, NULL);
|
|
||||||
|
|
||||||
if (sc_adapter[card]->EngineUp) {
|
|
||||||
del_timer(&sc_adapter[card]->stat_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_adapter[card]->EngineUp = 0;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
init_timer(&sc_adapter[card]->reset_timer);
|
|
||||||
sc_adapter[card]->reset_timer.function = sc_check_reset;
|
|
||||||
sc_adapter[card]->reset_timer.data = card;
|
|
||||||
sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
|
|
||||||
add_timer(&sc_adapter[card]->reset_timer);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
|
|
||||||
outb(0x1, sc_adapter[card]->ioport[SFT_RESET]);
|
|
||||||
|
|
||||||
pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flushreadfifo(int card)
|
|
||||||
{
|
|
||||||
while (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
|
|
||||||
inb(sc_adapter[card]->ioport[FIFO_READ]);
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
/* $Id: event.c,v 1.4.8.1 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "message.h"
|
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static char *events[] = { "ISDN_STAT_STAVAIL",
|
|
||||||
"ISDN_STAT_ICALL",
|
|
||||||
"ISDN_STAT_RUN",
|
|
||||||
"ISDN_STAT_STOP",
|
|
||||||
"ISDN_STAT_DCONN",
|
|
||||||
"ISDN_STAT_BCONN",
|
|
||||||
"ISDN_STAT_DHUP",
|
|
||||||
"ISDN_STAT_BHUP",
|
|
||||||
"ISDN_STAT_CINF",
|
|
||||||
"ISDN_STAT_LOAD",
|
|
||||||
"ISDN_STAT_UNLOAD",
|
|
||||||
"ISDN_STAT_BSENT",
|
|
||||||
"ISDN_STAT_NODCH",
|
|
||||||
"ISDN_STAT_ADDCH",
|
|
||||||
"ISDN_STAT_CAUSE" };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int indicate_status(int card, int event, ulong Channel, char *Data)
|
|
||||||
{
|
|
||||||
isdn_ctrl cmd;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
pr_debug("%s: Indicating event %s on Channel %d\n",
|
|
||||||
sc_adapter[card]->devicename, events[event - 256], Channel);
|
|
||||||
#endif
|
|
||||||
if (Data != NULL) {
|
|
||||||
pr_debug("%s: Event data: %s\n", sc_adapter[card]->devicename,
|
|
||||||
Data);
|
|
||||||
switch (event) {
|
|
||||||
case ISDN_STAT_BSENT:
|
|
||||||
memcpy(&cmd.parm.length, Data, sizeof(cmd.parm.length));
|
|
||||||
break;
|
|
||||||
case ISDN_STAT_ICALL:
|
|
||||||
memcpy(&cmd.parm.setup, Data, sizeof(cmd.parm.setup));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
strlcpy(cmd.parm.num, Data, sizeof(cmd.parm.num));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.command = event;
|
|
||||||
cmd.driver = sc_adapter[card]->driverId;
|
|
||||||
cmd.arg = Channel;
|
|
||||||
return sc_adapter[card]->card->statcallb(&cmd);
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hardware specific macros, defines and structures
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HARDWARE_H
|
|
||||||
#define HARDWARE_H
|
|
||||||
|
|
||||||
#include <asm/param.h> /* For HZ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* General hardware parameters common to all ISA adapters
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MAX_CARDS 4 /* The maximum number of cards to
|
|
||||||
control or probe for. */
|
|
||||||
|
|
||||||
#define SIGNATURE 0x87654321 /* Board reset signature */
|
|
||||||
#define SIG_OFFSET 0x1004 /* Where to find signature in shared RAM */
|
|
||||||
#define TRACE_OFFSET 0x1008 /* Trace enable word offset in shared RAM */
|
|
||||||
#define BUFFER_OFFSET 0x1800 /* Beginning of buffers */
|
|
||||||
|
|
||||||
/* I/O Port parameters */
|
|
||||||
#define IOBASE_MIN 0x180 /* Lowest I/O port address */
|
|
||||||
#define IOBASE_MAX 0x3C0 /* Highest I/O port address */
|
|
||||||
#define IOBASE_OFFSET 0x20 /* Inter-board I/O port gap used during
|
|
||||||
probing */
|
|
||||||
#define FIFORD_OFFSET 0x0
|
|
||||||
#define FIFOWR_OFFSET 0x400
|
|
||||||
#define FIFOSTAT_OFFSET 0x1000
|
|
||||||
#define RESET_OFFSET 0x2800
|
|
||||||
#define PG0_OFFSET 0x3000 /* Offset from I/O Base for Page 0 register */
|
|
||||||
#define PG1_OFFSET 0x3400 /* Offset from I/O Base for Page 1 register */
|
|
||||||
#define PG2_OFFSET 0x3800 /* Offset from I/O Base for Page 2 register */
|
|
||||||
#define PG3_OFFSET 0x3C00 /* Offset from I/O Base for Page 3 register */
|
|
||||||
|
|
||||||
#define FIFO_READ 0 /* FIFO Read register */
|
|
||||||
#define FIFO_WRITE 1 /* FIFO Write rgister */
|
|
||||||
#define LO_ADDR_PTR 2 /* Extended RAM Low Addr Pointer */
|
|
||||||
#define HI_ADDR_PTR 3 /* Extended RAM High Addr Pointer */
|
|
||||||
#define NOT_USED_1 4
|
|
||||||
#define FIFO_STATUS 5 /* FIFO Status Register */
|
|
||||||
#define NOT_USED_2 6
|
|
||||||
#define MEM_OFFSET 7
|
|
||||||
#define SFT_RESET 10 /* Reset Register */
|
|
||||||
#define EXP_BASE 11 /* Shared RAM Base address */
|
|
||||||
#define EXP_PAGE0 12 /* Shared RAM Page0 register */
|
|
||||||
#define EXP_PAGE1 13 /* Shared RAM Page1 register */
|
|
||||||
#define EXP_PAGE2 14 /* Shared RAM Page2 register */
|
|
||||||
#define EXP_PAGE3 15 /* Shared RAM Page3 register */
|
|
||||||
#define IRQ_SELECT 16 /* IRQ selection register */
|
|
||||||
#define MAX_IO_REGS 17 /* Total number of I/O ports */
|
|
||||||
|
|
||||||
/* FIFO register values */
|
|
||||||
#define RF_HAS_DATA 0x01 /* fifo has data */
|
|
||||||
#define RF_QUART_FULL 0x02 /* fifo quarter full */
|
|
||||||
#define RF_HALF_FULL 0x04 /* fifo half full */
|
|
||||||
#define RF_NOT_FULL 0x08 /* fifo not full */
|
|
||||||
#define WF_HAS_DATA 0x10 /* fifo has data */
|
|
||||||
#define WF_QUART_FULL 0x20 /* fifo quarter full */
|
|
||||||
#define WF_HALF_FULL 0x40 /* fifo half full */
|
|
||||||
#define WF_NOT_FULL 0x80 /* fifo not full */
|
|
||||||
|
|
||||||
/* Shared RAM parameters */
|
|
||||||
#define SRAM_MIN 0xC0000 /* Lowest host shared RAM address */
|
|
||||||
#define SRAM_MAX 0xEFFFF /* Highest host shared RAM address */
|
|
||||||
#define SRAM_PAGESIZE 0x4000 /* Size of one RAM page (16K) */
|
|
||||||
|
|
||||||
/* Shared RAM buffer parameters */
|
|
||||||
#define BUFFER_SIZE 0x800 /* The size of a buffer in bytes */
|
|
||||||
#define BUFFER_BASE BUFFER_OFFSET /* Offset from start of shared RAM
|
|
||||||
where buffer start */
|
|
||||||
#define BUFFERS_MAX 16 /* Maximum number of send/receive
|
|
||||||
buffers per channel */
|
|
||||||
#define HDLC_PROTO 0x01 /* Frame Format for Layer 2 */
|
|
||||||
|
|
||||||
#define BRI_BOARD 0
|
|
||||||
#define POTS_BOARD 1
|
|
||||||
#define PRI_BOARD 2
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Specific hardware parameters for the DataCommute/BRI
|
|
||||||
*/
|
|
||||||
#define BRI_CHANNELS 2 /* Number of B channels */
|
|
||||||
#define BRI_BASEPG_VAL 0x98
|
|
||||||
#define BRI_MAGIC 0x60000 /* Magic Number */
|
|
||||||
#define BRI_MEMSIZE 0x10000 /* Amount of RAM (64K) */
|
|
||||||
#define BRI_PARTNO "72-029"
|
|
||||||
#define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS;
|
|
||||||
/*
|
|
||||||
* Specific hardware parameters for the DataCommute/PRI
|
|
||||||
*/
|
|
||||||
#define PRI_CHANNELS 23 /* Number of B channels */
|
|
||||||
#define PRI_BASEPG_VAL 0x88
|
|
||||||
#define PRI_MAGIC 0x20000 /* Magic Number */
|
|
||||||
#define PRI_MEMSIZE 0x100000 /* Amount of RAM (1M) */
|
|
||||||
#define PRI_PARTNO "72-030"
|
|
||||||
#define PRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some handy macros
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Determine if a channel number is valid for the adapter */
|
|
||||||
#define IS_VALID_CHANNEL(y, x) ((x > 0) && (x <= sc_adapter[y]->channels))
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <asm/io.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/ioport.h>
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/wait.h>
|
|
||||||
#include <linux/isdnif.h>
|
|
@ -1,549 +0,0 @@
|
|||||||
/*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include "includes.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("ISDN4Linux: Driver for Spellcaster card");
|
|
||||||
MODULE_AUTHOR("Spellcaster Telecommunications Inc.");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
board *sc_adapter[MAX_CARDS];
|
|
||||||
int cinst;
|
|
||||||
|
|
||||||
static char devname[] = "scX";
|
|
||||||
static const char version[] = "2.0b1";
|
|
||||||
|
|
||||||
static const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
|
|
||||||
|
|
||||||
/* insmod set parameters */
|
|
||||||
static unsigned int io[] = {0, 0, 0, 0};
|
|
||||||
static unsigned char irq[] = {0, 0, 0, 0};
|
|
||||||
static unsigned long ram[] = {0, 0, 0, 0};
|
|
||||||
static bool do_reset;
|
|
||||||
|
|
||||||
module_param_array(io, int, NULL, 0);
|
|
||||||
module_param_array(irq, byte, NULL, 0);
|
|
||||||
module_param_array(ram, long, NULL, 0);
|
|
||||||
module_param(do_reset, bool, 0);
|
|
||||||
|
|
||||||
static int identify_board(unsigned long, unsigned int);
|
|
||||||
|
|
||||||
static int __init sc_init(void)
|
|
||||||
{
|
|
||||||
int b = -1;
|
|
||||||
int i, j;
|
|
||||||
int status = -ENODEV;
|
|
||||||
|
|
||||||
unsigned long memsize = 0;
|
|
||||||
unsigned long features = 0;
|
|
||||||
isdn_if *interface;
|
|
||||||
unsigned char channels;
|
|
||||||
unsigned char pgport;
|
|
||||||
unsigned long magic;
|
|
||||||
int model;
|
|
||||||
int last_base = IOBASE_MIN;
|
|
||||||
int probe_exhasted = 0;
|
|
||||||
|
|
||||||
#ifdef MODULE
|
|
||||||
pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s Loaded\n", version);
|
|
||||||
#else
|
|
||||||
pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s\n", version);
|
|
||||||
#endif
|
|
||||||
pr_info("Copyright (C) 1996 SpellCaster Telecommunications Inc.\n");
|
|
||||||
|
|
||||||
while (b++ < MAX_CARDS - 1) {
|
|
||||||
pr_debug("Probing for adapter #%d\n", b);
|
|
||||||
/*
|
|
||||||
* Initialize reusable variables
|
|
||||||
*/
|
|
||||||
model = -1;
|
|
||||||
magic = 0;
|
|
||||||
channels = 0;
|
|
||||||
pgport = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if we should probe for IO base
|
|
||||||
*/
|
|
||||||
pr_debug("I/O Base for board %d is 0x%x, %s probe\n", b, io[b],
|
|
||||||
io[b] == 0 ? "will" : "won't");
|
|
||||||
if (io[b]) {
|
|
||||||
/*
|
|
||||||
* No, I/O Base has been provided
|
|
||||||
*/
|
|
||||||
for (i = 0; i < MAX_IO_REGS - 1; i++) {
|
|
||||||
if (!request_region(io[b] + i * 0x400, 1, "sc test")) {
|
|
||||||
pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400);
|
|
||||||
io[b] = 0;
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
release_region(io[b] + i * 0x400, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Confirm the I/O Address with a test
|
|
||||||
*/
|
|
||||||
if (io[b] == 0) {
|
|
||||||
pr_debug("I/O Address invalid.\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
outb(0x18, io[b] + 0x400 * EXP_PAGE0);
|
|
||||||
if (inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) {
|
|
||||||
pr_debug("I/O Base 0x%x fails test\n",
|
|
||||||
io[b] + 0x400 * EXP_PAGE0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Yes, probe for I/O Base
|
|
||||||
*/
|
|
||||||
if (probe_exhasted) {
|
|
||||||
pr_debug("All probe addresses exhausted, skipping\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pr_debug("Probing for I/O...\n");
|
|
||||||
for (i = last_base; i <= IOBASE_MAX; i += IOBASE_OFFSET) {
|
|
||||||
int found_io = 1;
|
|
||||||
if (i == IOBASE_MAX) {
|
|
||||||
probe_exhasted = 1; /* No more addresses to probe */
|
|
||||||
pr_debug("End of Probes\n");
|
|
||||||
}
|
|
||||||
last_base = i + IOBASE_OFFSET;
|
|
||||||
pr_debug(" checking 0x%x...", i);
|
|
||||||
for (j = 0; j < MAX_IO_REGS - 1; j++) {
|
|
||||||
if (!request_region(i + j * 0x400, 1, "sc test")) {
|
|
||||||
pr_debug("Failed\n");
|
|
||||||
found_io = 0;
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
release_region(i + j * 0x400, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found_io) {
|
|
||||||
io[b] = i;
|
|
||||||
outb(0x18, io[b] + 0x400 * EXP_PAGE0);
|
|
||||||
if (inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) {
|
|
||||||
pr_debug("Failed by test\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pr_debug("Passed\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (probe_exhasted) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if we should probe for shared RAM
|
|
||||||
*/
|
|
||||||
if (do_reset) {
|
|
||||||
pr_debug("Doing a SAFE probe reset\n");
|
|
||||||
outb(0xFF, io[b] + RESET_OFFSET);
|
|
||||||
msleep_interruptible(10000);
|
|
||||||
}
|
|
||||||
pr_debug("RAM Base for board %d is 0x%lx, %s probe\n", b,
|
|
||||||
ram[b], ram[b] == 0 ? "will" : "won't");
|
|
||||||
|
|
||||||
if (ram[b]) {
|
|
||||||
/*
|
|
||||||
* No, the RAM base has been provided
|
|
||||||
* Just look for a signature and ID the
|
|
||||||
* board model
|
|
||||||
*/
|
|
||||||
if (request_region(ram[b], SRAM_PAGESIZE, "sc test")) {
|
|
||||||
pr_debug("request_region for RAM base 0x%lx succeeded\n", ram[b]);
|
|
||||||
model = identify_board(ram[b], io[b]);
|
|
||||||
release_region(ram[b], SRAM_PAGESIZE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Yes, probe for free RAM and look for
|
|
||||||
* a signature and id the board model
|
|
||||||
*/
|
|
||||||
for (i = SRAM_MIN; i < SRAM_MAX; i += SRAM_PAGESIZE) {
|
|
||||||
pr_debug("Checking RAM address 0x%x...\n", i);
|
|
||||||
if (request_region(i, SRAM_PAGESIZE, "sc test")) {
|
|
||||||
pr_debug(" request_region succeeded\n");
|
|
||||||
model = identify_board(i, io[b]);
|
|
||||||
release_region(i, SRAM_PAGESIZE);
|
|
||||||
if (model >= 0) {
|
|
||||||
pr_debug(" Identified a %s\n",
|
|
||||||
boardname[model]);
|
|
||||||
ram[b] = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pr_debug(" Unidentified or inaccessible\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pr_debug(" request failed\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* See if we found free RAM and the board model
|
|
||||||
*/
|
|
||||||
if (!ram[b] || model < 0) {
|
|
||||||
/*
|
|
||||||
* Nope, there was no place in RAM for the
|
|
||||||
* board, or it couldn't be identified
|
|
||||||
*/
|
|
||||||
pr_debug("Failed to find an adapter at 0x%lx\n", ram[b]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the board's magic number, memory size and page register
|
|
||||||
*/
|
|
||||||
switch (model) {
|
|
||||||
case PRI_BOARD:
|
|
||||||
channels = 23;
|
|
||||||
magic = 0x20000;
|
|
||||||
memsize = 0x100000;
|
|
||||||
features = PRI_FEATURES;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BRI_BOARD:
|
|
||||||
case POTS_BOARD:
|
|
||||||
channels = 2;
|
|
||||||
magic = 0x60000;
|
|
||||||
memsize = 0x10000;
|
|
||||||
features = BRI_FEATURES;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (ram[b] >> 12 & 0x0F) {
|
|
||||||
case 0x0:
|
|
||||||
pr_debug("RAM Page register set to EXP_PAGE0\n");
|
|
||||||
pgport = EXP_PAGE0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x4:
|
|
||||||
pr_debug("RAM Page register set to EXP_PAGE1\n");
|
|
||||||
pgport = EXP_PAGE1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x8:
|
|
||||||
pr_debug("RAM Page register set to EXP_PAGE2\n");
|
|
||||||
pgport = EXP_PAGE2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xC:
|
|
||||||
pr_debug("RAM Page register set to EXP_PAGE3\n");
|
|
||||||
pgport = EXP_PAGE3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
pr_debug("RAM base address doesn't fall on 16K boundary\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("current IRQ: %d b: %d\n", irq[b], b);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure we got an IRQ
|
|
||||||
*/
|
|
||||||
if (!irq[b]) {
|
|
||||||
/*
|
|
||||||
* No interrupt could be used
|
|
||||||
*/
|
|
||||||
pr_debug("Failed to acquire an IRQ line\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Horray! We found a board, Make sure we can register
|
|
||||||
* it with ISDN4Linux
|
|
||||||
*/
|
|
||||||
interface = kzalloc(sizeof(isdn_if), GFP_KERNEL);
|
|
||||||
if (interface == NULL) {
|
|
||||||
/*
|
|
||||||
* Oops, can't malloc isdn_if
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface->owner = THIS_MODULE;
|
|
||||||
interface->hl_hdrlen = 0;
|
|
||||||
interface->channels = channels;
|
|
||||||
interface->maxbufsize = BUFFER_SIZE;
|
|
||||||
interface->features = features;
|
|
||||||
interface->writebuf_skb = sndpkt;
|
|
||||||
interface->writecmd = NULL;
|
|
||||||
interface->command = command;
|
|
||||||
strcpy(interface->id, devname);
|
|
||||||
interface->id[2] = '0' + cinst;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate the board structure
|
|
||||||
*/
|
|
||||||
sc_adapter[cinst] = kzalloc(sizeof(board), GFP_KERNEL);
|
|
||||||
if (sc_adapter[cinst] == NULL) {
|
|
||||||
/*
|
|
||||||
* Oops, can't alloc memory for the board
|
|
||||||
*/
|
|
||||||
kfree(interface);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
spin_lock_init(&sc_adapter[cinst]->lock);
|
|
||||||
|
|
||||||
if (!register_isdn(interface)) {
|
|
||||||
/*
|
|
||||||
* Oops, couldn't register for some reason
|
|
||||||
*/
|
|
||||||
kfree(interface);
|
|
||||||
kfree(sc_adapter[cinst]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_adapter[cinst]->card = interface;
|
|
||||||
sc_adapter[cinst]->driverId = interface->channels;
|
|
||||||
strcpy(sc_adapter[cinst]->devicename, interface->id);
|
|
||||||
sc_adapter[cinst]->nChannels = channels;
|
|
||||||
sc_adapter[cinst]->ramsize = memsize;
|
|
||||||
sc_adapter[cinst]->shmem_magic = magic;
|
|
||||||
sc_adapter[cinst]->shmem_pgport = pgport;
|
|
||||||
sc_adapter[cinst]->StartOnReset = 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate channels status structures
|
|
||||||
*/
|
|
||||||
sc_adapter[cinst]->channel = kzalloc(sizeof(bchan) * channels, GFP_KERNEL);
|
|
||||||
if (sc_adapter[cinst]->channel == NULL) {
|
|
||||||
/*
|
|
||||||
* Oops, can't alloc memory for the channels
|
|
||||||
*/
|
|
||||||
indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */
|
|
||||||
kfree(interface);
|
|
||||||
kfree(sc_adapter[cinst]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lock down the hardware resources
|
|
||||||
*/
|
|
||||||
sc_adapter[cinst]->interrupt = irq[b];
|
|
||||||
if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler,
|
|
||||||
0, interface->id,
|
|
||||||
(void *)(unsigned long) cinst)) {
|
|
||||||
kfree(sc_adapter[cinst]->channel);
|
|
||||||
indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */
|
|
||||||
kfree(interface);
|
|
||||||
kfree(sc_adapter[cinst]);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
sc_adapter[cinst]->iobase = io[b];
|
|
||||||
for (i = 0; i < MAX_IO_REGS - 1; i++) {
|
|
||||||
sc_adapter[cinst]->ioport[i] = io[b] + i * 0x400;
|
|
||||||
request_region(sc_adapter[cinst]->ioport[i], 1,
|
|
||||||
interface->id);
|
|
||||||
pr_debug("Requesting I/O Port %#x\n",
|
|
||||||
sc_adapter[cinst]->ioport[i]);
|
|
||||||
}
|
|
||||||
sc_adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2;
|
|
||||||
request_region(sc_adapter[cinst]->ioport[IRQ_SELECT], 1,
|
|
||||||
interface->id);
|
|
||||||
pr_debug("Requesting I/O Port %#x\n",
|
|
||||||
sc_adapter[cinst]->ioport[IRQ_SELECT]);
|
|
||||||
sc_adapter[cinst]->rambase = ram[b];
|
|
||||||
request_region(sc_adapter[cinst]->rambase, SRAM_PAGESIZE,
|
|
||||||
interface->id);
|
|
||||||
|
|
||||||
pr_info(" %s (%d) - %s %d channels IRQ %d, I/O Base 0x%x, RAM Base 0x%lx\n",
|
|
||||||
sc_adapter[cinst]->devicename,
|
|
||||||
sc_adapter[cinst]->driverId,
|
|
||||||
boardname[model], channels, irq[b], io[b], ram[b]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* reset the adapter to put things in motion
|
|
||||||
*/
|
|
||||||
reset(cinst);
|
|
||||||
|
|
||||||
cinst++;
|
|
||||||
status = 0;
|
|
||||||
}
|
|
||||||
if (status)
|
|
||||||
pr_info("Failed to find any adapters, driver unloaded\n");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit sc_exit(void)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
for (i = 0; i < cinst; i++) {
|
|
||||||
pr_debug("Cleaning up after adapter %d\n", i);
|
|
||||||
/*
|
|
||||||
* kill the timers
|
|
||||||
*/
|
|
||||||
del_timer_sync(&(sc_adapter[i]->reset_timer));
|
|
||||||
del_timer_sync(&(sc_adapter[i]->stat_timer));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tell I4L we're toast
|
|
||||||
*/
|
|
||||||
indicate_status(i, ISDN_STAT_STOP, 0, NULL);
|
|
||||||
indicate_status(i, ISDN_STAT_UNLOAD, 0, NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release shared RAM
|
|
||||||
*/
|
|
||||||
release_region(sc_adapter[i]->rambase, SRAM_PAGESIZE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release the IRQ
|
|
||||||
*/
|
|
||||||
free_irq(sc_adapter[i]->interrupt, NULL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset for a clean start
|
|
||||||
*/
|
|
||||||
outb(0xFF, sc_adapter[i]->ioport[SFT_RESET]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release the I/O Port regions
|
|
||||||
*/
|
|
||||||
for (j = 0; j < MAX_IO_REGS - 1; j++) {
|
|
||||||
release_region(sc_adapter[i]->ioport[j], 1);
|
|
||||||
pr_debug("Releasing I/O Port %#x\n",
|
|
||||||
sc_adapter[i]->ioport[j]);
|
|
||||||
}
|
|
||||||
release_region(sc_adapter[i]->ioport[IRQ_SELECT], 1);
|
|
||||||
pr_debug("Releasing I/O Port %#x\n",
|
|
||||||
sc_adapter[i]->ioport[IRQ_SELECT]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release any memory we alloced
|
|
||||||
*/
|
|
||||||
kfree(sc_adapter[i]->channel);
|
|
||||||
kfree(sc_adapter[i]->card);
|
|
||||||
kfree(sc_adapter[i]);
|
|
||||||
}
|
|
||||||
pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int identify_board(unsigned long rambase, unsigned int iobase)
|
|
||||||
{
|
|
||||||
unsigned int pgport;
|
|
||||||
unsigned long sig;
|
|
||||||
DualPortMemory *dpm;
|
|
||||||
RspMessage rcvmsg;
|
|
||||||
ReqMessage sndmsg;
|
|
||||||
HWConfig_pl hwci;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
pr_debug("Attempting to identify adapter @ 0x%lx io 0x%x\n",
|
|
||||||
rambase, iobase);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable the base pointer
|
|
||||||
*/
|
|
||||||
outb(rambase >> 12, iobase + 0x2c00);
|
|
||||||
|
|
||||||
switch (rambase >> 12 & 0x0F) {
|
|
||||||
case 0x0:
|
|
||||||
pgport = iobase + PG0_OFFSET;
|
|
||||||
pr_debug("Page Register offset is 0x%x\n", PG0_OFFSET);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x4:
|
|
||||||
pgport = iobase + PG1_OFFSET;
|
|
||||||
pr_debug("Page Register offset is 0x%x\n", PG1_OFFSET);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x8:
|
|
||||||
pgport = iobase + PG2_OFFSET;
|
|
||||||
pr_debug("Page Register offset is 0x%x\n", PG2_OFFSET);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xC:
|
|
||||||
pgport = iobase + PG3_OFFSET;
|
|
||||||
pr_debug("Page Register offset is 0x%x\n", PG3_OFFSET);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_debug("Invalid rambase 0x%lx\n", rambase);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to identify a PRI card
|
|
||||||
*/
|
|
||||||
outb(PRI_BASEPG_VAL, pgport);
|
|
||||||
msleep_interruptible(1000);
|
|
||||||
sig = readl(rambase + SIG_OFFSET);
|
|
||||||
pr_debug("Looking for a signature, got 0x%lx\n", sig);
|
|
||||||
if (sig == SIGNATURE)
|
|
||||||
return PRI_BOARD;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to identify a PRI card
|
|
||||||
*/
|
|
||||||
outb(BRI_BASEPG_VAL, pgport);
|
|
||||||
msleep_interruptible(1000);
|
|
||||||
sig = readl(rambase + SIG_OFFSET);
|
|
||||||
pr_debug("Looking for a signature, got 0x%lx\n", sig);
|
|
||||||
if (sig == SIGNATURE)
|
|
||||||
return BRI_BOARD;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to spot a card
|
|
||||||
*/
|
|
||||||
sig = readl(rambase + SIG_OFFSET);
|
|
||||||
pr_debug("Looking for a signature, got 0x%lx\n", sig);
|
|
||||||
if (sig != SIGNATURE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
dpm = (DualPortMemory *) rambase;
|
|
||||||
|
|
||||||
memset(&sndmsg, 0, MSG_LEN);
|
|
||||||
sndmsg.msg_byte_cnt = 3;
|
|
||||||
sndmsg.type = cmReqType1;
|
|
||||||
sndmsg.class = cmReqClass0;
|
|
||||||
sndmsg.code = cmReqHWConfig;
|
|
||||||
memcpy_toio(&(dpm->req_queue[dpm->req_head++]), &sndmsg, MSG_LEN);
|
|
||||||
outb(0, iobase + 0x400);
|
|
||||||
pr_debug("Sent HWConfig message\n");
|
|
||||||
/*
|
|
||||||
* Wait for the response
|
|
||||||
*/
|
|
||||||
x = 0;
|
|
||||||
while ((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) {
|
|
||||||
schedule_timeout_interruptible(1);
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
if (x == 100) {
|
|
||||||
pr_debug("Timeout waiting for response\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy_fromio(&rcvmsg, &(dpm->rsp_queue[dpm->rsp_tail]), MSG_LEN);
|
|
||||||
pr_debug("Got HWConfig response, status = 0x%x\n", rcvmsg.rsp_status);
|
|
||||||
memcpy(&hwci, &(rcvmsg.msg_data.HWCresponse), sizeof(HWConfig_pl));
|
|
||||||
pr_debug("Hardware Config: Interface: %s, RAM Size: %ld, Serial: %s\n"
|
|
||||||
" Part: %s, Rev: %s\n",
|
|
||||||
hwci.st_u_sense ? "S/T" : "U", hwci.ram_size,
|
|
||||||
hwci.serial_no, hwci.part_no, hwci.rev_no);
|
|
||||||
|
|
||||||
if (!strncmp(PRI_PARTNO, hwci.part_no, 6))
|
|
||||||
return PRI_BOARD;
|
|
||||||
if (!strncmp(BRI_PARTNO, hwci.part_no, 6))
|
|
||||||
return BRI_BOARD;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(sc_init);
|
|
||||||
module_exit(sc_exit);
|
|
@ -1,247 +0,0 @@
|
|||||||
/* $Id: interrupt.c,v 1.4.8.3 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "message.h"
|
|
||||||
#include "card.h"
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
irqreturn_t interrupt_handler(int dummy, void *card_inst)
|
|
||||||
{
|
|
||||||
|
|
||||||
RspMessage rcvmsg;
|
|
||||||
int channel;
|
|
||||||
int card = (int)(unsigned long) card_inst;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: Entered Interrupt handler\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pull all of the waiting messages off the response queue
|
|
||||||
*/
|
|
||||||
while (!receivemessage(card, &rcvmsg)) {
|
|
||||||
/*
|
|
||||||
* Push the message to the adapter structure for
|
|
||||||
* send_and_receive to snoop
|
|
||||||
*/
|
|
||||||
if (sc_adapter[card]->want_async_messages)
|
|
||||||
memcpy(&(sc_adapter[card]->async_msg),
|
|
||||||
&rcvmsg, sizeof(RspMessage));
|
|
||||||
|
|
||||||
channel = (unsigned int) rcvmsg.phy_link_no;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Trap Invalid request messages
|
|
||||||
*/
|
|
||||||
if (IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) {
|
|
||||||
pr_debug("%s: Invalid request Message, rsp_status = %d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.rsp_status);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check for a linkRead message
|
|
||||||
*/
|
|
||||||
if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read))
|
|
||||||
{
|
|
||||||
pr_debug("%s: Received packet 0x%x bytes long at 0x%lx\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.msg_data.response.msg_len,
|
|
||||||
rcvmsg.msg_data.response.buff_offset);
|
|
||||||
rcvpkt(card, &rcvmsg);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle a write acknoledgement
|
|
||||||
*/
|
|
||||||
if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) {
|
|
||||||
pr_debug("%s: Packet Send ACK on channel %d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.phy_link_no);
|
|
||||||
sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].free_sendbufs++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle a connection message
|
|
||||||
*/
|
|
||||||
if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Connect))
|
|
||||||
{
|
|
||||||
unsigned int callid;
|
|
||||||
setup_parm setup;
|
|
||||||
pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.phy_link_no,
|
|
||||||
rcvmsg.rsp_status,
|
|
||||||
rcvmsg.msg_data.byte_array[2]);
|
|
||||||
|
|
||||||
memcpy(&callid, rcvmsg.msg_data.byte_array, sizeof(int));
|
|
||||||
if (callid >= 0x8000 && callid <= 0xFFFF)
|
|
||||||
{
|
|
||||||
pr_debug("%s: Got Dial-Out Rsp\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
indicate_status(card, ISDN_STAT_DCONN,
|
|
||||||
(unsigned long)rcvmsg.phy_link_no - 1, NULL);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (callid >= 0x0000 && callid <= 0x7FFF)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
|
|
||||||
pr_debug("%s: Got Incoming Call\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]),
|
|
||||||
sizeof(setup.phone));
|
|
||||||
if (len >= sizeof(setup.phone))
|
|
||||||
continue;
|
|
||||||
len = strlcpy(setup.eazmsn,
|
|
||||||
sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
|
|
||||||
sizeof(setup.eazmsn));
|
|
||||||
if (len >= sizeof(setup.eazmsn))
|
|
||||||
continue;
|
|
||||||
setup.si1 = 7;
|
|
||||||
setup.si2 = 0;
|
|
||||||
setup.plan = 0;
|
|
||||||
setup.screen = 0;
|
|
||||||
|
|
||||||
indicate_status(card, ISDN_STAT_ICALL, (unsigned long)rcvmsg.phy_link_no - 1, (char *)&setup);
|
|
||||||
indicate_status(card, ISDN_STAT_DCONN, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle a disconnection message
|
|
||||||
*/
|
|
||||||
if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect))
|
|
||||||
{
|
|
||||||
pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.phy_link_no,
|
|
||||||
rcvmsg.rsp_status,
|
|
||||||
rcvmsg.msg_data.byte_array[2]);
|
|
||||||
|
|
||||||
indicate_status(card, ISDN_STAT_BHUP, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
|
|
||||||
indicate_status(card, ISDN_STAT_DHUP, (unsigned long)rcvmsg.phy_link_no - 1, NULL);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle a startProc engine up message
|
|
||||||
*/
|
|
||||||
if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) {
|
|
||||||
pr_debug("%s: Received EngineUp message\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
sc_adapter[card]->EngineUp = 1;
|
|
||||||
sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, 1, 0, NULL);
|
|
||||||
sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, 2, 0, NULL);
|
|
||||||
init_timer(&sc_adapter[card]->stat_timer);
|
|
||||||
sc_adapter[card]->stat_timer.function = check_phystat;
|
|
||||||
sc_adapter[card]->stat_timer.data = card;
|
|
||||||
sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME;
|
|
||||||
add_timer(&sc_adapter[card]->stat_timer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start proc response
|
|
||||||
*/
|
|
||||||
if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) {
|
|
||||||
pr_debug("%s: StartProc Response Status %d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.rsp_status);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle a GetMyNumber Rsp
|
|
||||||
*/
|
|
||||||
if (IS_CE_MESSAGE(rcvmsg, Call, 0, GetMyNumber)) {
|
|
||||||
strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn,
|
|
||||||
rcvmsg.msg_data.byte_array,
|
|
||||||
sizeof(rcvmsg.msg_data.byte_array));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PhyStatus response
|
|
||||||
*/
|
|
||||||
if (IS_CE_MESSAGE(rcvmsg, Phy, 2, Status)) {
|
|
||||||
unsigned int b1stat, b2stat;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Covert the message data to the adapter->phystat code
|
|
||||||
*/
|
|
||||||
b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0];
|
|
||||||
b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1];
|
|
||||||
|
|
||||||
sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */
|
|
||||||
pr_debug("%s: PhyStat is 0x%2x\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
sc_adapter[card]->nphystat);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle a GetFramFormat
|
|
||||||
*/
|
|
||||||
if (IS_CE_MESSAGE(rcvmsg, Call, 0, GetFrameFormat)) {
|
|
||||||
if (rcvmsg.msg_data.byte_array[0] != HDLC_PROTO) {
|
|
||||||
unsigned int proto = HDLC_PROTO;
|
|
||||||
/*
|
|
||||||
* Set board format to HDLC if it wasn't already
|
|
||||||
*/
|
|
||||||
pr_debug("%s: current frame format: 0x%x, will change to HDLC\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.msg_data.byte_array[0]);
|
|
||||||
sendmessage(card, CEPID, ceReqTypeCall,
|
|
||||||
ceReqClass0,
|
|
||||||
ceReqCallSetFrameFormat,
|
|
||||||
(unsigned char)channel + 1,
|
|
||||||
1, &proto);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hmm...
|
|
||||||
*/
|
|
||||||
pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg.type, rcvmsg.class, rcvmsg.code,
|
|
||||||
rcvmsg.phy_link_no);
|
|
||||||
|
|
||||||
} /* while */
|
|
||||||
|
|
||||||
pr_debug("%s: Exiting Interrupt Handler\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
@ -1,582 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "message.h"
|
|
||||||
#include "card.h"
|
|
||||||
#include "scioc.h"
|
|
||||||
|
|
||||||
static int GetStatus(int card, boardInfo *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process private IOCTL messages (typically from scctrl)
|
|
||||||
*/
|
|
||||||
int sc_ioctl(int card, scs_ioctl *data)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
RspMessage *rcvmsg;
|
|
||||||
char *spid;
|
|
||||||
char *dn;
|
|
||||||
char switchtype;
|
|
||||||
char speed;
|
|
||||||
|
|
||||||
rcvmsg = kmalloc(sizeof(RspMessage), GFP_KERNEL);
|
|
||||||
if (!rcvmsg)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
switch (data->command) {
|
|
||||||
case SCIOCRESET: /* Perform a hard reset of the adapter */
|
|
||||||
{
|
|
||||||
pr_debug("%s: SCIOCRESET: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
sc_adapter[card]->StartOnReset = 0;
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return reset(card);
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCLOAD:
|
|
||||||
{
|
|
||||||
char *srec;
|
|
||||||
|
|
||||||
srec = kmalloc(SCIOC_SRECSIZE, GFP_KERNEL);
|
|
||||||
if (!srec) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
pr_debug("%s: SCIOLOAD: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
if (sc_adapter[card]->EngineUp) {
|
|
||||||
pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
kfree(srec);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the SRec from user space
|
|
||||||
*/
|
|
||||||
if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
kfree(srec);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
|
|
||||||
0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
kfree(srec);
|
|
||||||
|
|
||||||
if (status) {
|
|
||||||
pr_debug("%s: SCIOCLOAD: command failed, status = %d\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pr_debug("%s: SCIOCLOAD: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCSTART:
|
|
||||||
{
|
|
||||||
kfree(rcvmsg);
|
|
||||||
pr_debug("%s: SCIOSTART: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
if (sc_adapter[card]->EngineUp) {
|
|
||||||
pr_debug("%s: SCIOCSTART: command failed, engine already running.\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_adapter[card]->StartOnReset = 1;
|
|
||||||
startproc(card);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCSETSWITCH:
|
|
||||||
{
|
|
||||||
pr_debug("%s: SCIOSETSWITCH: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the switch type from user space
|
|
||||||
*/
|
|
||||||
if (copy_from_user(&switchtype, data->dataptr, sizeof(char))) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
switchtype);
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType,
|
|
||||||
0, sizeof(char), &switchtype, rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status && !(rcvmsg->rsp_status)) {
|
|
||||||
pr_debug("%s: SCIOCSETSWITCH: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCGETSWITCH:
|
|
||||||
{
|
|
||||||
pr_debug("%s: SCIOGETSWITCH: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the switch type from the board
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
|
|
||||||
ceReqCallGetSwitchType, 0, 0, NULL, rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status && !(rcvmsg->rsp_status)) {
|
|
||||||
pr_debug("%s: SCIOCGETSWITCH: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
switchtype = rcvmsg->msg_data.byte_array[0];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Package the switch type and send to user space
|
|
||||||
*/
|
|
||||||
if (copy_to_user(data->dataptr, &switchtype,
|
|
||||||
sizeof(char))) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCGETSPID:
|
|
||||||
{
|
|
||||||
pr_debug("%s: SCIOGETSPID: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
spid = kzalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
|
|
||||||
if (!spid) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Get the spid from the board
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID,
|
|
||||||
data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
pr_debug("%s: SCIOCGETSPID: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
} else {
|
|
||||||
pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
kfree(spid);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Package the switch type and send to user space
|
|
||||||
*/
|
|
||||||
if (copy_to_user(data->dataptr, spid, SCIOC_SPIDSIZE)) {
|
|
||||||
kfree(spid);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(spid);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCSETSPID:
|
|
||||||
{
|
|
||||||
pr_debug("%s: DCBIOSETSPID: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the spid from user space
|
|
||||||
*/
|
|
||||||
spid = memdup_user(data->dataptr, SCIOC_SPIDSIZE);
|
|
||||||
if (IS_ERR(spid)) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return PTR_ERR(spid);
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n",
|
|
||||||
sc_adapter[card]->devicename, data->channel, spid);
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall,
|
|
||||||
ceReqClass0, ceReqCallSetSPID, data->channel,
|
|
||||||
strlen(spid), spid, rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status && !(rcvmsg->rsp_status)) {
|
|
||||||
pr_debug("%s: SCIOCSETSPID: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
kfree(spid);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
kfree(spid);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCGETDN:
|
|
||||||
{
|
|
||||||
pr_debug("%s: SCIOGETDN: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the dn from the board
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber,
|
|
||||||
data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
pr_debug("%s: SCIOCGETDN: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL);
|
|
||||||
if (!dn) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Package the dn and send to user space
|
|
||||||
*/
|
|
||||||
if (copy_to_user(data->dataptr, dn, SCIOC_DNSIZE)) {
|
|
||||||
kfree(dn);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
kfree(dn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCSETDN:
|
|
||||||
{
|
|
||||||
pr_debug("%s: SCIOSETDN: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the spid from user space
|
|
||||||
*/
|
|
||||||
dn = memdup_user(data->dataptr, SCIOC_DNSIZE);
|
|
||||||
if (IS_ERR(dn)) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return PTR_ERR(dn);
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n",
|
|
||||||
sc_adapter[card]->devicename, data->channel, dn);
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall,
|
|
||||||
ceReqClass0, ceReqCallSetMyNumber, data->channel,
|
|
||||||
strlen(dn), dn, rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status && !(rcvmsg->rsp_status)) {
|
|
||||||
pr_debug("%s: SCIOCSETDN: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
kfree(dn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
kfree(dn);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCTRACE:
|
|
||||||
|
|
||||||
pr_debug("%s: SCIOTRACE: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
/* sc_adapter[card]->trace = !sc_adapter[card]->trace;
|
|
||||||
pr_debug("%s: SCIOCTRACE: tracing turned %s\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
sc_adapter[card]->trace ? "ON" : "OFF"); */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SCIOCSTAT:
|
|
||||||
{
|
|
||||||
boardInfo *bi;
|
|
||||||
|
|
||||||
pr_debug("%s: SCIOSTAT: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
bi = kzalloc(sizeof(boardInfo), GFP_KERNEL);
|
|
||||||
if (!bi) {
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(rcvmsg);
|
|
||||||
GetStatus(card, bi);
|
|
||||||
|
|
||||||
if (copy_to_user(data->dataptr, bi, sizeof(boardInfo))) {
|
|
||||||
kfree(bi);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(bi);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCGETSPEED:
|
|
||||||
{
|
|
||||||
pr_debug("%s: SCIOGETSPEED: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the speed from the board
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
|
|
||||||
ceReqCallGetCallType, data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status && !(rcvmsg->rsp_status)) {
|
|
||||||
pr_debug("%s: SCIOCGETSPEED: command successful\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
speed = rcvmsg->msg_data.byte_array[0];
|
|
||||||
|
|
||||||
kfree(rcvmsg);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Package the switch type and send to user space
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (copy_to_user(data->dataptr, &speed, sizeof(char)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SCIOCSETSPEED:
|
|
||||||
pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SCIOCLOOPTST:
|
|
||||||
pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(rcvmsg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GetStatus(int card, boardInfo *bi)
|
|
||||||
{
|
|
||||||
RspMessage rcvmsg;
|
|
||||||
int i, status;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fill in some of the basic info about the board
|
|
||||||
*/
|
|
||||||
bi->modelid = sc_adapter[card]->model;
|
|
||||||
strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no);
|
|
||||||
strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no);
|
|
||||||
bi->iobase = sc_adapter[card]->iobase;
|
|
||||||
bi->rambase = sc_adapter[card]->rambase;
|
|
||||||
bi->irq = sc_adapter[card]->interrupt;
|
|
||||||
bi->ramsize = sc_adapter[card]->hwconfig.ram_size;
|
|
||||||
bi->interface = sc_adapter[card]->hwconfig.st_u_sense;
|
|
||||||
strcpy(bi->load_ver, sc_adapter[card]->load_ver);
|
|
||||||
strcpy(bi->proc_ver, sc_adapter[card]->proc_ver);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the current PhyStats and LnkStats
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2,
|
|
||||||
ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
if (sc_adapter[card]->model < PRI_BOARD) {
|
|
||||||
bi->l1_status = rcvmsg.msg_data.byte_array[2];
|
|
||||||
for (i = 0; i < BRI_CHANNELS; i++)
|
|
||||||
bi->status.bristats[i].phy_stat =
|
|
||||||
rcvmsg.msg_data.byte_array[i];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bi->l1_status = rcvmsg.msg_data.byte_array[0];
|
|
||||||
bi->l2_status = rcvmsg.msg_data.byte_array[1];
|
|
||||||
for (i = 0; i < PRI_CHANNELS; i++)
|
|
||||||
bi->status.pristats[i].phy_stat =
|
|
||||||
rcvmsg.msg_data.byte_array[i + 2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the call types for each channel
|
|
||||||
*/
|
|
||||||
for (i = 0; i < sc_adapter[card]->nChannels; i++) {
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
|
|
||||||
ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
if (sc_adapter[card]->model == PRI_BOARD) {
|
|
||||||
bi->status.pristats[i].call_type =
|
|
||||||
rcvmsg.msg_data.byte_array[0];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bi->status.bristats[i].call_type =
|
|
||||||
rcvmsg.msg_data.byte_array[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If PRI, get the call states and service states for each channel
|
|
||||||
*/
|
|
||||||
if (sc_adapter[card]->model == PRI_BOARD) {
|
|
||||||
/*
|
|
||||||
* Get the call states
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
|
|
||||||
ceReqPhyChCallState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
for (i = 0; i < PRI_CHANNELS; i++)
|
|
||||||
bi->status.pristats[i].call_state =
|
|
||||||
rcvmsg.msg_data.byte_array[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the service states
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
|
|
||||||
ceReqPhyChServState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
for (i = 0; i < PRI_CHANNELS; i++)
|
|
||||||
bi->status.pristats[i].serv_state =
|
|
||||||
rcvmsg.msg_data.byte_array[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the link stats for the channels
|
|
||||||
*/
|
|
||||||
for (i = 1; i <= PRI_CHANNELS; i++) {
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
|
|
||||||
ceReqLnkGetStats, i, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
bi->status.pristats[i - 1].link_stats.tx_good =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[0];
|
|
||||||
bi->status.pristats[i - 1].link_stats.tx_bad =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[4];
|
|
||||||
bi->status.pristats[i - 1].link_stats.rx_good =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[8];
|
|
||||||
bi->status.pristats[i - 1].link_stats.rx_bad =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[12];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Link stats for the D channel
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
|
|
||||||
ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
|
|
||||||
bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
|
|
||||||
bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
|
|
||||||
bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If BRI or POTS, Get SPID, DN and call types for each channel
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the link stats for the channels
|
|
||||||
*/
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
|
|
||||||
ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status) {
|
|
||||||
bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
|
|
||||||
bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
|
|
||||||
bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
|
|
||||||
bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
|
|
||||||
bi->status.bristats[0].link_stats.tx_good =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[16];
|
|
||||||
bi->status.bristats[0].link_stats.tx_bad =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[20];
|
|
||||||
bi->status.bristats[0].link_stats.rx_good =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[24];
|
|
||||||
bi->status.bristats[0].link_stats.rx_bad =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[28];
|
|
||||||
bi->status.bristats[1].link_stats.tx_good =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[32];
|
|
||||||
bi->status.bristats[1].link_stats.tx_bad =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[36];
|
|
||||||
bi->status.bristats[1].link_stats.rx_good =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[40];
|
|
||||||
bi->status.bristats[1].link_stats.rx_bad =
|
|
||||||
(unsigned long)rcvmsg.msg_data.byte_array[44];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the SPIDs
|
|
||||||
*/
|
|
||||||
for (i = 0; i < BRI_CHANNELS; i++) {
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
|
|
||||||
ceReqCallGetSPID, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status)
|
|
||||||
strcpy(bi->status.bristats[i].spid, rcvmsg.msg_data.byte_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the DNs
|
|
||||||
*/
|
|
||||||
for (i = 0; i < BRI_CHANNELS; i++) {
|
|
||||||
status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
|
|
||||||
ceReqCallGetMyNumber, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
|
|
||||||
if (!status)
|
|
||||||
strcpy(bi->status.bristats[i].dn, rcvmsg.msg_data.byte_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,230 +0,0 @@
|
|||||||
/* $Id: message.c,v 1.5.8.2 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* functions for sending and receiving control messages
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
#include <linux/sched.h>
|
|
||||||
#include "includes.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "message.h"
|
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* receive a message from the board
|
|
||||||
*/
|
|
||||||
int receivemessage(int card, RspMessage *rspmsg)
|
|
||||||
{
|
|
||||||
DualPortMemory *dpm;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: Entered receivemessage\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if there are messages waiting
|
|
||||||
*/
|
|
||||||
if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
|
|
||||||
/*
|
|
||||||
* Map in the DPM to the base page and copy the message
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
|
|
||||||
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
|
|
||||||
dpm = (DualPortMemory *) sc_adapter[card]->rambase;
|
|
||||||
memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
|
|
||||||
MSG_LEN);
|
|
||||||
dpm->rsp_tail = (dpm->rsp_tail + 1) % MAX_MESSAGES;
|
|
||||||
inb(sc_adapter[card]->ioport[FIFO_READ]);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
/*
|
|
||||||
* Tell the board that the message is received
|
|
||||||
*/
|
|
||||||
pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
|
|
||||||
"cnt:%d (type,class,code):(%d,%d,%d) "
|
|
||||||
"link:%d stat:0x%x\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rspmsg->sequence_no,
|
|
||||||
rspmsg->process_id,
|
|
||||||
rspmsg->time_stamp,
|
|
||||||
rspmsg->cmd_sequence_no,
|
|
||||||
rspmsg->msg_byte_cnt,
|
|
||||||
rspmsg->type,
|
|
||||||
rspmsg->class,
|
|
||||||
rspmsg->code,
|
|
||||||
rspmsg->phy_link_no,
|
|
||||||
rspmsg->rsp_status);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -ENOMSG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* send a message to the board
|
|
||||||
*/
|
|
||||||
int sendmessage(int card,
|
|
||||||
unsigned int procid,
|
|
||||||
unsigned int type,
|
|
||||||
unsigned int class,
|
|
||||||
unsigned int code,
|
|
||||||
unsigned int link,
|
|
||||||
unsigned int data_len,
|
|
||||||
unsigned int *data)
|
|
||||||
{
|
|
||||||
DualPortMemory *dpm;
|
|
||||||
ReqMessage sndmsg;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure we only send CEPID messages when the engine is up
|
|
||||||
* and CMPID messages when it is down
|
|
||||||
*/
|
|
||||||
if (sc_adapter[card]->EngineUp && procid == CMPID) {
|
|
||||||
pr_debug("%s: Attempt to send CM message with engine up\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return -ESRCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sc_adapter[card]->EngineUp && procid == CEPID) {
|
|
||||||
pr_debug("%s: Attempt to send CE message with engine down\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return -ESRCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&sndmsg, 0, MSG_LEN);
|
|
||||||
sndmsg.msg_byte_cnt = 4;
|
|
||||||
sndmsg.type = type;
|
|
||||||
sndmsg.class = class;
|
|
||||||
sndmsg.code = code;
|
|
||||||
sndmsg.phy_link_no = link;
|
|
||||||
|
|
||||||
if (data_len > 0) {
|
|
||||||
if (data_len > MSG_DATA_LEN)
|
|
||||||
data_len = MSG_DATA_LEN;
|
|
||||||
memcpy(&(sndmsg.msg_data), data, data_len);
|
|
||||||
sndmsg.msg_byte_cnt = data_len + 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
sndmsg.process_id = procid;
|
|
||||||
sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* wait for an empty slot in the queue
|
|
||||||
*/
|
|
||||||
while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
|
|
||||||
udelay(1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Disable interrupts and map in shared memory
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
|
|
||||||
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
|
|
||||||
dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */
|
|
||||||
memcpy_toio(&(dpm->req_queue[dpm->req_head]), &sndmsg, MSG_LEN);
|
|
||||||
dpm->req_head = (dpm->req_head + 1) % MAX_MESSAGES;
|
|
||||||
outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
|
|
||||||
pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
|
|
||||||
"cnt:%d (type,class,code):(%d,%d,%d) "
|
|
||||||
"link:%d\n ",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
sndmsg.sequence_no,
|
|
||||||
sndmsg.process_id,
|
|
||||||
sndmsg.time_stamp,
|
|
||||||
sndmsg.msg_byte_cnt,
|
|
||||||
sndmsg.type,
|
|
||||||
sndmsg.class,
|
|
||||||
sndmsg.code,
|
|
||||||
sndmsg.phy_link_no);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int send_and_receive(int card,
|
|
||||||
unsigned int procid,
|
|
||||||
unsigned char type,
|
|
||||||
unsigned char class,
|
|
||||||
unsigned char code,
|
|
||||||
unsigned char link,
|
|
||||||
unsigned char data_len,
|
|
||||||
unsigned char *data,
|
|
||||||
RspMessage *mesgdata,
|
|
||||||
int timeout)
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
int tries;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_adapter[card]->want_async_messages = 1;
|
|
||||||
retval = sendmessage(card, procid, type, class, code, link,
|
|
||||||
data_len, (unsigned int *) data);
|
|
||||||
|
|
||||||
if (retval) {
|
|
||||||
pr_debug("%s: SendMessage failed in SAR\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
sc_adapter[card]->want_async_messages = 0;
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
tries = 0;
|
|
||||||
/* wait for the response */
|
|
||||||
while (tries < timeout) {
|
|
||||||
schedule_timeout_interruptible(1);
|
|
||||||
|
|
||||||
pr_debug("SAR waiting..\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* See if we got our message back
|
|
||||||
*/
|
|
||||||
if ((sc_adapter[card]->async_msg.type == type) &&
|
|
||||||
(sc_adapter[card]->async_msg.class == class) &&
|
|
||||||
(sc_adapter[card]->async_msg.code == code) &&
|
|
||||||
(sc_adapter[card]->async_msg.phy_link_no == link)) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Got it!
|
|
||||||
*/
|
|
||||||
pr_debug("%s: Got ASYNC message\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
memcpy(mesgdata, &(sc_adapter[card]->async_msg),
|
|
||||||
sizeof(RspMessage));
|
|
||||||
sc_adapter[card]->want_async_messages = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
|
|
||||||
sc_adapter[card]->want_async_messages = 0;
|
|
||||||
return -ETIME;
|
|
||||||
}
|
|
@ -1,245 +0,0 @@
|
|||||||
/* $Id: message.h,v 1.1.10.1 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* structures, macros and defines useful for sending
|
|
||||||
* messages to the adapter
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Board message macros, defines and structures
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MESSAGE_H
|
|
||||||
#define MESSAGE_H
|
|
||||||
|
|
||||||
#define MAX_MESSAGES 32 /* Maximum messages that can be
|
|
||||||
queued */
|
|
||||||
#define MSG_DATA_LEN 48 /* Maximum size of message payload */
|
|
||||||
#define MSG_LEN 64 /* Size of a message */
|
|
||||||
#define CMPID 0 /* Loader message process ID */
|
|
||||||
#define CEPID 64 /* Firmware message process ID */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macro to determine if a message is a loader message
|
|
||||||
*/
|
|
||||||
#define IS_CM_MESSAGE(mesg, tx, cx, dx) \
|
|
||||||
((mesg.type == cmRspType##tx) \
|
|
||||||
&& (mesg.class == cmRspClass##cx) \
|
|
||||||
&& (mesg.code == cmRsp##dx))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Macro to determine if a message is a firmware message
|
|
||||||
*/
|
|
||||||
#define IS_CE_MESSAGE(mesg, tx, cx, dx) \
|
|
||||||
((mesg.type == ceRspType##tx) \
|
|
||||||
&& (mesg.class == ceRspClass##cx) \
|
|
||||||
&& (mesg.code == ceRsp##tx##dx))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loader Request and Response Messages
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* message types */
|
|
||||||
#define cmReqType1 1
|
|
||||||
#define cmReqType2 2
|
|
||||||
#define cmRspType0 0
|
|
||||||
#define cmRspType1 1
|
|
||||||
#define cmRspType2 2
|
|
||||||
#define cmRspType5 5
|
|
||||||
|
|
||||||
/* message classes */
|
|
||||||
#define cmReqClass0 0
|
|
||||||
#define cmRspClass0 0
|
|
||||||
|
|
||||||
/* message codes */
|
|
||||||
#define cmReqHWConfig 1 /* 1,0,1 */
|
|
||||||
#define cmReqMsgLpbk 2 /* 1,0,2 */
|
|
||||||
#define cmReqVersion 3 /* 1,0,3 */
|
|
||||||
#define cmReqLoadProc 1 /* 2,0,1 */
|
|
||||||
#define cmReqStartProc 2 /* 2,0,2 */
|
|
||||||
#define cmReqReadMem 6 /* 2,0,6 */
|
|
||||||
#define cmRspHWConfig cmReqHWConfig
|
|
||||||
#define cmRspMsgLpbk cmReqMsgLpbk
|
|
||||||
#define cmRspVersion cmReqVersion
|
|
||||||
#define cmRspLoadProc cmReqLoadProc
|
|
||||||
#define cmRspStartProc cmReqStartProc
|
|
||||||
#define cmRspReadMem cmReqReadMem
|
|
||||||
#define cmRspMiscEngineUp 1 /* 5,0,1 */
|
|
||||||
#define cmRspInvalid 0 /* 0,0,0 */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Firmware Request and Response Messages
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* message types */
|
|
||||||
#define ceReqTypePhy 1
|
|
||||||
#define ceReqTypeLnk 2
|
|
||||||
#define ceReqTypeCall 3
|
|
||||||
#define ceReqTypeStat 1
|
|
||||||
#define ceRspTypeErr 0
|
|
||||||
#define ceRspTypePhy ceReqTypePhy
|
|
||||||
#define ceRspTypeLnk ceReqTypeLnk
|
|
||||||
#define ceRspTypeCall ceReqTypeCall
|
|
||||||
#define ceRspTypeStat ceReqTypeStat
|
|
||||||
|
|
||||||
/* message classes */
|
|
||||||
#define ceReqClass0 0
|
|
||||||
#define ceReqClass1 1
|
|
||||||
#define ceReqClass2 2
|
|
||||||
#define ceReqClass3 3
|
|
||||||
#define ceRspClass0 ceReqClass0
|
|
||||||
#define ceRspClass1 ceReqClass1
|
|
||||||
#define ceRspClass2 ceReqClass2
|
|
||||||
#define ceRspClass3 ceReqClass3
|
|
||||||
|
|
||||||
/* message codes (B) = BRI only, (P) = PRI only, (V) = POTS only */
|
|
||||||
#define ceReqPhyProcInfo 1 /* 1,0,1 */
|
|
||||||
#define ceReqPhyConnect 1 /* 1,1,1 */
|
|
||||||
#define ceReqPhyDisconnect 2 /* 1,1,2 */
|
|
||||||
#define ceReqPhySetParams 3 /* 1,1,3 (P) */
|
|
||||||
#define ceReqPhyGetParams 4 /* 1,1,4 (P) */
|
|
||||||
#define ceReqPhyStatus 1 /* 1,2,1 */
|
|
||||||
#define ceReqPhyAcfaStatus 2 /* 1,2,2 (P) */
|
|
||||||
#define ceReqPhyChCallState 3 /* 1,2,3 (P) */
|
|
||||||
#define ceReqPhyChServState 4 /* 1,2,4 (P) */
|
|
||||||
#define ceReqPhyRLoopBack 1 /* 1,3,1 */
|
|
||||||
#define ceRspPhyProcInfo ceReqPhyProcInfo
|
|
||||||
#define ceRspPhyConnect ceReqPhyConnect
|
|
||||||
#define ceRspPhyDisconnect ceReqPhyDisconnect
|
|
||||||
#define ceRspPhySetParams ceReqPhySetParams
|
|
||||||
#define ceRspPhyGetParams ceReqPhyGetParams
|
|
||||||
#define ceRspPhyStatus ceReqPhyStatus
|
|
||||||
#define ceRspPhyAcfaStatus ceReqPhyAcfaStatus
|
|
||||||
#define ceRspPhyChCallState ceReqPhyChCallState
|
|
||||||
#define ceRspPhyChServState ceReqPhyChServState
|
|
||||||
#define ceRspPhyRLoopBack ceReqphyRLoopBack
|
|
||||||
#define ceReqLnkSetParam 1 /* 2,0,1 */
|
|
||||||
#define ceReqLnkGetParam 2 /* 2,0,2 */
|
|
||||||
#define ceReqLnkGetStats 3 /* 2,0,3 */
|
|
||||||
#define ceReqLnkWrite 1 /* 2,1,1 */
|
|
||||||
#define ceReqLnkRead 2 /* 2,1,2 */
|
|
||||||
#define ceReqLnkFlush 3 /* 2,1,3 */
|
|
||||||
#define ceReqLnkWrBufTrc 4 /* 2,1,4 */
|
|
||||||
#define ceReqLnkRdBufTrc 5 /* 2,1,5 */
|
|
||||||
#define ceRspLnkSetParam ceReqLnkSetParam
|
|
||||||
#define ceRspLnkGetParam ceReqLnkGetParam
|
|
||||||
#define ceRspLnkGetStats ceReqLnkGetStats
|
|
||||||
#define ceRspLnkWrite ceReqLnkWrite
|
|
||||||
#define ceRspLnkRead ceReqLnkRead
|
|
||||||
#define ceRspLnkFlush ceReqLnkFlush
|
|
||||||
#define ceRspLnkWrBufTrc ceReqLnkWrBufTrc
|
|
||||||
#define ceRspLnkRdBufTrc ceReqLnkRdBufTrc
|
|
||||||
#define ceReqCallSetSwitchType 1 /* 3,0,1 */
|
|
||||||
#define ceReqCallGetSwitchType 2 /* 3,0,2 */
|
|
||||||
#define ceReqCallSetFrameFormat 3 /* 3,0,3 */
|
|
||||||
#define ceReqCallGetFrameFormat 4 /* 3,0,4 */
|
|
||||||
#define ceReqCallSetCallType 5 /* 3,0,5 */
|
|
||||||
#define ceReqCallGetCallType 6 /* 3,0,6 */
|
|
||||||
#define ceReqCallSetSPID 7 /* 3,0,7 (!P) */
|
|
||||||
#define ceReqCallGetSPID 8 /* 3,0,8 (!P) */
|
|
||||||
#define ceReqCallSetMyNumber 9 /* 3,0,9 (!P) */
|
|
||||||
#define ceReqCallGetMyNumber 10 /* 3,0,10 (!P) */
|
|
||||||
#define ceRspCallSetSwitchType ceReqCallSetSwitchType
|
|
||||||
#define ceRspCallGetSwitchType ceReqCallSetSwitchType
|
|
||||||
#define ceRspCallSetFrameFormat ceReqCallSetFrameFormat
|
|
||||||
#define ceRspCallGetFrameFormat ceReqCallGetFrameFormat
|
|
||||||
#define ceRspCallSetCallType ceReqCallSetCallType
|
|
||||||
#define ceRspCallGetCallType ceReqCallGetCallType
|
|
||||||
#define ceRspCallSetSPID ceReqCallSetSPID
|
|
||||||
#define ceRspCallGetSPID ceReqCallGetSPID
|
|
||||||
#define ceRspCallSetMyNumber ceReqCallSetMyNumber
|
|
||||||
#define ceRspCallGetMyNumber ceReqCallGetMyNumber
|
|
||||||
#define ceRspStatAcfaStatus 2
|
|
||||||
#define ceRspStat
|
|
||||||
#define ceRspErrError 0 /* 0,0,0 */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call Types
|
|
||||||
*/
|
|
||||||
#define CALLTYPE_64K 0
|
|
||||||
#define CALLTYPE_56K 1
|
|
||||||
#define CALLTYPE_SPEECH 2
|
|
||||||
#define CALLTYPE_31KHZ 3
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Link Level data contains a pointer to and the length of
|
|
||||||
* a buffer in shared RAM. Used by LnkRead and LnkWrite message
|
|
||||||
* types. Part of RspMsgStruct and ReqMsgStruct.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
unsigned long buff_offset;
|
|
||||||
unsigned short msg_len;
|
|
||||||
} LLData;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Message payload template for an HWConfig message
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
char st_u_sense;
|
|
||||||
char powr_sense;
|
|
||||||
char sply_sense;
|
|
||||||
unsigned char asic_id;
|
|
||||||
long ram_size;
|
|
||||||
char serial_no[13];
|
|
||||||
char part_no[13];
|
|
||||||
char rev_no[2];
|
|
||||||
} HWConfig_pl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A Message
|
|
||||||
*/
|
|
||||||
struct message {
|
|
||||||
unsigned char sequence_no;
|
|
||||||
unsigned char process_id;
|
|
||||||
unsigned char time_stamp;
|
|
||||||
unsigned char cmd_sequence_no; /* Rsp messages only */
|
|
||||||
unsigned char reserved1[3];
|
|
||||||
unsigned char msg_byte_cnt;
|
|
||||||
unsigned char type;
|
|
||||||
unsigned char class;
|
|
||||||
unsigned char code;
|
|
||||||
unsigned char phy_link_no;
|
|
||||||
unsigned char rsp_status; /* Rsp messages only */
|
|
||||||
unsigned char reseved2[3];
|
|
||||||
union {
|
|
||||||
unsigned char byte_array[MSG_DATA_LEN];
|
|
||||||
LLData response;
|
|
||||||
HWConfig_pl HWCresponse;
|
|
||||||
} msg_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct message ReqMessage; /* Request message */
|
|
||||||
typedef struct message RspMessage; /* Response message */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The first 5010 bytes of shared memory contain the message queues,
|
|
||||||
* indexes and other data. This structure is its template
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
volatile ReqMessage req_queue[MAX_MESSAGES];
|
|
||||||
volatile RspMessage rsp_queue[MAX_MESSAGES];
|
|
||||||
volatile unsigned char req_head;
|
|
||||||
volatile unsigned char req_tail;
|
|
||||||
volatile unsigned char rsp_head;
|
|
||||||
volatile unsigned char rsp_tail;
|
|
||||||
volatile unsigned long signature;
|
|
||||||
volatile unsigned long trace_enable;
|
|
||||||
volatile unsigned char reserved[4];
|
|
||||||
} DualPortMemory;
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,204 +0,0 @@
|
|||||||
/* $Id: packet.c,v 1.5.8.1 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "message.h"
|
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
int sndpkt(int devId, int channel, int ack, struct sk_buff *data)
|
|
||||||
{
|
|
||||||
LLData ReqLnkWrite;
|
|
||||||
int status;
|
|
||||||
int card;
|
|
||||||
unsigned long len;
|
|
||||||
|
|
||||||
card = get_card_from_id(devId);
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: sndpkt: frst = 0x%lx nxt = %d f = %d n = %d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
sc_adapter[card]->channel[channel].first_sendbuf,
|
|
||||||
sc_adapter[card]->channel[channel].next_sendbuf,
|
|
||||||
sc_adapter[card]->channel[channel].free_sendbufs,
|
|
||||||
sc_adapter[card]->channel[channel].num_sendbufs);
|
|
||||||
|
|
||||||
if (!sc_adapter[card]->channel[channel].free_sendbufs) {
|
|
||||||
pr_debug("%s: out of TX buffers\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->len > BUFFER_SIZE) {
|
|
||||||
pr_debug("%s: data overflows buffer size (data > buffer)\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReqLnkWrite.buff_offset = sc_adapter[card]->channel[channel].next_sendbuf *
|
|
||||||
BUFFER_SIZE + sc_adapter[card]->channel[channel].first_sendbuf;
|
|
||||||
ReqLnkWrite.msg_len = data->len; /* sk_buff size */
|
|
||||||
pr_debug("%s: writing %d bytes to buffer offset 0x%lx\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset);
|
|
||||||
memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sendmessage
|
|
||||||
*/
|
|
||||||
pr_debug("%s: sndpkt size=%d, buf_offset=0x%lx buf_indx=%d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset,
|
|
||||||
sc_adapter[card]->channel[channel].next_sendbuf);
|
|
||||||
|
|
||||||
status = sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkWrite,
|
|
||||||
channel + 1, sizeof(LLData), (unsigned int *)&ReqLnkWrite);
|
|
||||||
len = data->len;
|
|
||||||
if (status) {
|
|
||||||
pr_debug("%s: failed to send packet, status = %d\n",
|
|
||||||
sc_adapter[card]->devicename, status);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sc_adapter[card]->channel[channel].free_sendbufs--;
|
|
||||||
sc_adapter[card]->channel[channel].next_sendbuf =
|
|
||||||
++sc_adapter[card]->channel[channel].next_sendbuf ==
|
|
||||||
sc_adapter[card]->channel[channel].num_sendbufs ? 0 :
|
|
||||||
sc_adapter[card]->channel[channel].next_sendbuf;
|
|
||||||
pr_debug("%s: packet sent successfully\n", sc_adapter[card]->devicename);
|
|
||||||
dev_kfree_skb(data);
|
|
||||||
indicate_status(card, ISDN_STAT_BSENT, channel, (char *)&len);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rcvpkt(int card, RspMessage *rcvmsg)
|
|
||||||
{
|
|
||||||
LLData newll;
|
|
||||||
struct sk_buff *skb;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("invalid param: %d is not a valid card id\n", card);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (rcvmsg->rsp_status) {
|
|
||||||
case 0x01:
|
|
||||||
case 0x02:
|
|
||||||
case 0x70:
|
|
||||||
pr_debug("%s: error status code: 0x%x\n",
|
|
||||||
sc_adapter[card]->devicename, rcvmsg->rsp_status);
|
|
||||||
return;
|
|
||||||
case 0x00:
|
|
||||||
if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) {
|
|
||||||
printk(KERN_WARNING "%s: rcvpkt out of memory, dropping packet\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
skb_put(skb, rcvmsg->msg_data.response.msg_len);
|
|
||||||
pr_debug("%s: getting data from offset: 0x%lx\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
rcvmsg->msg_data.response.buff_offset);
|
|
||||||
memcpy_fromshmem(card,
|
|
||||||
skb_put(skb, rcvmsg->msg_data.response.msg_len),
|
|
||||||
(char *)rcvmsg->msg_data.response.buff_offset,
|
|
||||||
rcvmsg->msg_data.response.msg_len);
|
|
||||||
sc_adapter[card]->card->rcvcallb_skb(sc_adapter[card]->driverId,
|
|
||||||
rcvmsg->phy_link_no - 1, skb);
|
|
||||||
|
|
||||||
case 0x03:
|
|
||||||
/*
|
|
||||||
* Recycle the buffer
|
|
||||||
*/
|
|
||||||
pr_debug("%s: buffer size : %d\n",
|
|
||||||
sc_adapter[card]->devicename, BUFFER_SIZE);
|
|
||||||
/* memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */
|
|
||||||
newll.buff_offset = rcvmsg->msg_data.response.buff_offset;
|
|
||||||
newll.msg_len = BUFFER_SIZE;
|
|
||||||
pr_debug("%s: recycled buffer at offset 0x%lx size %d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
newll.buff_offset, newll.msg_len);
|
|
||||||
sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead,
|
|
||||||
rcvmsg->phy_link_no, sizeof(LLData), (unsigned int *)&newll);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int setup_buffers(int card, int c)
|
|
||||||
{
|
|
||||||
unsigned int nBuffers, i, cBase;
|
|
||||||
unsigned int buffer_size;
|
|
||||||
LLData RcvBuffOffset;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("invalid param: %d is not a valid card id\n", card);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calculate the buffer offsets (send/recv/send/recv)
|
|
||||||
*/
|
|
||||||
pr_debug("%s: setting up channel buffer space in shared RAM\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
buffer_size = BUFFER_SIZE;
|
|
||||||
nBuffers = ((sc_adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2;
|
|
||||||
nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers;
|
|
||||||
pr_debug("%s: calculating buffer space: %d buffers, %d big\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
nBuffers, buffer_size);
|
|
||||||
if (nBuffers < 2) {
|
|
||||||
pr_debug("%s: not enough buffer space\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
cBase = (nBuffers * buffer_size) * (c - 1);
|
|
||||||
pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n",
|
|
||||||
sc_adapter[card]->devicename, cBase);
|
|
||||||
sc_adapter[card]->channel[c - 1].first_sendbuf = BUFFER_BASE + cBase;
|
|
||||||
sc_adapter[card]->channel[c - 1].num_sendbufs = nBuffers / 2;
|
|
||||||
sc_adapter[card]->channel[c - 1].free_sendbufs = nBuffers / 2;
|
|
||||||
sc_adapter[card]->channel[c - 1].next_sendbuf = 0;
|
|
||||||
pr_debug("%s: send buffer setup complete: first=0x%lx n=%d f=%d, nxt=%d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
sc_adapter[card]->channel[c - 1].first_sendbuf,
|
|
||||||
sc_adapter[card]->channel[c - 1].num_sendbufs,
|
|
||||||
sc_adapter[card]->channel[c - 1].free_sendbufs,
|
|
||||||
sc_adapter[card]->channel[c - 1].next_sendbuf);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prep the receive buffers
|
|
||||||
*/
|
|
||||||
pr_debug("%s: adding %d RecvBuffers:\n",
|
|
||||||
sc_adapter[card]->devicename, nBuffers / 2);
|
|
||||||
for (i = 0; i < nBuffers / 2; i++) {
|
|
||||||
RcvBuffOffset.buff_offset =
|
|
||||||
((sc_adapter[card]->channel[c - 1].first_sendbuf +
|
|
||||||
(nBuffers / 2) * buffer_size) + (buffer_size * i));
|
|
||||||
RcvBuffOffset.msg_len = buffer_size;
|
|
||||||
pr_debug("%s: adding RcvBuffer #%d offset=0x%lx sz=%d bufsz:%d\n",
|
|
||||||
sc_adapter[card]->devicename,
|
|
||||||
i + 1, RcvBuffOffset.buff_offset,
|
|
||||||
RcvBuffOffset.msg_len, buffer_size);
|
|
||||||
sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead,
|
|
||||||
c, sizeof(LLData), (unsigned int *)&RcvBuffOffset);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
#ifndef __ISDN_SC_SCIOC_H__
|
|
||||||
#define __ISDN_SC_SCIOC_H__
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* IOCTL Command Codes
|
|
||||||
*/
|
|
||||||
#define SCIOCLOAD 0x01 /* Load a firmware record */
|
|
||||||
#define SCIOCRESET 0x02 /* Perform hard reset */
|
|
||||||
#define SCIOCDEBUG 0x03 /* Set debug level */
|
|
||||||
#define SCIOCREV 0x04 /* Get driver revision(s) */
|
|
||||||
#define SCIOCSTART 0x05 /* Start the firmware */
|
|
||||||
#define SCIOCGETSWITCH 0x06 /* Get switch type */
|
|
||||||
#define SCIOCSETSWITCH 0x07 /* Set switch type */
|
|
||||||
#define SCIOCGETSPID 0x08 /* Get channel SPID */
|
|
||||||
#define SCIOCSETSPID 0x09 /* Set channel SPID */
|
|
||||||
#define SCIOCGETDN 0x0A /* Get channel DN */
|
|
||||||
#define SCIOCSETDN 0x0B /* Set channel DN */
|
|
||||||
#define SCIOCTRACE 0x0C /* Toggle trace mode */
|
|
||||||
#define SCIOCSTAT 0x0D /* Get line status */
|
|
||||||
#define SCIOCGETSPEED 0x0E /* Set channel speed */
|
|
||||||
#define SCIOCSETSPEED 0x0F /* Set channel speed */
|
|
||||||
#define SCIOCLOOPTST 0x10 /* Perform loopback test */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int device;
|
|
||||||
int channel;
|
|
||||||
unsigned long command;
|
|
||||||
void __user *dataptr;
|
|
||||||
} scs_ioctl;
|
|
||||||
|
|
||||||
/* Size of strings */
|
|
||||||
#define SCIOC_SPIDSIZE 49
|
|
||||||
#define SCIOC_DNSIZE SCIOC_SPIDSIZE
|
|
||||||
#define SCIOC_REVSIZE SCIOC_SPIDSIZE
|
|
||||||
#define SCIOC_SRECSIZE 49
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned long tx_good;
|
|
||||||
unsigned long tx_bad;
|
|
||||||
unsigned long rx_good;
|
|
||||||
unsigned long rx_bad;
|
|
||||||
} ChLinkStats;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char spid[49];
|
|
||||||
char dn[49];
|
|
||||||
char call_type;
|
|
||||||
char phy_stat;
|
|
||||||
ChLinkStats link_stats;
|
|
||||||
} BRIStat;
|
|
||||||
|
|
||||||
typedef BRIStat POTStat;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char call_type;
|
|
||||||
char call_state;
|
|
||||||
char serv_state;
|
|
||||||
char phy_stat;
|
|
||||||
ChLinkStats link_stats;
|
|
||||||
} PRIStat;
|
|
||||||
|
|
||||||
typedef char PRIInfo;
|
|
||||||
typedef char BRIInfo;
|
|
||||||
typedef char POTInfo;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char acfa_nos;
|
|
||||||
char acfa_ais;
|
|
||||||
char acfa_los;
|
|
||||||
char acfa_rra;
|
|
||||||
char acfa_slpp;
|
|
||||||
char acfa_slpn;
|
|
||||||
char acfa_fsrf;
|
|
||||||
} ACFAStat;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned char modelid;
|
|
||||||
char serial_no[13];
|
|
||||||
char part_no[13];
|
|
||||||
char load_ver[11];
|
|
||||||
char proc_ver[11];
|
|
||||||
int iobase;
|
|
||||||
long rambase;
|
|
||||||
char irq;
|
|
||||||
long ramsize;
|
|
||||||
char interface;
|
|
||||||
char switch_type;
|
|
||||||
char l1_status;
|
|
||||||
char l2_status;
|
|
||||||
ChLinkStats dch_stats;
|
|
||||||
ACFAStat AcfaStats;
|
|
||||||
union {
|
|
||||||
PRIStat pristats[23];
|
|
||||||
BRIStat bristats[2];
|
|
||||||
POTStat potsstats[2];
|
|
||||||
} status;
|
|
||||||
union {
|
|
||||||
PRIInfo priinfo;
|
|
||||||
BRIInfo briinfo;
|
|
||||||
POTInfo potsinfo;
|
|
||||||
} info;
|
|
||||||
} boardInfo;
|
|
||||||
|
|
||||||
#endif /* __ISDN_SC_SCIOC_H__ */
|
|
@ -1,138 +0,0 @@
|
|||||||
/* $Id: shmem.c,v 1.2.10.1 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* Card functions implementing ISDN4Linux functionality
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h" /* This must be first */
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned char ch;
|
|
||||||
unsigned long dest_rem = ((unsigned long) dest) % 0x4000;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n > SRAM_PAGESIZE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* determine the page to load from the address
|
|
||||||
*/
|
|
||||||
ch = (unsigned long) dest / SRAM_PAGESIZE;
|
|
||||||
pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename, ch);
|
|
||||||
/*
|
|
||||||
* Block interrupts and load the page
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
|
|
||||||
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
|
|
||||||
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
|
|
||||||
memcpy_toio((void __iomem *)(sc_adapter[card]->rambase + dest_rem), src, n);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
pr_debug("%s: set page to %#x\n", sc_adapter[card]->devicename,
|
|
||||||
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80);
|
|
||||||
pr_debug("%s: copying %zu bytes from %#lx to %#lx\n",
|
|
||||||
sc_adapter[card]->devicename, n,
|
|
||||||
(unsigned long) src,
|
|
||||||
sc_adapter[card]->rambase + ((unsigned long) dest % 0x4000));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reverse of above
|
|
||||||
*/
|
|
||||||
void memcpy_fromshmem(int card, void *dest, const void *src, size_t n)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned char ch;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n > SRAM_PAGESIZE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* determine the page to load from the address
|
|
||||||
*/
|
|
||||||
ch = (unsigned long) src / SRAM_PAGESIZE;
|
|
||||||
pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename, ch);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Block interrupts and load the page
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
|
|
||||||
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
|
|
||||||
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
|
|
||||||
memcpy_fromio(dest, (void *)(sc_adapter[card]->rambase +
|
|
||||||
((unsigned long) src % 0x4000)), n);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
pr_debug("%s: set page to %#x\n", sc_adapter[card]->devicename,
|
|
||||||
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80);
|
|
||||||
/* pr_debug("%s: copying %d bytes from %#x to %#x\n",
|
|
||||||
sc_adapter[card]->devicename, n,
|
|
||||||
sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
void memset_shmem(int card, void *dest, int c, size_t n)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned char ch;
|
|
||||||
|
|
||||||
if (!IS_VALID_CARD(card)) {
|
|
||||||
pr_debug("Invalid param: %d is not a valid card id\n", card);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n > SRAM_PAGESIZE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* determine the page to load from the address
|
|
||||||
*/
|
|
||||||
ch = (unsigned long) dest / SRAM_PAGESIZE;
|
|
||||||
pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename, ch);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Block interrupts and load the page
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
|
|
||||||
outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80,
|
|
||||||
sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
|
|
||||||
memset_io(sc_adapter[card]->rambase +
|
|
||||||
((unsigned long) dest % 0x4000), c, n);
|
|
||||||
pr_debug("%s: set page to %#x\n", sc_adapter[card]->devicename,
|
|
||||||
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
}
|
|
||||||
#endif /* 0 */
|
|
@ -1,122 +0,0 @@
|
|||||||
/* $Id: timer.c,v 1.3.6.1 2001/09/23 22:24:59 kai Exp $
|
|
||||||
*
|
|
||||||
* Copyright (C) 1996 SpellCaster Telecommunications Inc.
|
|
||||||
*
|
|
||||||
* This software may be used and distributed according to the terms
|
|
||||||
* of the GNU General Public License, incorporated herein by reference.
|
|
||||||
*
|
|
||||||
* For more information, please contact gpl-info@spellcast.com or write:
|
|
||||||
*
|
|
||||||
* SpellCaster Telecommunications Inc.
|
|
||||||
* 5621 Finch Avenue East, Unit #3
|
|
||||||
* Scarborough, Ontario Canada
|
|
||||||
* M1B 2T9
|
|
||||||
* +1 (416) 297-8565
|
|
||||||
* +1 (416) 297-6433 Facsimile
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "message.h"
|
|
||||||
#include "card.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write the proper values into the I/O ports following a reset
|
|
||||||
*/
|
|
||||||
static void setup_ports(int card)
|
|
||||||
{
|
|
||||||
|
|
||||||
outb((sc_adapter[card]->rambase >> 12), sc_adapter[card]->ioport[EXP_BASE]);
|
|
||||||
|
|
||||||
/* And the IRQ */
|
|
||||||
outb((sc_adapter[card]->interrupt | 0x80),
|
|
||||||
sc_adapter[card]->ioport[IRQ_SELECT]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Timed function to check the status of a previous reset
|
|
||||||
* Must be very fast as this function runs in the context of
|
|
||||||
* an interrupt handler.
|
|
||||||
*
|
|
||||||
* Setup the ioports for the board that were cleared by the reset.
|
|
||||||
* Then, check to see if the signate has been set. Next, set the
|
|
||||||
* signature to a known value and issue a startproc if needed.
|
|
||||||
*/
|
|
||||||
void sc_check_reset(unsigned long data)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned long sig;
|
|
||||||
int card = (unsigned int) data;
|
|
||||||
|
|
||||||
pr_debug("%s: check_timer timer called\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
/* Setup the io ports */
|
|
||||||
setup_ports(card);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
outb(sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport],
|
|
||||||
(sc_adapter[card]->shmem_magic >> 14) | 0x80);
|
|
||||||
sig = (unsigned long) *((unsigned long *)(sc_adapter[card]->rambase + SIG_OFFSET));
|
|
||||||
|
|
||||||
/* check the signature */
|
|
||||||
if (sig == SIGNATURE) {
|
|
||||||
flushreadfifo(card);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
/* See if we need to do a startproc */
|
|
||||||
if (sc_adapter[card]->StartOnReset)
|
|
||||||
startproc(card);
|
|
||||||
} else {
|
|
||||||
pr_debug("%s: No signature yet, waiting another %lu jiffies.\n",
|
|
||||||
sc_adapter[card]->devicename, CHECKRESET_TIME);
|
|
||||||
mod_timer(&sc_adapter[card]->reset_timer, jiffies + CHECKRESET_TIME);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Timed function to check the status of a previous reset
|
|
||||||
* Must be very fast as this function runs in the context of
|
|
||||||
* an interrupt handler.
|
|
||||||
*
|
|
||||||
* Send check sc_adapter->phystat to see if the channels are up
|
|
||||||
* If they are, tell ISDN4Linux that the board is up. If not,
|
|
||||||
* tell IADN4Linux that it is up. Always reset the timer to
|
|
||||||
* fire again (endless loop).
|
|
||||||
*/
|
|
||||||
void check_phystat(unsigned long data)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
int card = (unsigned int) data;
|
|
||||||
|
|
||||||
pr_debug("%s: Checking status...\n", sc_adapter[card]->devicename);
|
|
||||||
/*
|
|
||||||
* check the results of the last PhyStat and change only if
|
|
||||||
* has changed drastically
|
|
||||||
*/
|
|
||||||
if (sc_adapter[card]->nphystat && !sc_adapter[card]->phystat) { /* All is well */
|
|
||||||
pr_debug("PhyStat transition to RUN\n");
|
|
||||||
pr_info("%s: Switch contacted, transmitter enabled\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
indicate_status(card, ISDN_STAT_RUN, 0, NULL);
|
|
||||||
}
|
|
||||||
else if (!sc_adapter[card]->nphystat && sc_adapter[card]->phystat) { /* All is not well */
|
|
||||||
pr_debug("PhyStat transition to STOP\n");
|
|
||||||
pr_info("%s: Switch connection lost, transmitter disabled\n",
|
|
||||||
sc_adapter[card]->devicename);
|
|
||||||
|
|
||||||
indicate_status(card, ISDN_STAT_STOP, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_adapter[card]->phystat = sc_adapter[card]->nphystat;
|
|
||||||
|
|
||||||
/* Reinitialize the timer */
|
|
||||||
spin_lock_irqsave(&sc_adapter[card]->lock, flags);
|
|
||||||
mod_timer(&sc_adapter[card]->stat_timer, jiffies + CHECKSTAT_TIME);
|
|
||||||
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
|
|
||||||
|
|
||||||
/* Send a new cePhyStatus message */
|
|
||||||
sendmessage(card, CEPID, ceReqTypePhy, ceReqClass2,
|
|
||||||
ceReqPhyStatus, 0, 0, NULL);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user