Start of new driver V2.

This commit is contained in:
Armin Schindler 2000-04-02 21:56:34 +00:00
parent c86c3637cb
commit 390db3a46d
37 changed files with 9156 additions and 2179 deletions

View File

@ -0,0 +1,171 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.15
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/fs.h>
#undef N_DATA
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <errno.h>
#include "adapter.h"
#include "uxio.h"
#ifdef MODULE
#include "idi.h"
void EtdM_DIDD_Write(DESCRIPTOR *, int);
EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Read);
EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Write);
EXPORT_SYMBOL_NOVERS(DivasPrintf);
#define Divas_init init_module
#endif
extern char *file_check(void);
int DivasCardsDiscover(void);
int
Divas_init(void)
{
printk(KERN_DEBUG "DIVA Server Driver - initialising\n");
printk(KERN_DEBUG "DIVA Server Driver - Version 2.00 (%s)\n",file_check());
#if !defined(CONFIG_PCI)
printk(KERN_WARNING "CONFIG_PCI is not defined!\n");
return -ENODEV;
#endif
if (pci_present())
{
if (DivasCardsDiscover() < 0)
{
printk(KERN_WARNING "Divas: Not loaded\n");
return -ENODEV;
}
}
else
{
printk(KERN_WARNING "Divas: No PCI bus present\n");
return -ENODEV;
}
return 0;
}
#ifdef MODULE
void
cleanup_module(void)
{
card_t *pCard;
word wCardIndex;
extern int Divas_major;
printk(KERN_DEBUG "DIVA Server Driver - unloading\n");
pCard = DivasCards;
for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
{
if ((pCard->hw) && (pCard->hw->in_use))
{
(*pCard->card_reset)(pCard);
UxIsrRemove(pCard->hw, pCard);
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
if(pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
{
release_region(pCard->hw->io_base,0x20);
release_region(pCard->hw->reset_base,0x80);
}
// If this is a 4BRI ...
if (pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
{
// Skip over the next 3 virtual adapters
wCardIndex += 3;
// But free their handles
pCard++;
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
pCard++;
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
pCard++;
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
}
}
pCard++;
}
unregister_chrdev(Divas_major, "Divas");
}
void mod_inc_use_count(void)
{
MOD_INC_USE_COUNT;
}
void mod_dec_use_count(void)
{
MOD_DEC_USE_COUNT;
}
#else
Divas_setup(char *str, int *ints)
{
}
#endif

View File

@ -1,8 +1,38 @@
L_OBJS :=
M_OBJS :=
O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
LX_OBJS :=
MX_OBJS :=
O_OBJS :=
OX_OBJS :=
L_TARGET :=
O_TARGET :=
ifeq ($(CONFIG_ISDN_DRV_EICON_STANDALONE),y)
ifeq ($(CONFIG_PCI),y)
O_OBJS += common.o idi.o bri.o pri.o log.o xlog.o kprintf.o fpga.o fourbri.o
O_OBJS += lincfg.o linchr.o linsys.o linio.o
O_OBJS += fcheck.o
OX_OBJS += Divas_mod.o
endif
else
OX_OBJS += eicon_mod.o
O_OBJS := eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
O_OBJS += linio.o
O_OBJS += fcheck.o
ifeq ($(CONFIG_PCI),y)
ifeq ($(CONFIG_ISDN_DRV_EICON_PCI),y)
O_OBJS += common.o idi.o bri.o pri.o log.o xlog.o kprintf.o fpga.o fourbri.o
O_OBJS += lincfg.o linchr.o linsys.o
endif
endif
endif
O_TARGET :=
ifeq ($(CONFIG_ISDN_DRV_EICON),y)
O_TARGET += eicon.o
else
@ -10,4 +40,14 @@ else
M_OBJS = eicon.o
endif
include $(TOPDIR)/Rules.make
MD5FILES += common.c idi.c bri.c pri.c log.c xlog.c kprintf.c fpga.c \
fourbri.c fcheck.c
FCHECK = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
fcheck.o: $(MD5FILES)
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D FILECHECK=$(FCHECK) -c -o fcheck.o fcheck.c

View File

@ -0,0 +1,262 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.4
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* Main internal include file for Diva Server driver */
#if !defined(ADAPTER_H)
#define ADAPTER_H
#include "sys.h"
#include "idi.h"
#include "divas.h"
#undef ID_MASK
#include "pc.h"
#define XMOREC 0x1f
#define XMOREF 0x20
#define XBUSY 0x40
#define RMORE 0x80
/* buffer definition */
#if 0
typedef struct {
word length; /* length of data/parameter field */
byte P[270]; /* data/parameter field */
} PBUFFER;
#endif
/* structure for all information we have to keep on a per */
/* adapater basis */
typedef struct adapter_s ADAPTER;
struct adapter_s {
void * io;
byte IdTable[256];
byte ReadyInt;
byte (* ram_in)(ADAPTER * a, void * adr);
word (* ram_inw)(ADAPTER * a, void * adr);
void (* ram_in_buffer)(ADAPTER * a, void * adr, void * P, word length);
void (* ram_look_ahead)(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e);
void (* ram_out)(ADAPTER * a, void * adr, byte data);
void (* ram_outw)(ADAPTER * a, void * adr, word data);
void (* ram_out_buffer)(ADAPTER * a, void * adr, void * P, word length);
void (* ram_inc)(ADAPTER * a, void * adr);
};
typedef struct card card_t;
typedef int card_load_fn_t(card_t *card, dia_load_t *load);
typedef int card_config_fn_t(card_t *card, dia_config_t *config);
typedef int card_start_fn_t(card_t *card, byte *channels);
typedef int card_reset_fn_t(card_t *card);
typedef int card_mem_get_fn_t(card_t *card, mem_block_t *mem_block);
#define MAX_PENTITIES 256 /* Number of entities primary adapter */
#define MAX_ENTITIES 16 /* Number of entities standard adapter */
typedef struct e_info_s E_INFO;
struct e_info_s
{
ENTITY *e; /* entity pointer */
byte next; /* chaining index */
word assign_ref; /* assign reference */
};
/* DIVA card info (details hidden from user) */
typedef struct ux_diva_card_s ux_diva_card_t;
/* card info */
struct card
{
ADAPTER a; /* per-adapter information */
dia_card_t cfg; /* card configuration */
int state; /* State of the adapter */
dword serial_no; /* serial number */
int test_int_pend; /* set for interrupt testing */
int int_pend; /* interrupt pending */
ux_diva_card_t *hw; /* O/S-specific handle */
card_reset_fn_t *card_reset; /* call this to reset card */
card_load_fn_t *card_load; /* call this to load card */
card_config_fn_t *card_config; /* call this to config card */
card_start_fn_t *card_start; /* call this to start card */
card_mem_get_fn_t *card_mem_get; /* call this to get card memory */
E_INFO *e_tbl; /* table of ENTITY pointers */
byte e_head; /* list of active ENTITIES */
byte e_tail; /* list of active ENTITIES */
int e_count; /* # of active ENTITIES */
int e_max; /* total # of ENTITIES */
byte assign; /* assign queue entry */
PBUFFER RBuffer; /* Copy of receive lookahead buffer */
int log_types; /* bit-mask of active logs */
word xlog_offset; /* offset to XLOG buffer on card */
void (*out)(ADAPTER *a);
byte (*dpc)(ADAPTER * a);
byte (*test_int)(ADAPTER * a);
void (*clear_int)(ADAPTER * a);
void (*reset_int)(card_t *c);
} ;
/* card information */
#define MAX_CARDS 20 /* max number of cards on a system */
extern
card_t DivasCards[];
extern
int DivasCardNext;
extern
dia_config_t DivasCardConfigs[];
extern
byte DivasFlavourConfig[];
/*------------------------------------------------------------------*/
/* public functions of IDI common code */
/*------------------------------------------------------------------*/
void DivasOut(ADAPTER * a);
byte DivasDpc(ADAPTER * a);
byte DivasTestInt(ADAPTER * a);
void DivasClearInt(ADAPTER * a);
/*------------------------------------------------------------------*/
/* public functions of configuration platform-specific code */
/*------------------------------------------------------------------*/
int DivasConfigGet(dia_card_t *card);
/*------------------------------------------------------------------*/
/* public functions of LOG related code */
/*------------------------------------------------------------------*/
void DivasXlogReq(int card_num);
int DivasXlogRetrieve(card_t *card);
void DivasLog(dia_log_t *log);
void DivasLogIdi(card_t *card, ENTITY *e, int request);
/*------------------------------------------------------------------*/
/* public functions to initialise cards for each type supported */
/*------------------------------------------------------------------*/
int DivasPriInit(card_t *card, dia_card_t *cfg);
int DivasBriInit(card_t *card, dia_card_t *cfg);
int Divas4BriInit(card_t *card, dia_card_t *cfg);
void DivasBriPatch(card_t *card);
/*------------------------------------------------------------------*/
/* public functions of log common code */
/*------------------------------------------------------------------*/
extern char *DivasLogFifoRead(void);
extern void DivasLogFifoWrite(char *entry, int length);
extern int DivasLogFifoEmpty(void);
extern int DivasLogFifoFull(void);
extern void DivasLogAdd(void *buffer, int length);
/*------------------------------------------------------------------*/
/* public functions of misc. platform-specific code */
/*------------------------------------------------------------------*/
int DivasDpcSchedule(void);
void DivasDoDpc(void *);
/* table of IDI request functions */
extern
IDI_CALL DivasIdiRequest[];
/*
* intialisation entry point
*/
int DivasInit(void);
/*
* Get information on the number and type of cards present
*/
extern
int DivasCardsDiscover(void);
/*
* initialise a new card
*/
int DivasCardNew(dia_card_t *card);
/*
* configure specified card
*/
int DivasCardConfig(dia_config_t *config);
/*
* load specified binary code onto card
*/
int DivasCardLoad(dia_load_t *load);
/*
* start specified card running
*/
int DivasCardStart(int card_id);
/*
* ISR for card
* Returns 0 if specified card was interrupting
*/
int DivasIsr(void *arg);
/*
* Get number of active cards
*/
int DivasGetNum(void);
/*
* Get list of active cards
*/
int DivasGetList(dia_card_list_t *card_list);
/* definitions common to several card types */
#define DIVAS_SHARED_OFFSET (0x1000)
#endif /* ADAPTER_H */

681
drivers/isdn/eicon/bri.c Normal file
View File

@ -0,0 +1,681 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.5
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <sys/types.h>
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "adapter.h"
#include "uxio.h"
#define PCI_COMMAND 0x04
#define PCI_STATUS 0x06
#define PCI_LATENCY 0x0D
#define PCI_BADDR0 0x10
#define PCI_BADDR1 0x14
#define PCI_BADDR2 0x18
#define DIVAS_SIGNATURE 0x4447
/* offset to start of MAINT area (used by xlog) */
#define DIVAS_MAINT_OFFSET 0xff00 /* value for BRI card */
#define PROTCAP_TELINDUS 0x1
#define PROTCAP_V90D 0x8
word GetProtFeatureValue(char *sw_id);
byte io_in(ADAPTER *a, void *adr);
word io_inw(ADAPTER *a, void *adr);
void io_in_buffer(ADAPTER *a, void *adr, void *P, word length);
void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
void io_out(ADAPTER *a, void *adr, byte data);
void io_outw(ADAPTER *a, void *adr, word data);
void io_out_buffer(ADAPTER *a, void *adr, void *P, word length);
void io_inc(ADAPTER *a, void *adr);
static int diva_server_bri_test_int(card_t *card);
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
#define REG_DATA 0x00
#define REG_ADDRLO 0x04
#define REG_ADDRHI 0x0C
#define REG_IOCTRL 0x10
byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
int DivasBRIInitPCI(card_t *card, dia_card_t *cfg);
static
int diva_server_bri_reset(card_t *card)
{
byte *DivasIOBase;
word i;
dword dwWait;
UxCardLog(0);
DPRINTF(("divas: resetting BRI adapter"));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0);
for (i=0; i < 50000; i++)
;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x0000);
for (i=0; i<0x8000; i++)
{
UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
}
for (dwWait=0; dwWait < 0x00FFFFFF; dwWait++)
;
UxCardMemDetach(card->hw, DivasIOBase);
return 0;
}
static
void diva_server_bri_reset_int(card_t *card)
{
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
static
int diva_server_bri_start(card_t *card, byte *channels)
{
byte *DivasIOBase, *PLXIOBase;
word wSig, i;
dword dwSerialNum;
byte bPLX9060 = FALSE;
DPRINTF(("divas: starting Diva Server BRI card"));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
/* wait for signature to indicate card has started */
for (i = 0; i < 300; i++)
{
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
wSig = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
if (wSig == DIVAS_SIGNATURE)
{
DPRINTF(("divas: card started after %d ms", i * 10));
break;
}
UxPause(10);
}
if (wSig != DIVAS_SIGNATURE)
{
DPRINTF(("divas: card failed to start (Sig=0x%x)", wSig));
UxCardMemDetach(card->hw, DivasIOBase);
return -1;
}
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x3F6);
*channels = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
UxCardMemDetach(card->hw, DivasIOBase);
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) | UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
if (bPLX9060)
{
dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x1E) << 16) |
(UxCardPortIoInW(card->hw, PLXIOBase, 0x22));
DPRINTF(("divas: PLX9060 in use. Serial number 0x%04X", dwSerialNum));
}
else
{
dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x22) << 16) |
(UxCardPortIoInW(card->hw, PLXIOBase, 0x26));
DPRINTF(("divas: PLX9050 in use. Serial number 0x%04X", dwSerialNum));
}
UxCardMemDetach(card->hw, PLXIOBase);
card->serial_no = dwSerialNum;
diva_server_bri_test_int(card);
return 0;
}
static
int diva_server_bri_load(card_t *card, dia_load_t *load)
{
byte *DivasIOBase;
dword r3000_base;
dword dwAddr, dwLength, i;
word wTest, aWord;
DPRINTF(("divas: loading Diva Server BRI card"));
switch (load->code_type)
{
case DIA_CPU_CODE:
DPRINTF(("divas: loading RISC %s", &load->code[0x80]));
card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
DPRINTF(("divas: features 0x%x", card->hw->features));
if (card->hw->features == 0xFFFF)
{
DPRINTF(("divas: invalid feature string failed load\n"));
return -1;
}
r3000_base = 0;
break;
case DIA_DSP_CODE:
DPRINTF(("divas: DSP code \"%s\"", load->code));
if ((card->hw->features) && (!(card->hw->features & PROTCAP_TELINDUS)))
{
DPRINTF(("divas: only Telindus style binaries supported"));
return -1;
}
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
DPRINTF(("divas: V.90 DSP binary"));
r3000_base = (0xBF790000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
}
else
{
DPRINTF(("divas: non-V.90 DSP binary"));
r3000_base = (0xBF7A0000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
}
DPRINTF(("divas: loading at 0x%x", r3000_base));
break;
case DIA_TABLE_CODE:
DPRINTF(("divas: TABLE code"));
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
r3000_base = 0xBF790000 + sizeof(dword);
}
else
{
r3000_base = 0xBF7A0000 + sizeof(dword);
}
break;
case DIA_DLOAD_CNT:
DPRINTF(("divas: COUNT code"));
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
r3000_base = 0xBF790000;
}
else
{
r3000_base = 0xBF7A0000;
}
break;
default:
DPRINTF(("divas: unknown code type %d", load->code_type));
return -1;
break;
}
DPRINTF(("divas: Writing %d bytes to adapter, address 0x%x", load->length, r3000_base));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardLog(1);
dwLength = load->length;
for (i=0; i < dwLength; i++)
{
dwAddr = r3000_base + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, load->code[i]);
}
DPRINTF(("divas: Verifying"));
for (i=0; i<dwLength; i++)
{
dwAddr = r3000_base + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
wTest = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
aWord = load->code[i];
if (wTest != aWord)
{
DPRINTF(("divas: load verify failed on byte %d", i));
DPRINTF(("divas: RAM 0x%x File 0x%x",wTest,aWord));
UxCardMemDetach(card->hw, DivasIOBase);
return -1;
}
}
DPRINTF(("divas: Loaded and verified. Detaching from adapter"));
UxCardMemDetach(card->hw, DivasIOBase);
UxCardLog(0);
return 0;
}
static
int diva_server_bri_config(card_t *card, dia_config_t *config)
{
byte *DivasIOBase, i;
DPRINTF(("divas: configuring Diva Server BRI card"));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 8);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->tei);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 9);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->nt2);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 10);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 11);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->watchdog);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 12);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->permanent);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 13);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 14);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->stable_l2);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 15);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->no_order_check);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 16);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 17);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 18);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->low_channel);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 19);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->prot_version);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 20);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->crc4);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 21);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
DPRINTF(("divas: Signifying V.90"));
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 4);
}
else
{
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
}
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 23);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, card->serial_no & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 24);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 8) & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 25);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 16) & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 26);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 21);
for (i=0; i<32; i++)
{
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 32+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].oad[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 64+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].osa[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 96+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].spid[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 128+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].oad[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 160+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].osa[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 192+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].spid[i]);
}
UxCardMemDetach(card->hw, DivasIOBase);
return 0;
}
void DivasBriPatch(card_t *card)
{
dword PLXIOBase = 0;
dword DivasIOBase = 0;
PLXIOBase = card->cfg.reset_base;
DivasIOBase = card->cfg.io_base;
if (PLXIOBase == 0)
{
DPRINTF(("Divas: BRI (PLX chip) cannot be patched. The BRI adapter may"));
DPRINTF(("Divas: not function properly. If you do encounter problems,"));
DPRINTF(("Divas: ensure that your machine is using the latest BIOS."));
return;
}
DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
if (PLXIOBase & 0x80)
{
dword dwSize, dwSerialNum, dwCmd;
boolean_t bPLX9060;
word wSerHi, wSerLo;
DPRINTF(("Divas: Patch required"));
dwCmd = 0;
UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
PLXIOBase &= ~0x80;
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &PLXIOBase);
dwSize = 0xFFFFFFFF;
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &dwSize);
UxPciConfigRead(card->hw, 4, PCI_BADDR1, &dwSize);
dwSize = (~ (dwSize & ~7)) + 1;
DivasIOBase = PLXIOBase + dwSize;
card->cfg.reset_base = PLXIOBase;
card->cfg.io_base = DivasIOBase;
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &card->cfg.reset_base);
UxPciConfigWrite(card->hw, 4, PCI_BADDR2, &card->cfg.io_base);
dwCmd = 5;
UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
UxCardLog(1);
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) |
UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
if (bPLX9060)
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
dwSerialNum = (wSerHi << 16) | wSerLo;
UxCardLog(0);
}
else
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
dwSerialNum = (wSerHi << 16) | wSerLo;
UxCardLog(0);
}
}
else
{
word wSerHi, wSerLo;
boolean_t bPLX9060;
dword dwSerialNum;
DPRINTF(("divas: No patch required"));
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) |
UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
if (bPLX9060)
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
dwSerialNum = (wSerHi << 16) | wSerLo;
}
else
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
dwSerialNum = (wSerHi << 16) | wSerLo;
}
}
DPRINTF(("Divas: After patching:"));
DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
}
#define TEST_INT_DIVAS_BRI 0x12
static
int diva_server_bri_test_int(card_t *card)
{
boolean_t bPLX9060 = FALSE;
byte *PLXIOBase = NULL, *DivasIOBase = NULL;
DPRINTF(("divas: test interrupt for Diva Server BRI card"));
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) || UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
if (bPLX9060)
{ /* PLX9060 */
UxCardPortIoOut(card->hw, PLXIOBase, 0x69, 0x09);
}
else
{ /* PLX9050 */
UxCardPortIoOut(card->hw, PLXIOBase, 0x4C, 0x41);
}
card->test_int_pend = TEST_INT_DIVAS_BRI;
UxCardMemDetach(card->hw, PLXIOBase);
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x89);
UxCardMemDetach(card->hw, DivasIOBase);
return 0;
}
static
int diva_server_bri_mem_get(card_t *card, mem_block_t *mem_block)
{
dword user_addr = mem_block->addr;
word length = 0;
dword addr;
word i;
byte *DivasIOBase;
DPRINTF(("divas: Retrieving memory from 0x%x", user_addr));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
addr = user_addr;
for (i=0; i < (16 * 8); i++)
{
addr = user_addr + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, addr >> 16);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, (word) addr);
mem_block->data[i] = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
length++;
}
UxCardMemDetach(card->hw, DivasIOBase);
return length;
}
int DivasBriInit(card_t *card, dia_card_t *cfg)
{
DPRINTF(("divas: initialise Diva Server BRI card"));
if (DivasBRIInitPCI(card, cfg) == -1)
{
return -1;
}
card->card_reset = diva_server_bri_reset;
card->card_start = diva_server_bri_start;
card->card_load = diva_server_bri_load;
card->card_config = diva_server_bri_config;
card->reset_int = diva_server_bri_reset_int;
card->card_mem_get = diva_server_bri_mem_get;
card->xlog_offset = DIVAS_MAINT_OFFSET;
card->out = DivasOut;
card->test_int = DivasTestInt;
card->dpc = DivasDpc;
card->clear_int = DivasClearInt;
card->a.ram_out = io_out;
card->a.ram_outw = io_outw;
card->a.ram_out_buffer = io_out_buffer;
card->a.ram_inc = io_inc;
card->a.ram_in = io_in;
card->a.ram_inw = io_inw;
card->a.ram_in_buffer = io_in_buffer;
card->a.ram_look_ahead = io_look_ahead;
return 0;
}
word GetProtFeatureValue(char *sw_id)
{
word features = 0;
while ((*sw_id) && (sw_id[0] != '['))
sw_id++;
if (sw_id == NULL)
{
DPRINTF(("divas: no feature string present"));
features = -1;
}
else
{
byte i, shifter;
sw_id += 3;
for (i=0, shifter=12; i<4; i++, shifter-=4)
{
if ((sw_id[i] >= '0') && (sw_id[i] <= '9'))
{
features |= (sw_id[i] - '0') << shifter;
}
else if ((sw_id[i] >= 'a') && (sw_id[i] <= 'f'))
{
features |= (sw_id[i] - 'a' + 10) << shifter;
}
else if ((sw_id[i] >= 'A') && (sw_id[i] <= 'F'))
{
features |= (sw_id[i] - 'A' + 10) << shifter;
}
else
{
DPRINTF(("divas: invalid feature string"));
return -1;
}
}
}
return features;
}

870
drivers/isdn/eicon/common.c Normal file
View File

@ -0,0 +1,870 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.11
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "sys.h"
#include "idi.h"
#include "constant.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "uxio.h"
#include <sys/types.h>
#define MAX_ADDR_LEN
#define DIVAS_LOAD_CMD 0x02
#define DIVAS_START_CMD 0x03
#define DIVAS_IRQ_RESET 0xC18
#define DIVAS_IRQ_RESET_VAL 0xFE
#define PCI_COMMAND 0x04
#define PCI_STATUS 0x06
#define PCI_LATENCY 0x0D
#define PCI_INTERRUPT 0x3C
#define TEST_INT_DIVAS 0x11
#define TEST_INT_DIVAS_BRI 0x12
#define TEST_INT_DIVAS_Q 0x13
#define DIVAS_RESET 0x81
#define DIVAS_LED1 0x04
#define DIVAS_LED2 0x08
#define DIVAS_LED3 0x20
#define DIVAS_LED4 0x40
#define DIVAS_SIGNATURE 0x4447
#define MP_PROTOCOL_ADDR 0xA0011000
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
typedef struct {
dword cmd;
dword addr;
dword len;
dword err;
dword live;
dword reserved[(0x1020>>2)-6];
dword signature;
byte data[1];
} diva_server_boot_t;
int DivasCardNext;
card_t DivasCards[MAX_CARDS];
dia_config_t *DivasConfig(card_t *, dia_config_t *);
static
DESCRIPTOR DIDD_Table[16];
static
int DIDD_Length = 0;
void EtdM_DIDD_Read( DESCRIPTOR *table, int *tablelength )
{
int table_size = sizeof(DIDD_Table);
bcopy((caddr_t)DIDD_Table, (caddr_t)table, table_size);
*tablelength = DIDD_Length;
return;
}
static
void EtdM_DIDD_Write(DESCRIPTOR *table, int tablelength)
{
int table_size = sizeof(DIDD_Table);
bcopy((caddr_t)table, (caddr_t)DIDD_Table, table_size);
DIDD_Length = tablelength;
return;
}
static
void init_idi_tab(void)
{
int length = 0;
DESCRIPTOR d[16];
EtdM_DIDD_Read(d, &length);
d[length].type = IDI_DIMAINT; /* identify the DIMAINT entry */
d[length].channels = 0; /* zero channels associated with dimaint*/
d[length].features = 0; /* no features associated with dimaint */
d[length].request = (IDI_CALL) DivasPrintf;
length++;
EtdM_DIDD_Write(d, length);
return;
}
/*
* I/O routines for memory mapped cards
*/
byte mem_in(ADAPTER *a, void *adr)
{
card_t *card = a->io;
unsigned char *b, *m;
byte value;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemIn(card->hw, m);
UxCardMemDetach(card->hw, b);
return value;
}
word mem_inw(ADAPTER *a, void *adr)
{
card_t *card = a->io;
unsigned char *b, *m;
word value;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemInW(card->hw, m);
UxCardMemDetach(card->hw, b);
return value;
}
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemInBuffer(card->hw, m, P, length);
UxCardMemDetach(card->hw, b);
return;
}
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (dword) &RBuffer->length;
card->RBuffer.length = UxCardMemInW(card->hw, m);
m = b;
m += (dword) &RBuffer->P;
UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
e->RBuffer = (DBUFFER *) &card->RBuffer;
UxCardMemDetach(card->hw, b);
return;
}
void mem_out(ADAPTER *a, void *adr, byte data)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOut(card->hw, m, data);
UxCardMemDetach(card->hw, b);
return;
}
void mem_outw(ADAPTER *a, void *adr, word data)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOutW(card->hw, m, data);
UxCardMemDetach(card->hw, b);
return;
}
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOutBuffer(card->hw, m, P, length);
UxCardMemDetach(card->hw, b);
return;
}
void mem_inc(ADAPTER *a, void *adr)
{
word value;
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemInW(card->hw, m);
value++;
UxCardMemOutW(card->hw, m, value);
UxCardMemDetach(card->hw, b);
return;
}
/*
* I/O routines for I/O mapped cards
*/
byte io_in(ADAPTER *a, void *adr)
{
card_t *card = a->io;
byte value;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoIn(card->hw, DivasIOBase, adr);
UxCardMemDetach(card->hw, DivasIOBase);
return value;
}
word io_inw(ADAPTER *a, void *adr)
{
card_t *card = a->io;
word value;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoInW(card->hw, DivasIOBase, adr);
UxCardMemDetach(card->hw, DivasIOBase);
return value;
}
void io_in_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
UxCardMemDetach(card->hw, DivasIOBase);
e->RBuffer = (DBUFFER *) &card->RBuffer;
return;
}
void io_out(ADAPTER *a, void *adr, byte data)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOut(card->hw, DivasIOBase, adr, data);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_outw(ADAPTER *a, void *adr, word data)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutW(card->hw, DivasIOBase, adr, data);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_out_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_inc(ADAPTER *a, void *adr)
{
word value;
card_t *card = a->io;
byte *DivasIOBase;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoInW(card->hw, DivasIOBase, adr);
value++;
UxCardIoOutW(card->hw, DivasIOBase, adr, value);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
static
void test_int(card_t *card)
{
byte *shared, *DivasIOBase;
switch (card->test_int_pend)
{
case TEST_INT_DIVAS:
DPRINTF(("divas: test interrupt pending"));
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
if (UxCardMemIn(card->hw, &shared[0x3FE]))
{
UxCardMemOut(card->hw,
&(((struct pr_ram *)shared)->RcOutput), 0);
UxCardMemDetach(card->hw, shared);
(*card->reset_int)(card);
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
UxCardMemOut(card->hw, &shared[0x3FE], 0);
DPRINTF(("divas: test interrupt cleared"));
}
UxCardMemDetach(card->hw, shared);
card->test_int_pend = 0;
break;
case TEST_INT_DIVAS_BRI:
DPRINTF(("divas: BRI test interrupt pending"));
(*card->reset_int)(card);
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0);
UxCardMemDetach(card->hw, DivasIOBase);
DPRINTF(("divas: test interrupt cleared"));
card->test_int_pend = 0;
break;
case TEST_INT_DIVAS_Q:
DPRINTF(("divas: 4BRI test interrupt pending"));
(*card->reset_int)(card);
card->test_int_pend = 0;
break;
default:
DPRINTF(("divas: unknown test interrupt pending"));
return;
}
return;
}
void card_isr (void *dev_id)
{
card_t *card = (card_t *) dev_id;
ADAPTER *a = &card->a;
if (card->test_int_pend)
{
test_int(card);
return;
}
if ((card->test_int)(a))
{
card->int_pend = TRUE;
DivasDpcSchedule();
(card->reset_int)(card);
}
return;
}
int DivasCardNew(dia_card_t *card_info)
{
card_t *card;
byte b;
static boolean_t first_call = TRUE;
boolean_t NeedISRandReset = FALSE;
DPRINTF(("divas: new card "));
if (first_call)
{
first_call = FALSE;
init_idi_tab();
}
DivasConfigGet(card_info);
if (DivasCardNext == DIM(DivasCards))
{
KDPRINTF((KERN_WARNING "Divas: no space available for new card"));
return -1;
}
card = &DivasCards[DivasCardNext];
card->state = DIA_UNKNOWN;
card->cfg = *card_info;
card->a.io = card;
if (UxCardHandleGet(&card->hw, card_info))
{
KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card"));
return -1;
}
if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
{
DivasBriPatch(card);
card_info->io_base = card->cfg.io_base;
}
switch (card_info->card_type)
{
case DIA_CARD_TYPE_DIVA_SERVER:
if (DivasPriInit(card, card_info))
{
return -1;
}
NeedISRandReset = TRUE;
break;
case DIA_CARD_TYPE_DIVA_SERVER_B:
if (DivasBriInit(card, card_info))
{
return -1;
}
NeedISRandReset = TRUE;
break;
case DIA_CARD_TYPE_DIVA_SERVER_Q:
if (Divas4BriInit(card, card_info))
{
return -1;
}
if (card_info->name[6] == '0')
{
NeedISRandReset = TRUE;
}
else // Need to set paramater for ISR anyway
{
card->hw->user_isr_arg = card;
card->hw->user_isr = card_isr;
}
break;
default:
KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type));
return -1;
}
if (NeedISRandReset)
{
if (UxIsrInstall(card->hw, card_isr, card))
{
KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq));
UxCardHandleFree(card->hw);
return -1;
}
b = card->cfg.irq;
UxPciConfigWrite(card->hw, sizeof(b), PCI_INTERRUPT, &b);
if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
{
if ((*card->card_reset)(card))
{
KDPRINTF((KERN_WARNING "Divas: Adapter reset failed"));
return -1;
}
card->state = DIA_RESET;
}
NeedISRandReset = FALSE;
}
DivasCardNext++;
return 0;
}
void *get_card(int card_id)
{
int i;
for (i=0; i < DivasCardNext; i++)
{
if (DivasCards[i].cfg.card_id == card_id)
{
return(&DivasCards[i]);
}
}
DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
return NULL;
}
int DivasCardConfig(dia_config_t *config)
{
card_t *card;
int status;
DPRINTF(("divas: configuring card"));
card = get_card(config->card_id);
if (!card)
{
return -1;
}
config = DivasConfig(card, config);
status = (*card->card_config)(card, config);
if (!status)
{
card->state = DIA_CONFIGURED;
}
return status;
}
int DivasCardLoad(dia_load_t *load)
{
card_t *card;
int status;
card = get_card(load->card_id);
if (!card)
{
return -1;
}
if (card->state == DIA_RUNNING)
{
(*card->card_reset)(card);
}
status = (*card->card_load)(card, load);
if (!status)
{
card->state = DIA_LOADED;
}
return status;
}
static int idi_register(card_t *card, byte channels)
{
DESCRIPTOR d[16];
int length, num_entities;
DPRINTF(("divas: registering card with IDI"));
num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES;
card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
if (!card->e_tbl)
{
KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available"));
return -1;
}
bzero(card->e_tbl, sizeof(E_INFO) * num_entities);
card->e_max = num_entities;
EtdM_DIDD_Read(d, &length);
if (length == DIM(d))
{
KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
return -1;
}
switch (card->cfg.card_type)
{
case DIA_CARD_TYPE_DIVA_SERVER:
d[length].type = IDI_ADAPTER_PR;
break;
case DIA_CARD_TYPE_DIVA_SERVER_B:
d[length].type = IDI_ADAPTER_MAESTRA;
break;
case DIA_CARD_TYPE_DIVA_SERVER_Q:
d[length].type = IDI_ADAPTER_MAESTRAQ;
}
d[length].features = 0;
d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
if ( card->hw->features & PROTCAP_MANIF )
{
d[length].features |= DI_MANAGE ;
}
if ( card->hw->features & PROTCAP_V_42 )
{
d[length].features |= DI_V_42 ;
}
if ( card->hw->features & PROTCAP_EXTD_FAX )
{
d[length].features |= DI_EXTD_FAX ;
}
d[length].channels = channels;
d[length].request = DivasIdiRequest[card - DivasCards];
length++;
EtdM_DIDD_Write(d, length);
return 0;
}
int DivasCardStart(int card_id)
{
card_t *card;
byte channels;
int status;
DPRINTF(("divas: starting card"));
card = get_card(card_id);
if (!card)
{
return -1;
}
status = (*card->card_start)(card, &channels);
if (status)
{
return status;
}
/* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
{
int i;
card_t *FourBRISlave;
for (i=3; i >= 0; i--)
{
FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */
if (FourBRISlave)
{
idi_register(FourBRISlave, 2);
FourBRISlave->state = DIA_RUNNING;
}
}
card->serial_no = card->cfg.serial;
DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels",
card_id - 3, card->serial_no, (int) channels));
}
else
{
status = idi_register(card, channels);
if (!status)
{
card->state = DIA_RUNNING;
DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels",
card_id, card->serial_no, (int) channels));
}
}
return status;
}
int DivasGetMem(mem_block_t *mem_block)
{
card_t *card;
word card_id = mem_block->card_id;
card = get_card(card_id);
if (!card)
{
return 0;
}
return (*card->card_mem_get)(card, mem_block);
}
/*
* Deleyed Procedure Call for handling interrupts from card
*/
void DivasDoDpc(void *pData)
{
int ipl, i;
card_t *card;
card = DivasCards;
for (i = 0; i < DivasCardNext; i++)
{
if (card->int_pend)
{
ipl = UxCardLock(card->hw);
(card->dpc)(&card->a);
(card->clear_int)(&card->a);
card->int_pend = FALSE;
UxCardUnlock(card->hw, ipl);
}
/* if XLOG active, use opportunity to poll card */
if (card->log_types & DIVAS_LOG_XLOG)
{
DivasXlogRetrieve(card);
}
card++;
}
return;
}
/*
* DivasGetNum
* Returns the number of active adapters
*/
int DivasGetNum(void)
{
return(DivasCardNext);
}
/*
* DivasGetList
* Returns a list of active adapters
*/
int DivasGetList(dia_card_list_t *card_list)
{
int i;
bzero(card_list, sizeof(dia_card_list_t));
for(i = 0; i < DivasCardNext; i++)
{
card_list->card_type = DivasCards[i].cfg.card_type;
card_list->card_slot = DivasCards[i].cfg.slot;
card_list->state = DivasCards[i].state;
card_list++;
}
return 0;
}
/*
* control logging for specified card
*/
void DivasLog(dia_log_t *log)
{
card_t *card;
card = get_card(log->card_id);
if (!card)
{
return;
}
card->log_types = log->log_types;
return;
}

View File

@ -0,0 +1,179 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*------------------------------------------------------------------*/
/* Q.931 information elements maximum length */
/* excluding the identifier, including the length field */
/*------------------------------------------------------------------*/
#define MAX_LEN_BC 13
#define MAX_LEN_LLC 19 /* ctr3 */
#define MAX_LEN_HLC 6 /* ctr3 */
#define MAX_LEN_UUI 200 /* Hicom USBS req */
#define MAX_LEN_NUM 24
#define MAX_LEN_DSP 83 /* ctr3 */
#define MAX_LEN_NI 4
#define MAX_LEN_PI 5
#define MAX_LEN_SIN 3
#define MAX_LEN_CST 4
#define MAX_LEN_SIG 2
#define MAX_LEN_SPID 32
#define MAX_LEN_EID 3
#define MAX_LEN_CHI 35 /* ctr3 */
#define MAX_LEN_CAU 33
#define MAX_LEN_FTY 130
#define MAX_LEN_KEY 83 /* ctr3 */
#define MAX_LEN_RSI 4
#define MAX_LEN_CAI 11
#define MAX_NUM_SPID 4
#define MAX_LEN_USERID 9
#define MAX_LEN_APPLID 5
#define MAX_LEN_NTTCIF 15
/*------------------------------------------------------------------*/
/* decision return values */
/*------------------------------------------------------------------*/
#define YES 1
#define NO 0
/*-------------------------------------------------------------------*/
/* w element coding */
/*-------------------------------------------------------------------*/
#define NTTCIF 0x01
#define BC 0x04
#define CAU 0x08
#define CAD 0x0c
#define CAI 0x10
#define CST 0x14
#define CHI 0x18
#define LLI 0x19
#define CHA 0x1a
#define FTY 0x1c
#define PI 0x1e
#define NFAC 0x20
#define TC 0x24
#define ATT_EID 0x26
#define NI 0x27
#define DSP 0x28
#define DT 0x29
#define KEY 0x2c
#define KP 0x2c
#define UID 0x2d
#define SIG 0x34
#define FI 0x39
#define SPID 0x3a
#define EID 0x3b
#define DSPF 0x3c
#define ECAD 0x4c
#define OAD 0x6c
#define OSA 0x6d
#define DAD 0x70
#define CPN 0x70
#define DSA 0x71
#define RDX 0x73
#define RAD 0x74
#define RDN 0x74
#define RSI 0x79
#define SCR 0x7A /* internal unscreened CPN */
#define MIE 0x7a /* internal management info element */
#define LLC 0x7c
#define HLC 0x7d
#define UUI 0x7e
#define ESC 0x7f
#define SHIFT 0x90
#define MORE 0xa0
#define CL 0xb0
/* information elements used on the spid interface */
#define SPID_CMD 0xc0
#define SPID_LINK 0x10
#define SPID_DN 0x70
#define SPID_BC 0x04
#define SPID_SWITCH 0x11
/*------------------------------------------------------------------*/
/* global configuration parameters, defined in exec.c */
/* these parameters are configured with program loading */
/*------------------------------------------------------------------*/
#define PROT_1TR6 0
#define PROT_ETSI 1
#define PROT_FRANC 2
#define PROT_BELG 3
#define PROT_SWED 4
#define PROT_NI 5
#define PROT_5ESS 6
#define PROT_JAPAN 7
#define PROT_ATEL 8
#define PROT_US 9
#define PROT_ITALY 10
#define PROT_TWAN 11
#define PROT_AUSTRAL 12
#define INIT_PROT_1TR6 0x80|PROT_1TR6
#define INIT_PROT_ETSI 0x80|PROT_ETSI
#define INIT_PROT_FRANC 0x80|PROT_FRANC
#define INIT_PROT_BELG 0x80|PROT_BELG
#define INIT_PROT_SWED 0x80|PROT_SWED
#define INIT_PROT_NI 0x80|PROT_NI
#define INIT_PROT_5ESS 0x80|PROT_5ESS
#define INIT_PROT_JAPAN 0x80|PROT_JAPAN
#define INIT_PROT_ATEL 0x80|PROT_ATEL
#define INIT_PROT_ITALY 0x80|PROT_ITALY
#define INIT_PROT_TWAN 0x80|PROT_TWAN
#define INIT_PROT_AUSTRAL 0x80|PROT_AUSTRAL
/* -----------------------------------------------------------**
** The PROTOCOL_FEATURE_STRING in feature.h (included **
** in prstart.sx and astart.sx) defines capabilities and **
** features of the actual protocol code. It's used as a bit **
** mask. **
** The following Bits are defined: **
** -----------------------------------------------------------*/
#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */
#define PROTCAP_MANIF 0x0002 /* Management interface implemented */
#define PROTCAP_V_42 0x0004 /* V42 implemented */
#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */
#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */
#define PROTCAP_FREE4 0x0020 /* not used */
#define PROTCAP_FREE5 0x0040 /* not used */
#define PROTCAP_FREE6 0x0080 /* not used */
#define PROTCAP_FREE7 0x0100 /* not used */
#define PROTCAP_FREE8 0x0200 /* not used */
#define PROTCAP_FREE9 0x0400 /* not used */
#define PROTCAP_FREE10 0x0800 /* not used */
#define PROTCAP_FREE11 0x1000 /* not used */
#define PROTCAP_FREE12 0x2000 /* not used */
#define PROTCAP_FREE13 0x4000 /* not used */
#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */

View File

@ -0,0 +1,57 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Include file for defining the kernel loggger messages
* These definitions are shared between the klog driver and the
* klogd daemon process
*/
#if !defined(_KLOGMSG_H)
#define _KLOGMSG_H
/* define a type for a log entry */
#define KLOG_TEXT_MSG (0)
#define KLOG_XLOG_MSG (1)
#define KLOG_XTXT_MSG (2)
#define KLOG_IDI_REQ (4)
#define KLOG_IDI_CALLBACK (5)
#define KLOG_CAPI_MSG (6)
typedef struct
{
unsigned long time_stamp; /* in ms since last system boot */
int card; /* card number (-1 for all) */
unsigned int type; /* type of log message (0 is text) */
unsigned int length; /* message length (non-text messages only) */
unsigned short code; /* message code (non-text messages only) */
char buffer[110];/* text/data to log */
} klog_t;
void DivasLogAdd(void *buffer, int length);
#endif /* of _KLOGMSG_H */

232
drivers/isdn/eicon/divas.h Normal file
View File

@ -0,0 +1,232 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.5
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* External Diva Server driver include file */
#if !defined(DIVAS_H)
#define DIVAS_H
#include "sys.h"
/* IOCTL commands */
#define DIA_IOCTL_INIT (0)
#define DIA_IOCTL_LOAD (1)
#define DIA_IOCTL_CONFIG (2)
#define DIA_IOCTL_START (3)
#define DIA_IOCTL_GET_NUM (4)
#define DIA_IOCTL_GET_LIST (5)
#define DIA_IOCTL_LOG (6)
#define DIA_IOCTL_DETECT (7)
#define DIA_IOCTL_SPACE (8)
#define DIA_IOCTL_GET_MEM (9)
#define DIA_IOCTL_FLAVOUR (10)
#define DIA_IOCTL_XLOG_REQ (11)
/* Error codes */
#define XLOG_ERR_CARD_NUM (13)
#define XLOG_ERR_DONE (14)
#define XLOG_ERR_CMD (15)
#define XLOG_ERR_TIMEOUT (16)
#define XLOG_ERR_CARD_STATE (17)
#define XLOG_ERR_UNKNOWN (18)
#define XLOG_OK (0)
/* Adapter states */
#define DIA_UNKNOWN (0)
#define DIA_RESET (1)
#define DIA_LOADED (2)
#define DIA_CONFIGURED (3)
#define DIA_RUNNING (4)
/* Stucture for getting card specific information from active cad driver */
typedef struct
{
int card_type;
int card_slot;
int state;
} dia_card_list_t;
/* use following to select which logging to have active */
#define DIVAS_LOG_DEBUG (1 << 0)
#define DIVAS_LOG_XLOG (1 << 1)
#define DIVAS_LOG_IDI (1 << 2)
#define DIVAS_LOG_CAPI (1 << 3)
/* stucture for DIA_IOCTL_LOG to get information from adapter */
typedef struct
{
int card_id;
int log_types; /* bit mask of log types: use DIVAS_LOG_XXX */
} dia_log_t;
/* list of cards supported by this driver */
#define DIA_CARD_TYPE_DIVA_SERVER (0) /* Diva Server PRI */
#define DIA_CARD_TYPE_DIVA_SERVER_B (1) /* Diva Server BRI */
#define DIA_CARD_TYPE_DIVA_SERVER_Q (2) /* Diva Server 4-BRI */
/* bus types */
#define DIA_BUS_TYPE_ISA (0)
#define DIA_BUS_TYPE_ISA_PNP (1)
#define DIA_BUS_TYPE_PCI (2)
#define DIA_BUS_TYPE_MCA (3)
/* types of memory used (index for memory array below) */
#define DIVAS_RAM_MEMORY 0
#define DIVAS_REG_MEMORY 1
#define DIVAS_CFG_MEMORY 2
#define DIVAS_SHARED_MEMORY 3
#define DIVAS_CTL_MEMORY 4
/*
* card config information
* passed as parameter to DIA_IOCTL_INIT ioctl to initialise new card
*/
typedef struct
{
int card_id; /* unique id assigned to this card */
int card_type; /* use DIA_CARD_TYPE_xxx above */
int bus_type; /* use DIA_BUS_TYPE_xxx above */
int bus_num; /* bus number (instance number of bus type) */
int func_num; /* adapter function number (PCI register) */
int slot; /* slot number in bus */
unsigned char irq; /* IRQ number */
int reset_base; /* Reset register for I/O mapped cards */
int io_base; /* I/O base for I/O mapped cards */
void *memory[5]; /* memory base addresses for memory mapped cards */
char name[9]; /* name of adapter */
int serial; /* serial number */
unsigned char int_priority; /* Interrupt priority */
} dia_card_t;
/*
* protocol configuration information
* passed as parameter to DIA_IOCTL_CONFIG ioctl to configure card
*/
typedef struct
{
int card_id; /* to identify particular card */
unsigned char tei;
unsigned char nt2;
unsigned char watchdog;
unsigned char permanent;
unsigned char x_interface;
unsigned char stable_l2;
unsigned char no_order_check;
unsigned char handset_type;
unsigned char sig_flags;
unsigned char low_channel;
unsigned char prot_version;
unsigned char crc4;
struct
{
unsigned char oad[32];
unsigned char osa[32];
unsigned char spid[32];
}terminal[2];
} dia_config_t;
/*
* code configuration
* passed as parameter to DIA_IOCTL_LOAD ioctl
* one of these ioctl per code file to load
*/
typedef struct
{
int card_id; /* card to load */
enum
{
DIA_CPU_CODE, /* CPU code */
DIA_DSP_CODE, /* DSP code */
DIA_CONT_CODE, /* continuation of code */
DIA_TABLE_CODE, /* code table */
DIA_DLOAD_CNT, /* number of downloads*/
DIA_FPGA_CODE
} code_type; /* code for CPU or DSP ? */
int length; /* length of code */
unsigned char *code; /* pointer (in user-space) to code */
} dia_load_t;
/*
* start configuration
* passed as parameter to DIA_IOCTL_START ioctl
*/
typedef struct
{
int card_id; /* card to start */
} dia_start_t;
/* used for retrieving memory from the card */
typedef struct {
word card_id;
dword addr;
byte data[16 * 8];
} mem_block_t;
/* DIVA Server specific addresses */
#define DIVAS_CPU_START_ADDR (0x0)
#define ORG_MAX_PROTOCOL_CODE_SIZE 0x000A0000
#define ORG_MAX_DSP_CODE_SIZE (0x000F0000 - ORG_MAX_PROTOCOL_CODE_SIZE)
#define ORG_DSP_CODE_BASE (0xBF7F0000 - ORG_MAX_DSP_CODE_SIZE)
#define DIVAS_DSP_START_ADDR (0xBF7A0000)
#define DIVAS_SHARED_OFFSET (0x1000)
#define MP_DSP_CODE_BASE 0xa03a0000
#define MQ_PROTCODE_OFFSET 0x100000
#define MQ_SM_OFFSET 0X0f0000
#define V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000
#define V90D_MAX_DSP_CODE_SIZE (0x000F0000 - V90D_MAX_PROTOCOL_CODE_SIZE)
#define V90D_DSP_CODE_BASE (0xBF7F0000 - V90D_MAX_DSP_CODE_SIZE)
#define MQ_ORG_MAX_PROTOCOL_CODE_SIZE 0x000a0000 /* max 640K Protocol-Code */
#define MQ_ORG_MAX_DSP_CODE_SIZE 0x00050000 /* max 320K DSP-Code */
#define MQ_ORG_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
- MQ_ORG_MAX_DSP_CODE_SIZE)
#define MQ_V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000 /* max 576K Protocol-Code */
#define MQ_V90D_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code if V.90D included */
#define MQ_MAX_DSP_DOWNLOAD_ADDR 0xa03f0000
#define MQ_V90D_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
- MQ_V90D_MAX_DSP_CODE_SIZE)
#define ALIGNMENT_MASK_MAESTRA 0xfffffffc
#endif /* DIVAS_H */

View File

@ -0,0 +1,303 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef DSP_DEFS_H_
#define DSP_DEFS_H_
#ifndef DSPDIDS_H_
#include "dspdids.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
#ifndef NULL
#define NULL 0
#endif
#ifndef TRUE
#define TRUE (0 == 0)
#endif
#ifndef FALSE
#define FALSE (0 != 0)
#endif
/*---------------------------------------------------------------------------*/
#define DSP_MEMORY_TYPE_EXTERNAL_DM 0
#define DSP_MEMORY_TYPE_EXTERNAL_PM 1
#define DSP_MEMORY_TYPE_INTERNAL_DM 2
#define DSP_MEMORY_TYPE_INTERNAL_PM 3
#define DSP_DOWNLOAD_FLAG_BOOTABLE 0x0001
#define DSP_DOWNLOAD_FLAG_2181 0x0002
#define DSP_DOWNLOAD_FLAG_TIMECRITICAL 0x0004
#define DSP_DOWNLOAD_FLAG_COMPAND 0x0008
#define DSP_MEMORY_BLOCK_COUNT 16
#define DSP_SEGMENT_PM_FLAG 0x0001
#define DSP_SEGMENT_SHARED_FLAG 0x0002
#define DSP_SEGMENT_EXTERNAL_DM DSP_MEMORY_TYPE_EXTERNAL_DM
#define DSP_SEGMENT_EXTERNAL_PM DSP_MEMORY_TYPE_EXTERNAL_PM
#define DSP_SEGMENT_INTERNAL_DM DSP_MEMORY_TYPE_INTERNAL_DM
#define DSP_SEGMENT_INTERNAL_PM DSP_MEMORY_TYPE_INTERNAL_PM
#define DSP_SEGMENT_FIRST_RELOCATABLE 4
#define DSP_DATA_BLOCK_PM_FLAG 0x0001
#define DSP_DATA_BLOCK_DWORD_FLAG 0x0002
#define DSP_DATA_BLOCK_RESOLVE_FLAG 0x0004
#define DSP_RELOC_NONE 0x00
#define DSP_RELOC_SEGMENT_MASK 0x3f
#define DSP_RELOC_TYPE_MASK 0xc0
#define DSP_RELOC_TYPE_0 0x00 /* relocation of address in DM word / high part of PM word */
#define DSP_RELOC_TYPE_1 0x40 /* relocation of address in low part of PM data word */
#define DSP_RELOC_TYPE_2 0x80 /* relocation of address in standard command */
#define DSP_RELOC_TYPE_3 0xc0 /* relocation of address in call/jump on flag in */
#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100
#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
#define DSP_FILE_FORMAT_VERSION_BCD 0x0100
typedef struct tag_dsp_combifile_header
{
char format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE];
word format_version_bcd;
word header_size;
word combifile_description_size;
word directory_entries;
word directory_size;
word download_count;
word usage_mask_size;
} t_dsp_combifile_header;
typedef struct tag_dsp_combifile_directory_entry
{
word card_type_number;
word file_set_number;
} t_dsp_combifile_directory_entry;
typedef struct tag_dsp_file_header
{
char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE];
word format_version_bcd;
word download_id;
word download_flags;
word required_processing_power;
word interface_channel_count;
word header_size;
word download_description_size;
word memory_block_table_size;
word memory_block_count;
word segment_table_size;
word segment_count;
word symbol_table_size;
word symbol_count;
word total_data_size_dm;
word data_block_count_dm;
word total_data_size_pm;
word data_block_count_pm;
} t_dsp_file_header;
typedef struct tag_dsp_memory_block_desc
{
word alias_memory_block;
word memory_type;
word address;
word size; /* DSP words */
} t_dsp_memory_block_desc;
typedef struct tag_dsp_segment_desc
{
word memory_block;
word attributes;
word base;
word size;
word alignment; /* ==0 -> no other legal start address than base */
} t_dsp_segment_desc;
typedef struct tag_dsp_symbol_desc
{
word symbol_id;
word segment;
word offset;
word size; /* DSP words */
} t_dsp_symbol_desc;
typedef struct tag_dsp_data_block_header
{
word attributes;
word segment;
word offset;
word size; /* DSP words */
} t_dsp_data_block_header;
typedef struct tag_dsp_download_desc /* be sure to keep native alignment for MAESTRA's */
{
word download_id;
word download_flags;
word required_processing_power;
word interface_channel_count;
word excess_header_size;
word memory_block_count;
word segment_count;
word symbol_count;
word data_block_count_dm;
word data_block_count_pm;
byte *p_excess_header_data;
char *p_download_description;
t_dsp_memory_block_desc *p_memory_block_table;
t_dsp_segment_desc *p_segment_table;
t_dsp_symbol_desc *p_symbol_table;
word *p_data_blocks_dm;
word *p_data_blocks_pm;
} t_dsp_download_desc;
#define DSP_DOWNLOAD_INDEX_KERNEL 0
#define DSP30TX_DOWNLOAD_INDEX_KERNEL 1
#define DSP30RX_DOWNLOAD_INDEX_KERNEL 2
#define DSP_MAX_DOWNLOAD_COUNT 35
#define DSP_DOWNLOAD_MAX_SEGMENTS 16
#define DSP_UDATA_REQUEST_RECONFIGURE 0
/*
parameters:
<word> reconfigure delay (in 8kHz samples)
<word> reconfigure code
<byte> reconfigure hdlc preamble flags
*/
#define DSP_RECONFIGURE_TX_FLAG 0x8000
#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000
#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000
#define DSP_RECONFIGURE_HDLC_FLAG 0x1000
#define DSP_RECONFIGURE_SYNC_FLAG 0x0800
#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff
#define DSP_RECONFIGURE_IDLE 0
#define DSP_RECONFIGURE_V25 1
#define DSP_RECONFIGURE_V21_CH2 2
#define DSP_RECONFIGURE_V27_2400 3
#define DSP_RECONFIGURE_V27_4800 4
#define DSP_RECONFIGURE_V29_7200 5
#define DSP_RECONFIGURE_V29_9600 6
#define DSP_RECONFIGURE_V33_12000 7
#define DSP_RECONFIGURE_V33_14400 8
#define DSP_RECONFIGURE_V17_7200 9
#define DSP_RECONFIGURE_V17_9600 10
#define DSP_RECONFIGURE_V17_12000 11
#define DSP_RECONFIGURE_V17_14400 12
/*
data indications if transparent framer
<byte> data 0
<byte> data 1
...
data indications if HDLC framer
<byte> data 0
<byte> data 1
...
<byte> CRC 0
<byte> CRC 1
<byte> preamble flags
*/
#define DSP_UDATA_INDICATION_SYNC 0
/*
returns:
<word> time of sync (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_OFF 1
/*
returns:
<word> time of DCD off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_ON 2
/*
returns:
<word> time of DCD on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s)
*/
#define DSP_UDATA_INDICATION_CTS_OFF 3
/*
returns:
<word> time of CTS off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_CTS_ON 4
/*
returns:
<word> time of CTS on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s)
*/
#define DSP_CONNECTED_NORM_UNSPECIFIED 0
#define DSP_CONNECTED_NORM_V21 1
#define DSP_CONNECTED_NORM_V23 2
#define DSP_CONNECTED_NORM_V22 3
#define DSP_CONNECTED_NORM_V22_BIS 4
#define DSP_CONNECTED_NORM_V32_BIS 5
#define DSP_CONNECTED_NORM_V34 6
#define DSP_CONNECTED_NORM_V8 7
#define DSP_CONNECTED_NORM_BELL_212A 8
#define DSP_CONNECTED_NORM_BELL_103 9
#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10
#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11
#define DSP_CONNECTED_NORM_TFAST 12
#define DSP_CONNECTED_NORM_V21_CH2 13
#define DSP_CONNECTED_NORM_V27_TER 14
#define DSP_CONNECTED_NORM_V29 15
#define DSP_CONNECTED_NORM_V33 16
#define DSP_CONNECTED_NORM_V17 17
#define DSP_CONNECTED_OPTION_TRELLIS 0x0001
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,84 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef DSPDIDS_H_
#define DSPDIDS_H_
/*---------------------------------------------------------------------------*/
#define DSP_DID_INVALID 0
#define DSP_DID_DIVA 1
#define DSP_DID_DIVA_PRO 2
#define DSP_DID_DIVA_PRO_20 3
#define DSP_DID_DIVA_PRO_PCCARD 4
#define DSP_DID_DIVA_SERVER_BRI_1M 5
#define DSP_DID_DIVA_SERVER_BRI_2M 6
#define DSP_DID_DIVA_SERVER_PRI_2M_TX 7
#define DSP_DID_DIVA_SERVER_PRI_2M_RX 8
#define DSP_DID_DIVA_SERVER_PRI_30M 9
#define DSP_DID_TASK_HSCX 100
#define DSP_DID_TASK_HSCX_PRI_2M_TX 101
#define DSP_DID_TASK_HSCX_PRI_2M_RX 102
#define DSP_DID_TASK_V110KRNL 200
#define DSP_DID_OVERLAY_V1100 201
#define DSP_DID_OVERLAY_V1101 202
#define DSP_DID_OVERLAY_V1102 203
#define DSP_DID_OVERLAY_V1103 204
#define DSP_DID_OVERLAY_V1104 205
#define DSP_DID_OVERLAY_V1105 206
#define DSP_DID_OVERLAY_V1106 207
#define DSP_DID_OVERLAY_V1107 208
#define DSP_DID_OVERLAY_V1108 209
#define DSP_DID_OVERLAY_V1109 210
#define DSP_DID_TASK_V110_PRI_2M_TX 220
#define DSP_DID_TASK_V110_PRI_2M_RX 221
#define DSP_DID_TASK_MODEM 300
#define DSP_DID_TASK_FAX05 400
#define DSP_DID_TASK_VOICE 500
#define DSP_DID_TASK_TIKRNL81 600
#define DSP_DID_OVERLAY_DIAL 601
#define DSP_DID_OVERLAY_V22 602
#define DSP_DID_OVERLAY_V32 603
#define DSP_DID_OVERLAY_FSK 604
#define DSP_DID_OVERLAY_FAX 605
#define DSP_DID_OVERLAY_VXX 606
#define DSP_DID_OVERLAY_V8 607
#define DSP_DID_OVERLAY_INFO 608
#define DSP_DID_OVERLAY_V34 609
#define DSP_DID_OVERLAY_DFX 610
#define DSP_DID_PARTIAL_OVERLAY_DIAL 611
#define DSP_DID_PARTIAL_OVERLAY_FSK 612
#define DSP_DID_PARTIAL_OVERLAY_FAX 613
#define DSP_DID_TASK_TIKRNL05 700
/*---------------------------------------------------------------------------*/
#endif
/*---------------------------------------------------------------------------*/

View File

@ -21,6 +21,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.19 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
*
* Revision 1.18 1999/11/25 11:43:27 armin
* Fixed statectrl and connect message.
* X.75 fix and HDLC/transparent with autoconnect.
@ -120,6 +124,8 @@
#define EICON_IOCTL_TEST 98
#define EICON_IOCTL_DEBUGVAR 99
#define EICON_IOCTL_DIA_OFFSET 100
/* Bus types */
#define EICON_BUS_ISA 1
#define EICON_BUS_MCA 2
@ -181,39 +187,10 @@ typedef struct {
unsigned char code[1]; /* Rest (bootstrap- and firmware code) will be allocated */
} eicon_isa_codebuf;
/* Struct for downloading protocol via ioctl for PCI cards */
typedef struct {
/* start-up parameters */
unsigned char tei;
unsigned char nt2;
unsigned char WatchDog;
unsigned char Permanent;
unsigned char XInterface;
unsigned char StableL2;
unsigned char NoOrderCheck;
unsigned char HandsetType;
unsigned char LowChannel;
unsigned char ProtVersion;
unsigned char Crc4;
unsigned char NoHscx30Mode; /* switch PRI into No HSCX30 test mode */
unsigned char Loopback; /* switch card into Loopback mode */
struct q931_link_s
{
unsigned char oad[32];
unsigned char osa[32];
unsigned char spid[32];
} l[2];
unsigned long protocol_len;
unsigned int dsp_code_num;
unsigned long dsp_code_len[9];
unsigned char code[1]; /* Rest (protocol- and dsp code) will be allocated */
} eicon_pci_codebuf;
/* Data for downloading protocol via ioctl */
typedef union {
eicon_isa_codebuf isa;
eicon_isa_codebuf mca;
eicon_pci_codebuf pci;
} eicon_codebuf;
/* Data for Management interface */
@ -224,6 +201,7 @@ typedef struct {
unsigned char data[700];
} eicon_manifbuf;
#define TRACE_OK (1)
#ifdef __KERNEL__
@ -239,6 +217,7 @@ typedef struct {
#include <linux/major.h>
#include <asm/segment.h>
#include <asm/io.h>
#include <asm/spinlock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/malloc.h>
@ -262,206 +241,34 @@ typedef struct {
#include "eicon_isa.h"
#include "idi.h"
typedef struct {
__u16 NextReq __attribute__ ((packed)); /* pointer to next Req Buffer */
__u16 NextRc __attribute__ ((packed)); /* pointer to next Rc Buffer */
__u16 NextInd __attribute__ ((packed)); /* pointer to next Ind Buffer */
__u8 ReqInput __attribute__ ((packed)); /* number of Req Buffers sent */
__u8 ReqOutput __attribute__ ((packed)); /* number of Req Buffers returned */
__u8 ReqReserved __attribute__ ((packed));/*number of Req Buffers reserved */
__u8 Int __attribute__ ((packed)); /* ISDN-P interrupt */
__u8 XLock __attribute__ ((packed)); /* Lock field for arbitration */
__u8 RcOutput __attribute__ ((packed)); /* number of Rc buffers received */
__u8 IndOutput __attribute__ ((packed)); /* number of Ind buffers received */
__u8 IMask __attribute__ ((packed)); /* Interrupt Mask Flag */
__u8 Reserved1[2] __attribute__ ((packed)); /* reserved field, do not use */
__u8 ReadyInt __attribute__ ((packed)); /* request field for ready int */
__u8 Reserved2[12] __attribute__ ((packed)); /* reserved field, do not use */
__u8 InterfaceType __attribute__ ((packed)); /* interface type 1=16K */
__u16 Signature __attribute__ ((packed)); /* ISDN-P initialized ind */
__u8 B[1]; /* buffer space for Req,Ind and Rc */
} eicon_pr_ram;
/* Macro for delay via schedule() */
#define SLEEP(j) { \
set_current_state(TASK_UNINTERRUPTIBLE); \
schedule_timeout(j); \
}
#endif /* KERNEL */
#define DIVAS_SHARED_OFFSET (0x1000)
#define MIPS_BUFFER_SZ 128
#define MIPS_MAINT_OFFS 0xff00
#define XLOG_ERR_CARD_NUM (13)
#define XLOG_ERR_DONE (14)
#define XLOG_ERR_CMD (15)
#define XLOG_ERR_TIMEOUT (16)
#define XLOG_ERR_CARD_STATE (17)
#define XLOG_ERR_UNKNOWN (18)
#define XLOG_OK (0)
#define TRACE_OK (1)
typedef struct {
__u8 Id __attribute__ ((packed));
__u8 uX __attribute__ ((packed));
__u8 listen __attribute__ ((packed));
__u8 active __attribute__ ((packed));
__u8 sin[3] __attribute__ ((packed));
__u8 bc[6] __attribute__ ((packed));
__u8 llc[6] __attribute__ ((packed));
__u8 hlc[6] __attribute__ ((packed));
__u8 oad[20] __attribute__ ((packed));
}DSigStruc;
typedef struct {
__u32 cx_b1 __attribute__ ((packed));
__u32 cx_b2 __attribute__ ((packed));
__u32 cr_b1 __attribute__ ((packed));
__u32 cr_b2 __attribute__ ((packed));
__u32 px_b1 __attribute__ ((packed));
__u32 px_b2 __attribute__ ((packed));
__u32 pr_b1 __attribute__ ((packed));
__u32 pr_b2 __attribute__ ((packed));
__u16 er_b1 __attribute__ ((packed));
__u16 er_b2 __attribute__ ((packed));
}BL1Struc;
typedef struct {
__u32 XTotal __attribute__ ((packed));
__u32 RTotal __attribute__ ((packed));
__u16 XError __attribute__ ((packed));
__u16 RError __attribute__ ((packed));
}L2Struc;
typedef struct {
__u16 free_n;
}OSStruc;
typedef union
{
DSigStruc DSigStats;
BL1Struc BL1Stats;
L2Struc L2Stats;
OSStruc OSStats;
__u8 b[MIPS_BUFFER_SZ];
__u16 w[MIPS_BUFFER_SZ>>1];
__u16 l[MIPS_BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
__u32 d[MIPS_BUFFER_SZ>>2];
} MIPS_BUFFER;
typedef struct
{
__u8 req __attribute__ ((packed));
__u8 rc __attribute__ ((packed));
__u8 reserved[2] __attribute__ ((packed)); /* R3000 alignment ... */
__u8 *mem __attribute__ ((packed));
__u16 length __attribute__ ((packed)); /* used to be short */
__u16 port __attribute__ ((packed));
__u8 fill[4] __attribute__ ((packed)); /* data at offset 16 */
MIPS_BUFFER data __attribute__ ((packed));
} mi_pc_maint_t;
typedef struct
{
__u16 command;
mi_pc_maint_t pcm;
}xlogreq_t;
typedef struct{
__u16 code __attribute__ ((packed)); /* used to be short */
__u16 timeh __attribute__ ((packed));
__u16 timel __attribute__ ((packed));
char buffer[MIPS_BUFFER_SZ - 6];
}xlog_entry_t;
#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100
#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
#define DSP_FILE_FORMAT_VERSION_BCD 0x0100
typedef struct tag_dsp_combifile_header
{
char format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
__u16 format_version_bcd __attribute__ ((packed));
__u16 header_size __attribute__ ((packed));
__u16 combifile_description_size __attribute__ ((packed));
__u16 directory_entries __attribute__ ((packed));
__u16 directory_size __attribute__ ((packed));
__u16 download_count __attribute__ ((packed));
__u16 usage_mask_size __attribute__ ((packed));
} t_dsp_combifile_header;
typedef struct tag_dsp_combifile_directory_entry
{
__u16 card_type_number __attribute__ ((packed));
__u16 file_set_number __attribute__ ((packed));
} t_dsp_combifile_directory_entry;
typedef struct tag_dsp_file_header
{
char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
__u16 format_version_bcd __attribute__ ((packed));
__u16 download_id __attribute__ ((packed));
__u16 download_flags __attribute__ ((packed));
__u16 required_processing_power __attribute__ ((packed));
__u16 interface_channel_count __attribute__ ((packed));
__u16 header_size __attribute__ ((packed));
__u16 download_description_size __attribute__ ((packed));
__u16 memory_block_table_size __attribute__ ((packed));
__u16 memory_block_count __attribute__ ((packed));
__u16 segment_table_size __attribute__ ((packed));
__u16 segment_count __attribute__ ((packed));
__u16 symbol_table_size __attribute__ ((packed));
__u16 symbol_count __attribute__ ((packed));
__u16 total_data_size_dm __attribute__ ((packed));
__u16 data_block_count_dm __attribute__ ((packed));
__u16 total_data_size_pm __attribute__ ((packed));
__u16 data_block_count_pm __attribute__ ((packed));
} t_dsp_file_header;
typedef struct tag_dsp_memory_block_desc
{
__u16 alias_memory_block;
__u16 memory_type;
__u16 address;
__u16 size; /* DSP words */
} t_dsp_memory_block_desc;
typedef struct tag_dsp_segment_desc
{
__u16 memory_block;
__u16 attributes;
__u16 base;
__u16 size;
__u16 alignment; /* ==0 -> no other legal start address than base */
} t_dsp_segment_desc;
typedef struct tag_dsp_symbol_desc
{
__u16 symbol_id;
__u16 segment;
__u16 offset;
__u16 size; /* DSP words */
} t_dsp_symbol_desc;
typedef struct tag_dsp_data_block_header
{
__u16 attributes;
__u16 segment;
__u16 offset;
__u16 size; /* DSP words */
} t_dsp_data_block_header;
typedef struct tag_dsp_download_desc /* be sure to keep native alignment for MAESTRA's */
{
__u16 download_id;
__u16 download_flags;
__u16 required_processing_power;
__u16 interface_channel_count;
__u16 excess_header_size;
__u16 memory_block_count;
__u16 segment_count;
__u16 symbol_count;
__u16 data_block_count_dm;
__u16 data_block_count_pm;
__u8 * p_excess_header_data __attribute__ ((packed));
char * p_download_description __attribute__ ((packed));
t_dsp_memory_block_desc *p_memory_block_table __attribute__ ((packed));
t_dsp_segment_desc *p_segment_table __attribute__ ((packed));
t_dsp_symbol_desc *p_symbol_table __attribute__ ((packed));
__u16 * p_data_blocks_dm __attribute__ ((packed));
__u16 * p_data_blocks_pm __attribute__ ((packed));
} t_dsp_download_desc;
#ifdef __KERNEL__
typedef struct {
__u8 Req; /* pending request */
__u8 Rc; /* return code received */
@ -515,7 +322,9 @@ typedef struct {
T30_s *fax; /* pointer to fax data in LL */
eicon_ch_fax_buf fax2; /* fax related struct */
#endif
entity e; /* Entity */
entity e; /* Native Entity */
ENTITY de; /* Divas D Entity */
ENTITY be; /* Divas B Entity */
char cpn[32]; /* remember cpn */
char oad[32]; /* remember oad */
char dsa[32]; /* remember dsa */
@ -539,8 +348,6 @@ typedef struct {
#define EICON_FLAGS_MVALID 8 /* Cards membase is valid */
#define EICON_FLAGS_LOADED 8 /* Firmware loaded */
#define EICON_BCH 2 /* # of channels per card */
/* D-Channel states */
#define EICON_STATE_NULL 0
#define EICON_STATE_ICALL 1
@ -562,9 +369,6 @@ typedef struct {
#define EICON_MAX_QUEUE 2138
#define EICON_LOCK_TX 0
#define EICON_LOCK_RX 1
typedef union {
eicon_isa_card isa;
eicon_pci_card pci;
@ -590,17 +394,12 @@ typedef struct {
__u8 more;
} eicon_indhdr;
typedef struct msn_entry {
char eaz;
char msn[16];
struct msn_entry * next;
} msn_entry;
/*
* Per card driver data
*/
typedef struct eicon_card {
eicon_hwif hwif; /* Hardware dependant interface */
DESCRIPTOR *d; /* IDI Descriptor */
u_char ptype; /* Protocol type (1TR6 or Euro) */
u_char bus; /* Bustype (ISA, MCA, PCI) */
u_char type; /* Cardtype (EICON_CTYPE_...) */
@ -618,49 +417,23 @@ typedef struct eicon_card {
struct tq_struct snd_tq; /* Task struct for xmit bh */
struct tq_struct rcv_tq; /* Task struct for rcv bh */
struct tq_struct ack_tq; /* Task struct for ack bh */
msn_entry *msn_list;
eicon_chan* IdTable[256]; /* Table to find entity */
__u16 ref_in;
__u16 ref_out;
int nchannels; /* Number of B-Channels */
int ReadyInt; /* Ready Interrupt */
eicon_chan *bch; /* B-Channel status/control */
char status_buf[256]; /* Buffer for status messages */
char *status_buf_read;
char *status_buf_write;
char *status_buf_end;
DBUFFER *dbuf; /* Dbuffer for Diva Server */
BUFFERS *sbuf; /* Buffer for Diva Server */
char *sbufp; /* Data Buffer for Diva Server */
isdn_if interface; /* Interface to upper layer */
char regname[35]; /* Name used for request_region */
char regname[35]; /* Drivers card name */
#ifdef CONFIG_MCA
int mca_slot; /* # of cards MCA slot */
int mca_io; /* MCA cards IO port */
#endif /* CONFIG_MCA */
} eicon_card;
/* -----------------------------------------------------------**
** The PROTOCOL_FEATURE_STRING **
** defines capabilities and **
** features of the actual protocol code. It's used as a bit **
** mask. **
** The following Bits are defined: **
** -----------------------------------------------------------*/
#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */
#define PROTCAP_MANIF 0x0002 /* Management interface implemented */
#define PROTCAP_V_42 0x0004 /* V42 implemented */
#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */
#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */
#define PROTCAP_FREE4 0x0020 /* not used */
#define PROTCAP_FREE5 0x0040 /* not used */
#define PROTCAP_FREE6 0x0080 /* not used */
#define PROTCAP_FREE7 0x0100 /* not used */
#define PROTCAP_FREE8 0x0200 /* not used */
#define PROTCAP_FREE9 0x0400 /* not used */
#define PROTCAP_FREE10 0x0800 /* not used */
#define PROTCAP_FREE11 0x1000 /* not used */
#define PROTCAP_FREE12 0x2000 /* not used */
#define PROTCAP_FREE13 0x4000 /* not used */
#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */
#include "eicon_idi.h"
extern eicon_card *cards;
@ -685,13 +458,11 @@ extern __inline__ void eicon_schedule_ack(eicon_card *card)
mark_bh(IMMEDIATE_BH);
}
extern char *eicon_find_eaz(eicon_card *, char);
extern int eicon_addcard(int, int, int, char *);
extern void eicon_io_transmit(eicon_card *card);
extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs);
extern void eicon_io_rcv_dispatch(eicon_card *ccard);
extern void eicon_io_ack_dispatch(eicon_card *ccard);
extern int eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq);
#ifdef CONFIG_MCA
extern int eicon_mca_find_card(int, int, int, char *);
extern int eicon_mca_probe(int, int, int, int, char *);
@ -702,6 +473,8 @@ extern ulong DebugVar;
extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
extern void eicon_putstatus(eicon_card * card, char * buf);
extern spinlock_t eicon_lock;
#endif /* __KERNEL__ */
#endif /* eicon_h */

View File

@ -21,6 +21,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.5 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
*
* Revision 1.4 1999/07/25 15:12:02 armin
* fix of some debug logs.
* enabled ISA-cards option.
@ -43,48 +47,8 @@
#ifndef DSP_H
#define DSP_H
#define DSP_UDATA_REQUEST_RECONFIGURE 0
/*
parameters:
<word> reconfigure delay (in 8kHz samples)
<word> reconfigure code
<byte> reconfigure hdlc preamble flags
*/
#include "dsp_defs.h"
#define DSP_RECONFIGURE_TX_FLAG 0x8000
#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000
#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000
#define DSP_RECONFIGURE_HDLC_FLAG 0x1000
#define DSP_RECONFIGURE_SYNC_FLAG 0x0800
#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff
#define DSP_RECONFIGURE_IDLE 0
#define DSP_RECONFIGURE_V25 1
#define DSP_RECONFIGURE_V21_CH2 2
#define DSP_RECONFIGURE_V27_2400 3
#define DSP_RECONFIGURE_V27_4800 4
#define DSP_RECONFIGURE_V29_7200 5
#define DSP_RECONFIGURE_V29_9600 6
#define DSP_RECONFIGURE_V33_12000 7
#define DSP_RECONFIGURE_V33_14400 8
#define DSP_RECONFIGURE_V17_7200 9
#define DSP_RECONFIGURE_V17_9600 10
#define DSP_RECONFIGURE_V17_12000 11
#define DSP_RECONFIGURE_V17_14400 12
/*
data indications if transparent framer
<byte> data 0
<byte> data 1
...
data indications if HDLC framer
<byte> data 0
<byte> data 1
...
<byte> CRC 0
<byte> CRC 1
<byte> preamble flags
*/
#define DSP_UDATA_REQUEST_SWITCH_FRAMER 1
/*
@ -118,49 +82,6 @@ parameters:
- none -
*/
#define DSP_UDATA_INDICATION_SYNC 0
/*
returns:
<word> time of sync (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_OFF 1
/*
returns:
<word> time of DCD off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_ON 2
/*
returns:
<word> time of DCD on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s, max of tx and rx speed)
<word> roundtrip delay (ms)
<dword> connected speed tx (bit/s)
<dword> connected speed rx (bit/s)
*/
#define DSP_UDATA_INDICATION_CTS_OFF 3
/*
returns:
<word> time of CTS off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_CTS_ON 4
/*
returns:
<word> time of CTS on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s, max of tx and rx speed)
<word> roundtrip delay (ms)
<dword> connected speed tx (bit/s)
<dword> connected speed rx (bit/s)
*/
typedef struct eicon_dsp_ind {
__u16 time __attribute__ ((packed));
__u8 norm __attribute__ ((packed));
@ -171,32 +92,11 @@ typedef struct eicon_dsp_ind {
__u32 rxspeed __attribute__ ((packed));
} eicon_dsp_ind;
#define DSP_CONNECTED_NORM_UNSPECIFIED 0
#define DSP_CONNECTED_NORM_V21 1
#define DSP_CONNECTED_NORM_V23 2
#define DSP_CONNECTED_NORM_V22 3
#define DSP_CONNECTED_NORM_V22_BIS 4
#define DSP_CONNECTED_NORM_V32_BIS 5
#define DSP_CONNECTED_NORM_V34 6
#define DSP_CONNECTED_NORM_V8 7
#define DSP_CONNECTED_NORM_BELL_212A 8
#define DSP_CONNECTED_NORM_BELL_103 9
#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10
#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11
#define DSP_CONNECTED_NORM_V90 12
#define DSP_CONNECTED_NORM_V21_CH2 13
#define DSP_CONNECTED_NORM_V27_TER 14
#define DSP_CONNECTED_NORM_V29 15
#define DSP_CONNECTED_NORM_V33 16
#define DSP_CONNECTED_NORM_V17 17
#define DSP_CONNECTED_OPTION_TRELLIS 0x0001
#define DSP_CONNECTED_OPTION_V42_TRANS 0x0002
#define DSP_CONNECTED_OPTION_V42_LAPM 0x0004
#define DSP_CONNECTED_OPTION_SHORT_TRAIN 0x0008
#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010
#define DSP_UDATA_INDICATION_DISCONNECT 5
/*
returns:
@ -210,7 +110,6 @@ returns:
#define DSP_DISCONNECT_CAUSE_CLEARDOWN 0x04
#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT 0x05
#define DSP_UDATA_INDICATION_TX_CONFIRMATION 6
/*
returns:

View File

@ -26,6 +26,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.33 2000/03/06 15:45:17 armin
* Fixed incomplete number handling with BRI PtP connection.
*
* Revision 1.32 2000/03/04 17:04:21 armin
* Fix of statemachine, B-connect before D-connect,
* thanks to Helmut Adams <adams@ipcon.de>
@ -158,6 +161,7 @@
#include "eicon.h"
#include "eicon_idi.h"
#include "eicon_dsp.h"
#include "uxio.h"
#undef EICON_FULL_SERVICE_OKTETT
@ -206,7 +210,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
reqbuf->XBuffer.P[l++] = 0; /* end */
reqbuf->Req = ASSIGN;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 0;
reqbuf->ReqId = DSIG_ID;
reqbuf->XBuffer.length = l;
reqbuf->Reference = 0; /* Sig Entity */
}
@ -259,7 +263,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
reqbuf->XBuffer.P[l++] = 0; /* end */
reqbuf->Req = ASSIGN;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 0x20;
reqbuf->ReqId = NL_ID;
reqbuf->XBuffer.length = l;
reqbuf->Reference = 1; /* Net Entity */
}
@ -397,17 +401,17 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
case CALL_RES:
idi_call_res_req(reqbuf, chan);
break;
case IDI_N_CONNECT|0x700:
idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
case N_CONNECT|0x700:
idi_put_req(reqbuf, N_CONNECT, 1, 0);
break;
case IDI_N_CONNECT_ACK|0x700:
idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
case N_CONNECT_ACK|0x700:
idi_put_req(reqbuf, N_CONNECT_ACK, 1, 0);
break;
case IDI_N_DISC|0x700:
idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
case N_DISC|0x700:
idi_put_req(reqbuf, N_DISC, 1, chan->e.IndCh);
break;
case IDI_N_DISC_ACK|0x700:
idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
case N_DISC_ACK|0x700:
idi_put_req(reqbuf, N_DISC_ACK, 1, chan->e.IndCh);
break;
default:
eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
@ -489,7 +493,7 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
(chan->fsm_state == EICON_STATE_WMCONN)) {
if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1);
if (chan->e.B2Id) idi_do_req(card, chan, N_DISC, 1);
}
if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
if (chan->fsm_state != EICON_STATE_NULL) {
@ -1222,7 +1226,7 @@ idi_send_edata(eicon_card *card, eicon_chan *chan)
reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_EDATA;
reqbuf->Req = N_EDATA;
reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
@ -2252,7 +2256,7 @@ idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int
reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_UDATA;
reqbuf->Req = N_UDATA;
reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
@ -2446,12 +2450,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
while((skb2 = skb_dequeue(&chan->e.X))) {
dev_kfree_skb(skb2);
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
chan->queued = 0;
chan->waitq = 0;
chan->waitpq = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
if (message.e_cau[0] & 0x7f) {
cmd.driver = ccard->myid;
cmd.arg = chan->No;
@ -2588,11 +2591,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
/* do nothing, wait for connect */
break;
case ISDN_PROTO_L2_TRANS:
idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
idi_do_req(ccard, chan, N_CONNECT, 1);
break;
default:
/* On most incoming calls we use automatic connect */
/* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
/* idi_do_req(ccard, chan, N_CONNECT, 1); */
}
} else {
if (chan->fsm_state != EICON_STATE_ACTIVE)
@ -2616,7 +2619,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
idi_do_req(ccard, chan, ASSIGN, 1);
idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
idi_do_req(ccard, chan, N_CONNECT, 1);
#ifdef CONFIG_ISDN_TTY_FAX
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
if (chan->fax)
@ -2647,7 +2650,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
else
switch(ind->Ind) {
case IDI_N_CONNECT_ACK:
case N_CONNECT_ACK:
eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No);
if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
chan->fsm_state = EICON_STATE_WMCONN;
@ -2668,7 +2671,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
}
else {
eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
eicon_log(ccard, 1, "idi_ind: N_Connect_Ack with NULL fax struct, ERROR\n");
}
#endif
break;
@ -2680,10 +2683,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
strcpy(cmd.parm.num, "64000");
ccard->interface.statcallb(&cmd);
break;
case IDI_N_CONNECT:
case N_CONNECT:
eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
chan->e.IndCh = ind->IndCh;
if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
if (chan->e.B2Id) idi_do_req(ccard, chan, N_CONNECT_ACK, 1);
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
break;
}
@ -2698,13 +2701,13 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
strcpy(cmd.parm.num, "64000");
ccard->interface.statcallb(&cmd);
break;
case IDI_N_DISC:
eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No);
case N_DISC:
eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc\n", chan->No);
if (chan->e.B2Id) {
while((skb2 = skb_dequeue(&chan->e.X))) {
dev_kfree_skb(skb2);
}
idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
idi_do_req(ccard, chan, N_DISC_ACK, 1);
idi_do_req(ccard, chan, REMOVE, 1);
}
#ifdef CONFIG_ISDN_TTY_FAX
@ -2714,12 +2717,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
#endif
chan->e.IndCh = 0;
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
chan->queued = 0;
chan->waitq = 0;
chan->waitpq = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
idi_do_req(ccard, chan, HANGUP, 0);
if (chan->fsm_state == EICON_STATE_ACTIVE) {
cmd.driver = ccard->myid;
@ -2733,8 +2735,8 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
chan->fax = 0;
#endif
break;
case IDI_N_DISC_ACK:
eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
case N_DISC_ACK:
eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc_Ack\n", chan->No);
#ifdef CONFIG_ISDN_TTY_FAX
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
@ -2742,10 +2744,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
#endif
break;
case IDI_N_DATA_ACK:
eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
case N_DATA_ACK:
eicon_log(ccard, 128, "idi_ind: Ch%d: N_Data_Ack\n", chan->No);
break;
case IDI_N_DATA:
case N_DATA:
skb_pull(skb, sizeof(eicon_IND) - 1);
eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
@ -2757,11 +2759,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
free_buff = 0;
}
break;
case IDI_N_UDATA:
case N_UDATA:
idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
break;
#ifdef CONFIG_ISDN_TTY_FAX
case IDI_N_EDATA:
case N_EDATA:
idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
break;
#endif
@ -2804,8 +2806,7 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
ack->Reference, chan->e.ref);
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
ccard->IdTable[ack->RcId] = NULL;
eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
@ -2813,7 +2814,7 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
chan->e.D3Id = 0;
else
chan->e.B2Id = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
return 1;
}
@ -2824,14 +2825,14 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
} else {
/* Network layer */
switch(chan->e.Req & 0x0f) {
case IDI_N_CONNECT:
case N_CONNECT:
chan->e.IndCh = ack->RcCh;
eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
ack->RcId, ack->RcCh, ack->Reference);
break;
case IDI_N_MDATA:
case IDI_N_DATA:
if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
case N_MDATA:
case N_DATA:
if ((chan->e.Req & 0x0f) == N_DATA) {
if (chan->queued) {
cmd.driver = ccard->myid;
cmd.command = ISDN_STAT_BSENT;
@ -2839,10 +2840,9 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
cmd.parm.length = chan->waitpq;
ccard->interface.statcallb(&cmd);
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
chan->waitpq = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
#ifdef CONFIG_ISDN_TTY_FAX
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
if (((chan->queued - chan->waitq) < 1) &&
@ -2862,11 +2862,10 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
}
#endif
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
chan->queued -= chan->waitq;
if (chan->queued < 0) chan->queued = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
break;
default:
eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
@ -2892,11 +2891,10 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
return;
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if ((chan = ccard->IdTable[ack->RcId]) != NULL)
dCh = chan->No;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
switch (ack->Rc) {
case OK_FC:
@ -2924,8 +2922,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n",
chan->No, chan->e.D3Id, chan->e.B2Id);
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
for(j = 0; j < ccard->nchannels + 1; j++) {
if ((ccard->bch[j].e.ref == ack->Reference) &&
(ccard->bch[j].e.Req == ASSIGN)) {
@ -2939,8 +2936,8 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
break;
}
}
restore_flags(flags);
}
spin_unlock_irqrestore(&eicon_lock, flags);
if (j > ccard->nchannels) {
eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n",
ack->Reference, ack->RcId);
@ -2951,6 +2948,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
case UNKNOWN_COMMAND:
case WRONG_COMMAND:
case WRONG_ID:
case ADAPTER_DEAD:
case WRONG_CH:
case UNKNOWN_IE:
case WRONG_IE:
@ -2983,13 +2981,12 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
ccard->interface.statcallb(&cmd);
}
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if (chan) {
chan->e.ref = 0;
chan->e.busy = 0;
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
dev_kfree_skb(skb);
eicon_schedule_tx(ccard);
}
@ -3024,8 +3021,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len);
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
while(offset < len) {
plen = ((len - offset) > 270) ? 270 : len - offset;
@ -3034,7 +3030,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
if ((!xmit_skb) || (!skb2)) {
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
if (xmit_skb)
dev_kfree_skb(skb);
@ -3051,9 +3047,9 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
(chan->l2prot != ISDN_PROTO_L2_MODEM) &&
(chan->l2prot != ISDN_PROTO_L2_FAX) &&
(chan->l2prot != ISDN_PROTO_L2_TRANS)) {
reqbuf->Req = IDI_N_MDATA;
reqbuf->Req = N_MDATA;
} else {
reqbuf->Req = IDI_N_DATA;
reqbuf->Req = N_DATA;
/* if (ack) reqbuf->Req |= N_D_BIT; */
}
reqbuf->ReqCh = chan->e.IndCh;
@ -3069,7 +3065,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
}
if (que)
chan->queued += len;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
eicon_schedule_tx(card);
dev_kfree_skb(skb);
return len;
@ -3107,7 +3103,7 @@ eicon_idi_manage_assign(eicon_card *card)
reqbuf->XBuffer.P[0] = 0;
reqbuf->Req = ASSIGN;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 0xe0;
reqbuf->ReqId = MAN_ID;
reqbuf->XBuffer.length = 1;
reqbuf->Reference = 2; /* Man Entity */
@ -3233,7 +3229,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
reqbuf->XBuffer.P[1] = manbuf->length[0] + 1;
reqbuf->XBuffer.P[l++] = 0;
reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */
reqbuf->Req = (manbuf->count) ? manbuf->count : MAN_READ;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = l;

View File

@ -21,6 +21,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.9 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
*
* Revision 1.8 1999/11/25 11:43:27 armin
* Fixed statectrl and connect message.
* X.75 fix and HDLC/transparent with autoconnect.
@ -62,119 +66,21 @@
*
*/
#ifndef IDI_H
#define IDI_H
#ifndef E_IDI_H
#define E_IDI_H
#include <linux/config.h>
#define ASSIGN 0x01
#define REMOVE 0xff
#define CALL_REQ 1 /* call request */
#define CALL_CON 1 /* call confirmation */
#define CALL_IND 2 /* incoming call connected */
#define LISTEN_REQ 2 /* listen request */
#define HANGUP 3 /* hangup request/indication */
#define SUSPEND 4 /* call suspend request/confirm */
#define RESUME 5 /* call resume request/confirm */
#define SUSPEND_REJ 6 /* suspend rejected indication */
#define USER_DATA 8 /* user data for user to user signaling */
#define CONGESTION 9 /* network congestion indication */
#define INDICATE_REQ 10 /* request to indicate an incoming call */
#define INDICATE_IND 10 /* indicates that there is an incoming call */
#define CALL_RES 11 /* accept an incoming call */
#define CALL_ALERT 12 /* send ALERT for incoming call */
#define INFO_REQ 13 /* INFO request */
#define INFO_IND 13 /* INFO indication */
#define REJECT 14 /* reject an incoming call */
#define RESOURCES 15 /* reserve B-Channel hardware resources */
#define TEL_CTRL 16 /* Telephone control request/indication */
#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */
#define FAC_REG_REQ 18 /* connection idependent fac registration */
#define FAC_REG_ACK 19 /* fac registration acknowledge */
#define FAC_REG_REJ 20 /* fac registration reject */
#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */
#define AOC_IND 26/* Advice of Charge */
#undef N_DATA
#undef ID_MASK
#define IDI_N_MDATA (0x01)
#define IDI_N_CONNECT (0x02)
#define IDI_N_CONNECT_ACK (0x03)
#define IDI_N_DISC (0x04)
#define IDI_N_DISC_ACK (0x05)
#define IDI_N_RESET (0x06)
#define IDI_N_RESET_ACK (0x07)
#define IDI_N_DATA (0x08)
#define IDI_N_EDATA (0x09)
#define IDI_N_UDATA (0x0a)
#define IDI_N_BDATA (0x0b)
#define IDI_N_DATA_ACK (0x0c)
#define IDI_N_EDATA_ACK (0x0d)
#include "pc.h"
#define N_Q_BIT 0x10 /* Q-bit for req/ind */
#define N_M_BIT 0x20 /* M-bit for req/ind */
#define N_D_BIT 0x40 /* D-bit for req/ind */
#define AOC_IND 26 /* Advice of Charge */
#define PI 0x1e /* Progress Indicator */
#define NI 0x27 /* Notification Indicator */
#define SHIFT 0x90 /* codeset shift */
#define MORE 0xa0 /* more data */
#define CL 0xb0 /* congestion level */
/* codeset 0 */
#define BC 0x04 /* Bearer Capability */
#define CAU 0x08 /* cause */
#define CAD 0x0c /* Connected address */
#define CAI 0x10 /* call identity */
#define CHI 0x18 /* channel identification */
#define LLI 0x19 /* logical link id */
#define CHA 0x1a /* charge advice */
#define FTY 0x1c
#define PI 0x1e /* Progress Indicator */
#define NI 0x27 /* Notification Indicator */
#define DT 0x29 /* ETSI date/time */
#define KEY 0x2c /* keypad information element */
#define DSP 0x28 /* display */
#define OAD 0x6c /* origination address */
#define OSA 0x6d /* origination sub-address */
#define CPN 0x70 /* called party number */
#define DSA 0x71 /* destination sub-address */
#define RDN 0x74 /* redirecting number */
#define LLC 0x7c /* low layer compatibility */
#define HLC 0x7d /* high layer compatibility */
#define UUI 0x7e /* user user information */
#define ESC 0x7f /* escape extension */
#define DLC 0x20 /* data link layer configuration */
#define NLC 0x21 /* network layer configuration */
/* codeset 6 */
#define SIN 0x01 /* service indicator */
#define CIF 0x02 /* charging information */
#define DATE 0x03 /* date */
#define CPS 0x07 /* called party status */
/*------------------------------------------------------------------*/
/* return code coding */
/*------------------------------------------------------------------*/
#define UNKNOWN_COMMAND 0x01 /* unknown command */
#define WRONG_COMMAND 0x02 /* wrong command */
#define WRONG_ID 0x03 /* unknown task/entity id */
#define WRONG_CH 0x04 /* wrong task/entity id */
#define UNKNOWN_IE 0x05 /* unknown information el. */
#define WRONG_IE 0x06 /* wrong information el. */
#define OUT_OF_RESOURCES 0x07 /* card out of res. */
#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */
#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */
#define ASSIGN_OK 0xef /* ASSIGN OK */
#define OK_FC 0xfc /* Flow-Control RC */
#define READY_INT 0xfd /* Ready interrupt */
#define TIMER_INT 0xfe /* timer interrupt */
#define OK 0xff /* command accepted */
/*------------------------------------------------------------------*/
/* defines for statectrl */
#define WAITING_FOR_HANGUP 0x01
#define HAVE_CONN_REQ 0x02
@ -237,26 +143,6 @@ typedef struct {
eicon_PBUFFER RBuffer;
} eicon_IND;
typedef struct {
__u16 NextReq __attribute__ ((packed)); /* pointer to next Req Buffer */
__u16 NextRc __attribute__ ((packed)); /* pointer to next Rc Buffer */
__u16 NextInd __attribute__ ((packed)); /* pointer to next Ind Buffer */
__u8 ReqInput __attribute__ ((packed)); /* number of Req Buffers sent */
__u8 ReqOutput __attribute__ ((packed)); /* number of Req Buffers returned */
__u8 ReqReserved __attribute__ ((packed));/*number of Req Buffers reserved */
__u8 Int __attribute__ ((packed)); /* ISDN-P interrupt */
__u8 XLock __attribute__ ((packed)); /* Lock field for arbitration */
__u8 RcOutput __attribute__ ((packed)); /* number of Rc buffers received */
__u8 IndOutput __attribute__ ((packed)); /* number of Ind buffers received */
__u8 IMask __attribute__ ((packed)); /* Interrupt Mask Flag */
__u8 Reserved1[2] __attribute__ ((packed)); /* reserved field, do not use */
__u8 ReadyInt __attribute__ ((packed)); /* request field for ready int */
__u8 Reserved2[12] __attribute__ ((packed)); /* reserved field, do not use */
__u8 InterfaceType __attribute__ ((packed)); /* interface type 1=16K */
__u16 Signature __attribute__ ((packed)); /* ISDN-P initialized ind */
__u8 B[1]; /* buffer space for Req,Ind and Rc */
} eicon_pr_ram;
typedef struct {
__u8 *Data;
unsigned int Size;

View File

@ -24,6 +24,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.10 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
*
* Revision 1.9 1999/11/18 20:55:25 armin
* Ready_Int fix of ISA cards.
*
@ -65,6 +69,7 @@
#include <linux/config.h>
#include "eicon.h"
#include "uxio.h"
void
eicon_io_rcv_dispatch(eicon_card *ccard) {
@ -81,12 +86,11 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
while((skb = skb_dequeue(&ccard->rcvq))) {
ind = (eicon_IND *)skb->data;
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
if (DebugVar & 1) {
switch(ind->Ind) {
case IDI_N_DISC_ACK:
case N_DISC_ACK:
/* doesn't matter if this happens */
break;
default:
@ -95,11 +99,11 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
}
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
dev_kfree_skb(skb);
continue;
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
if (chan->e.complete) { /* check for rec-buffer chaining */
if (ind->MLength == ind->RBuffer.length) {
@ -115,12 +119,11 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
}
}
else {
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if (!(skb2 = skb_dequeue(&chan->e.R))) {
chan->e.complete = 1;
eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n");
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
dev_kfree_skb(skb);
continue;
}
@ -129,7 +132,7 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
GFP_ATOMIC);
if (!skb_new) {
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n");
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
dev_kfree_skb(skb);
dev_kfree_skb(skb2);
continue;
@ -148,14 +151,14 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
dev_kfree_skb(skb2);
if (ind->MLength == ind->RBuffer.length) {
chan->e.complete = 2;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
idi_handle_ind(ccard, skb_new);
continue;
}
else {
chan->e.complete = 0;
skb_queue_tail(&chan->e.R, skb_new);
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
continue;
}
}
@ -177,242 +180,120 @@ eicon_io_ack_dispatch(eicon_card *ccard) {
/*
* IO-Functions for different card-types
* IO-Functions for ISA cards
*/
u8 ram_inb(eicon_card *card, void *adr) {
eicon_pci_card *pcard;
eicon_isa_card *icard;
u32 addr = (u32) adr;
pcard = &card->hwif.pci;
icard = &card->hwif.isa;
switch(card->type) {
case EICON_CTYPE_MAESTRA:
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
return(inb((u16)pcard->PCIreg + M_DATA));
case EICON_CTYPE_MAESTRAP:
case EICON_CTYPE_S2M:
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
case EICON_CTYPE_QUADRO:
return(readb(addr));
}
return(0);
return(readb(addr));
}
u16 ram_inw(eicon_card *card, void *adr) {
eicon_pci_card *pcard;
eicon_isa_card *icard;
u32 addr = (u32) adr;
pcard = &card->hwif.pci;
icard = &card->hwif.isa;
switch(card->type) {
case EICON_CTYPE_MAESTRA:
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
return(inw((u16)pcard->PCIreg + M_DATA));
case EICON_CTYPE_MAESTRAP:
case EICON_CTYPE_S2M:
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
case EICON_CTYPE_QUADRO:
return(readw(addr));
}
return(0);
return(readw(addr));
}
void ram_outb(eicon_card *card, void *adr, u8 data) {
eicon_pci_card *pcard;
eicon_isa_card *icard;
u32 addr = (u32) adr;
pcard = &card->hwif.pci;
icard = &card->hwif.isa;
switch(card->type) {
case EICON_CTYPE_MAESTRA:
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
outb((u8)data, (u16)pcard->PCIreg + M_DATA);
break;
case EICON_CTYPE_MAESTRAP:
case EICON_CTYPE_S2M:
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
case EICON_CTYPE_QUADRO:
writeb(data, addr);
break;
}
writeb(data, addr);
}
void ram_outw(eicon_card *card, void *adr , u16 data) {
eicon_pci_card *pcard;
eicon_isa_card *icard;
u32 addr = (u32) adr;
pcard = &card->hwif.pci;
icard = &card->hwif.isa;
switch(card->type) {
case EICON_CTYPE_MAESTRA:
outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
outw((u16)data, (u16)pcard->PCIreg + M_DATA);
break;
case EICON_CTYPE_MAESTRAP:
case EICON_CTYPE_S2M:
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
case EICON_CTYPE_QUADRO:
writew(data, addr);
break;
}
writew(data, addr);
}
void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) {
int i;
switch(card->type) {
case EICON_CTYPE_MAESTRA:
for(i = 0; i < len; i++) {
writeb(ram_inb(card, adr + i), adrto + i);
}
break;
case EICON_CTYPE_MAESTRAP:
memcpy(adrto, adr, len);
break;
case EICON_CTYPE_S2M:
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
case EICON_CTYPE_QUADRO:
memcpy_fromio(adrto, adr, len);
break;
}
memcpy_fromio(adrto, adr, len);
}
void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) {
int i;
switch(card->type) {
case EICON_CTYPE_MAESTRA:
for(i = 0; i < len; i++) {
ram_outb(card, adrto + i, readb(adr + i));
}
break;
case EICON_CTYPE_MAESTRAP:
memcpy(adrto, adr, len);
break;
case EICON_CTYPE_S2M:
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
case EICON_CTYPE_QUADRO:
memcpy_toio(adrto, adr, len);
break;
}
memcpy_toio(adrto, adr, len);
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
/*
* XLOG
* IDI-Callback function
*/
int
eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq)
void
eicon_idi_callback(ENTITY *de)
{
int timeout, i;
int divas_shared_offset = 0;
eicon_card *ccard = (eicon_card *)de->R;
struct sk_buff *skb;
eicon_RC *ack;
eicon_IND *ind;
int len = 0;
int stype = 0;
__u32 time = 0;
mi_pc_maint_t *pcm = &xlogreq->pcm;
eicon_pci_card *pci_card = &card->hwif.pci;
eicon_isa_card *isa_card = &card->hwif.isa;
eicon_pr_ram *prram = 0;
char *ram;
switch(card->type) {
case EICON_CTYPE_MAESTRAP:
ram = (char *)pci_card->PCIram;
prram = (eicon_pr_ram *)ram;
divas_shared_offset = DIVAS_SHARED_OFFSET;
len = sizeof(mi_pc_maint_t);
break;
case EICON_CTYPE_MAESTRA:
prram = 0;
divas_shared_offset = 0;
len = sizeof(mi_pc_maint_t);
break;
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
case EICON_CTYPE_QUADRO:
case EICON_CTYPE_S2M:
prram = (eicon_pr_ram *)isa_card->shmem;
divas_shared_offset = 0xfb80;
len = sizeof(mi_pc_maint_t) - 78;
stype = 1;
break;
default:
return -ENODEV;
if (de->complete == 255) {
/* Return Code */
skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
if (!skb) {
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
} else {
ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
ack->Rc = de->Rc;
if (de->Rc == ASSIGN_OK) {
ack->RcId = de->Id;
de->user[1] = de->Id;
} else {
ack->RcId = de->user[1];
}
ack->RcCh = de->RcCh;
ack->Reference = de->user[0];
skb_queue_tail(&ccard->rackq, skb);
eicon_schedule_ack(ccard);
eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n",
de->user[0], de->Rc, ack->RcId, de->RLength, de->complete);
}
} else {
/* Indication */
if (de->complete) {
len = de->RLength;
} else {
len = 270;
if (de->RLength <= 270)
eicon_log(ccard, 1, "eicon_cbk: ind not complete but <= 270\n");
}
skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
if (!skb) {
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
} else {
ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
ind->Ind = de->Ind;
ind->IndId = de->user[1];
ind->IndCh = de->IndCh;
ind->MInd = de->Ind;
ind->RBuffer.length = len;
ind->MLength = de->RLength;
memcpy(&ind->RBuffer.P, &de->RBuffer->P, len);
skb_queue_tail(&ccard->rcvq, skb);
eicon_schedule_rx(ccard);
eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n",
de->user[0], de->Ind, ind->IndId, de->RLength, de->complete);
}
}
memset(&(xlogreq->pcm), 0, sizeof(mi_pc_maint_t));
xlogreq->pcm.rc = 0;
xlogreq->pcm.req = 1; /* DO_LOG */
ram = ((char *)prram) + MIPS_MAINT_OFFS - divas_shared_offset;
ram_outb(card, ram+1, pcm->rc);
ram_outb(card, ram+0, pcm->req);
timeout = jiffies + 50;
while (timeout > jiffies) {
pcm->rc = ram_inb(card, ram+1);
pcm->req = ram_inb(card, ram+0);
if (!pcm->req) break;
SLEEP(10);
}
if (pcm->req) {
return XLOG_ERR_TIMEOUT;
}
if (pcm->rc != OK) {
return XLOG_ERR_DONE;
}
ram_copyfromcard(card, pcm, ram, len);
if (stype) {
for (i=0; i<8; i++)
((__u8 *)pcm)[11-i] = ((__u8 *)pcm)[9-i];
time = (__u32)pcm->data.w[2] * 3600 * 1000 +
(__u32)pcm->data.w[1] * 1000 +
(__u32)pcm->data.b[1] * 20 +
(__u32)pcm->data.b[0] ;
pcm->data.w[1] = (__u16) (time >> 16);
pcm->data.w[2] = (__u16) (time & 0x0000ffff);
pcm->data.w[0] = 2;
}
return XLOG_OK;
de->RNum = 0;
de->RNR = 0;
de->Rc = 0;
de->Ind = 0;
}
#endif /* CONFIG_ISDN_DRV_EICON_PCI */
/*
* Transmit-Function
*/
void
eicon_io_transmit(eicon_card *ccard) {
eicon_pci_card *pci_card;
eicon_isa_card *isa_card;
struct sk_buff *skb;
struct sk_buff *skb2;
unsigned long flags;
char *ram, *reg, *cfg;
eicon_pr_ram *prram = 0;
eicon_isa_com *com = 0;
eicon_REQ *ReqOut = 0;
@ -422,10 +303,11 @@ eicon_io_transmit(eicon_card *ccard) {
int ReqCount;
int scom = 0;
int tmp = 0;
int tmpid = 0;
int quloop = 1;
int dlev = 0;
ENTITY *ep = 0;
pci_card = &ccard->hwif.pci;
isa_card = &ccard->hwif.isa;
if (!ccard) {
@ -447,20 +329,17 @@ eicon_io_transmit(eicon_card *ccard) {
prram = (eicon_pr_ram *)isa_card->shmem;
break;
#endif
#ifdef CONFIG_ISDN_DRV_EICON_PCI
case EICON_CTYPE_MAESTRAP:
scom = 0;
ram = (char *)pci_card->PCIram;
reg = (char *)pci_card->PCIreg;
cfg = (char *)pci_card->PCIcfg;
prram = (eicon_pr_ram *)ram;
scom = 2;
break;
case EICON_CTYPE_MAESTRAQ:
scom = 2;
break;
case EICON_CTYPE_MAESTRA:
scom = 0;
ram = (char *)pci_card->PCIram;
reg = (char *)pci_card->PCIreg;
cfg = (char *)pci_card->PCIcfg;
prram = 0;
scom = 2;
break;
#endif
default:
eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");
return;
@ -470,69 +349,91 @@ eicon_io_transmit(eicon_card *ccard) {
if (!(skb2 = skb_dequeue(&ccard->sndq)))
quloop = 0;
while(quloop) {
save_flags(flags);
cli();
if (scom) {
spin_lock_irqsave(&eicon_lock, flags);
switch (scom) {
case 1:
if ((ram_inb(ccard, &com->Req)) || (ccard->ReadyInt)) {
if (!ccard->ReadyInt) {
tmp = ram_inb(ccard, &com->ReadyInt) + 1;
ram_outb(ccard, &com->ReadyInt, tmp);
ccard->ReadyInt++;
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
skb_queue_head(&ccard->sndq, skb2);
eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
return;
}
} else {
break;
case 0:
if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
skb_queue_head(&ccard->sndq, skb2);
eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
return;
}
break;
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
chan2 = (eicon_chan_ptr *)skb2->data;
chan = chan2->ptr;
if (!chan->e.busy) {
if((skb = skb_dequeue(&chan->e.X))) {
save_flags(flags);
cli();
reqbuf = (eicon_REQ *)skb->data;
if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {
eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No);
} else {
if (scom) {
spin_lock_irqsave(&eicon_lock, flags);
switch (scom) {
case 1:
ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh);
} else {
break;
case 0:
/* get address of next available request buffer */
ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)];
ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length);
ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);
ram_outb(ccard, &ReqOut->Req, reqbuf->Req);
break;
}
dlev = 160;
if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */
if (!reqbuf->Reference) { /* Signal Layer */
if (scom)
switch (scom) {
case 1:
ram_outb(ccard, &com->ReqId, chan->e.D3Id);
else
break;
case 0:
ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id);
break;
case 2:
ep = &chan->de;
break;
}
tmpid = chan->e.D3Id;
chan->e.ReqCh = 0;
}
else { /* Net Layer */
if (scom)
switch(scom) {
case 1:
ram_outb(ccard, &com->ReqId, chan->e.B2Id);
else
break;
case 0:
ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id);
break;
case 2:
ep = &chan->be;
break;
}
tmpid = chan->e.B2Id;
chan->e.ReqCh = 1;
if (((reqbuf->Req & 0x0f) == 0x08) ||
((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
@ -544,51 +445,106 @@ eicon_io_transmit(eicon_card *ccard) {
} else { /* It is an ASSIGN */
if (scom)
switch(scom) {
case 1:
ram_outb(ccard, &com->ReqId, reqbuf->ReqId);
else
break;
case 0:
ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId);
break;
case 2:
if (!reqbuf->Reference)
ep = &chan->de;
else
ep = &chan->be;
ep->Id = reqbuf->ReqId;
break;
}
tmpid = reqbuf->ReqId;
if (!reqbuf->Reference)
chan->e.ReqCh = 0;
else
chan->e.ReqCh = 1;
}
if (scom)
switch(scom) {
case 1:
chan->e.ref = ccard->ref_out++;
else
break;
case 0:
chan->e.ref = ram_inw(ccard, &ReqOut->Reference);
break;
case 2:
chan->e.ref = chan->No;
break;
}
chan->e.Req = reqbuf->Req;
ReqCount++;
if (scom)
switch (scom) {
case 1:
ram_outb(ccard, &com->Req, reqbuf->Req);
else
break;
case 0:
ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next));
break;
case 2:
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if (!ep) break;
ep->callback = eicon_idi_callback;
ep->R = (BUFFERS *)ccard;
ep->user[0] = (word)chan->No;
ep->user[1] = (word)tmpid;
ep->XNum = 1;
ep->RNum = 0;
ep->RNR = 0;
ep->Rc = 0;
ep->Ind = 0;
ep->X->PLength = reqbuf->XBuffer.length;
memcpy(ep->X->P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
ep->ReqCh = reqbuf->ReqCh;
ep->Req = reqbuf->Req;
#endif
break;
}
chan->e.busy = 1;
eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n",
reqbuf->Req,
(scom) ? ram_inb(ccard, &com->ReqId) :
ram_inb(ccard, &ReqOut->ReqId),
reqbuf->Req, tmpid,
reqbuf->ReqCh, reqbuf->XBuffer.length,
chan->e.ref);
spin_unlock_irqrestore(&eicon_lock, flags);
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if (scom == 2) {
if (ep) {
ccard->d->request(ep);
if (ep->Rc)
eicon_idi_callback(ep);
}
}
#endif
}
restore_flags(flags);
dev_kfree_skb(skb);
}
dev_kfree_skb(skb2);
}
else {
skb_queue_tail(&ccard->sackq, skb2);
eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No);
skb_queue_tail(&ccard->sackq, skb2);
eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No);
}
if (scom)
quloop = 0;
else
if (!(skb2 = skb_dequeue(&ccard->sndq)))
switch(scom) {
case 1:
quloop = 0;
break;
case 0:
case 2:
if (!(skb2 = skb_dequeue(&ccard->sndq)))
quloop = 0;
break;
}
}
if (!scom)
@ -599,18 +555,14 @@ eicon_io_transmit(eicon_card *ccard) {
}
}
#ifdef CONFIG_ISDN_DRV_EICON_ISA
/*
* IRQ handler
*/
void
eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
eicon_card *ccard = (eicon_card *)dev_id;
eicon_pci_card *pci_card;
eicon_isa_card *isa_card;
char *ram = 0;
char *reg = 0;
char *cfg = 0;
eicon_pr_ram *prram = 0;
eicon_isa_com *com = 0;
eicon_RC *RcIn;
@ -642,11 +594,9 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
}
}
pci_card = &ccard->hwif.pci;
isa_card = &ccard->hwif.isa;
switch(ccard->type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
@ -660,23 +610,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
prram = (eicon_pr_ram *)isa_card->shmem;
irqprobe = &isa_card->irqprobe;
break;
#endif
case EICON_CTYPE_MAESTRAP:
scom = 0;
ram = (char *)pci_card->PCIram;
reg = (char *)pci_card->PCIreg;
cfg = (char *)pci_card->PCIcfg;
irqprobe = &pci_card->irqprobe;
prram = (eicon_pr_ram *)ram;
break;
case EICON_CTYPE_MAESTRA:
scom = 0;
ram = (char *)pci_card->PCIram;
reg = (char *)pci_card->PCIreg;
cfg = (char *)pci_card->PCIcfg;
irqprobe = &pci_card->irqprobe;
prram = 0;
break;
default:
eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n");
return;
@ -684,7 +617,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
if (*irqprobe) {
switch(ccard->type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
@ -702,26 +634,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
}
(*irqprobe)++;
break;
#endif
case EICON_CTYPE_MAESTRAP:
if (readb(&ram[0x3fe])) {
writeb(0, &prram->RcOutput);
writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
writew(0, &cfg[MP_IRQ_RESET + 2]);
writeb(0, &ram[0x3fe]);
}
*irqprobe = 0;
break;
case EICON_CTYPE_MAESTRA:
outb(0x08, pci_card->PCIreg + M_RESET);
*irqprobe = 0;
break;
}
return;
}
switch(ccard->type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
@ -732,20 +649,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
return;
}
break;
#endif
case EICON_CTYPE_MAESTRAP:
if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */
eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
return;
}
break;
case EICON_CTYPE_MAESTRA:
outw(0x3fe, pci_card->PCIreg + M_ADDR);
if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */
eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
return;
}
break;
}
if (scom) {
@ -887,7 +790,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
/* clear interrupt */
switch(ccard->type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_QUADRO:
writeb(0, isa_card->intack);
writeb(0, &com[0x401]);
@ -898,19 +800,8 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
case EICON_CTYPE_S2M:
writeb(0, isa_card->intack);
break;
#endif
case EICON_CTYPE_MAESTRAP:
writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
writew(0, &cfg[MP_IRQ_RESET + 2]);
writeb(0, &ram[0x3fe]);
break;
case EICON_CTYPE_MAESTRA:
outb(0x08, pci_card->PCIreg + M_RESET);
outw(0x3fe, pci_card->PCIreg + M_ADDR);
outb(0, pci_card->PCIreg + M_DATA);
break;
}
return;
}
#endif

View File

@ -21,6 +21,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.8 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
*
* Revision 1.7 1999/11/18 21:14:30 armin
* New ISA memory mapped IO
*
@ -134,7 +138,6 @@ typedef struct {
unsigned char mvalid; /* Flag: Memory is valid */
unsigned char ivalid; /* Flag: IRQ is valid */
unsigned char master; /* Flag: Card ist Quadro 1/4 */
void* generic; /* Ptr to generic card struct */
} eicon_isa_card;
/* Offsets for special locations on standard cards */

View File

@ -31,6 +31,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.25 2000/02/22 16:26:40 armin
* Fixed membase error message.
* Fixed missing log buffer struct.
*
* Revision 1.24 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
@ -124,7 +128,10 @@
*
*/
#define DRIVERPATCH ""
#define DRIVERNAME "Eicon active ISDN driver"
#define DRIVERRELEASE "2.00"
#define DRIVERPATCH "B"
#include <linux/config.h>
#include <linux/module.h>
@ -135,6 +142,10 @@
#include "eicon.h"
#undef N_DATA
#include "adapter.h"
#include "uxio.h"
#define INCLUDE_INLINE_FUNCS
static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains
@ -146,6 +157,13 @@ extern char *eicon_pci_revision;
extern char *eicon_isa_revision;
extern char *eicon_idi_revision;
extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
unsigned int command, unsigned long arg);
extern void eicon_pci_init_conf(eicon_card *card);
void mod_inc_use_count(void);
void mod_dec_use_count(void);
extern char *file_check(void);
#ifdef MODULE
#define MOD_USE_COUNT (GET_USE_COUNT (&__this_module))
#endif
@ -154,6 +172,11 @@ extern char *eicon_idi_revision;
ulong DebugVar;
spinlock_t eicon_lock;
DESCRIPTOR idi_d[16];
int idi_dlength;
/* Parameters to be set by insmod */
#ifdef CONFIG_ISDN_DRV_EICON_ISA
static int membase = -1;
@ -185,23 +208,6 @@ char *eicon_ctype_name[] = {
"DIVA Server PRI/PCI"
};
static int
getrel(char *p)
{
int v = 0;
char *tmp = 0;
if ((tmp = strchr(p, '.')))
p = tmp + 1;
while (p[0] >= '0' && p[0] <= '9') {
v = ((v < 0) ? 0 : (v * 10)) + (int) (p[0] - '0');
p++;
}
return v;
}
static char *
eicon_getrev(const char *revision)
{
@ -225,146 +231,26 @@ find_channel(eicon_card *card, int channel)
return NULL;
}
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
/*
* Free MSN list
* Find pcicard with given card number
*/
static void
eicon_clear_msn(eicon_card *card)
static inline eicon_card *
eicon_findnpcicard(int driverid)
{
struct msn_entry *p = card->msn_list;
struct msn_entry *q;
unsigned long flags;
eicon_card *p = cards;
save_flags(flags);
cli();
card->msn_list = NULL;
restore_flags(flags);
while (p) {
q = p->next;
kfree(p);
p = q;
if ((p->regname[strlen(p->regname)-1] == (driverid + '0')) &&
(p->bus == EICON_BUS_PCI))
return p;
p = p->next;
}
}
/*
* Find an MSN entry in the list.
* If ia5 != 0, return IA5-encoded EAZ, else
* return a bitmask with corresponding bit set.
*/
static __u16
eicon_find_msn(eicon_card *card, char *msn, int ia5)
{
struct msn_entry *p = card->msn_list;
__u8 eaz = '0';
while (p) {
if (!strcmp(p->msn, msn)) {
eaz = p->eaz;
break;
}
p = p->next;
}
if (!ia5)
return (1 << (eaz - '0'));
else
return eaz;
}
/*
* Find an EAZ entry in the list.
* return a string with corresponding msn.
*/
char *
eicon_find_eaz(eicon_card *card, char eaz)
{
struct msn_entry *p = card->msn_list;
while (p) {
if (p->eaz == eaz)
return(p->msn);
p = p->next;
}
return("\0");
}
#if 0
/*
* Add or delete an MSN to the MSN list
*
* First character of msneaz is EAZ, rest is MSN.
* If length of eazmsn is 1, delete that entry.
*/
static int
eicon_set_msn(eicon_card *card, char *eazmsn)
{
struct msn_entry *p = card->msn_list;
struct msn_entry *q = NULL;
unsigned long flags;
int i;
if (!strlen(eazmsn))
return 0;
if (strlen(eazmsn) > 16)
return -EINVAL;
for (i = 0; i < strlen(eazmsn); i++)
if (!isdigit(eazmsn[i]))
return -EINVAL;
if (strlen(eazmsn) == 1) {
/* Delete a single MSN */
while (p) {
if (p->eaz == eazmsn[0]) {
save_flags(flags);
cli();
if (q)
q->next = p->next;
else
card->msn_list = p->next;
restore_flags(flags);
kfree(p);
eicon_log(card, 8,
"Mapping for EAZ %c deleted\n",
eazmsn[0]);
return 0;
}
q = p;
p = p->next;
}
return 0;
}
/* Add a single MSN */
while (p) {
/* Found in list, replace MSN */
if (p->eaz == eazmsn[0]) {
save_flags(flags);
cli();
strcpy(p->msn, &eazmsn[1]);
restore_flags(flags);
eicon_log(card, 8,
"Mapping for EAZ %c changed to %s\n",
eazmsn[0],
&eazmsn[1]);
return 0;
}
p = p->next;
}
/* Not found in list, add new entry */
p = kmalloc(sizeof(msn_entry), GFP_KERNEL);
if (!p)
return -ENOMEM;
p->eaz = eazmsn[0];
strcpy(p->msn, &eazmsn[1]);
p->next = card->msn_list;
save_flags(flags);
cli();
card->msn_list = p;
restore_flags(flags);
eicon_log(card, 8,
"Mapping %c -> %s added\n",
eazmsn[0],
&eazmsn[1]);
return 0;
return (eicon_card *) 0;
}
#endif
#endif /* CONFIG_PCI */
static void
eicon_rcv_dispatch(struct eicon_card *card)
@ -411,39 +297,18 @@ eicon_transmit(struct eicon_card *card)
}
}
static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq)
{
xlogreq_t *xlr;
int ret_val;
if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) {
eicon_log(card, 1, "idi_err: alloc_xlogreq_t failed\n");
return -ENOMEM;
}
if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) {
kfree(xlr);
return -EFAULT;
}
ret_val = eicon_get_xlog(card, xlr);
if (copy_to_user(xlogreq, xlr, sizeof(xlogreq_t))) {
kfree(xlr);
return -EFAULT;
}
kfree(xlr);
return ret_val;
}
static int
eicon_command(eicon_card * card, isdn_ctrl * c)
{
ulong a;
eicon_chan *chan;
eicon_cdef cdef;
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
dia_start_t dstart;
#endif
#endif
isdn_ctrl cmd;
char tmp[17];
int ret = 0;
unsigned long flags;
@ -463,10 +328,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
case EICON_BUS_ISA:
case EICON_BUS_MCA:
return (int)card->hwif.isa.shmem;
#if CONFIG_PCI
case EICON_BUS_PCI:
return card->hwif.pci.PCIram;
#endif
default:
eicon_log(card, 1,
"eicon: Illegal BUS type %d\n",
@ -507,10 +368,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
case EICON_BUS_ISA:
case EICON_BUS_MCA:
return card->hwif.isa.irq;
#if CONFIG_PCI
case EICON_BUS_PCI:
return card->hwif.pci.irq;
#endif
default:
eicon_log(card, 1,
"eicon: Illegal BUS type %d\n",
@ -588,7 +445,9 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
case EICON_IOCTL_MANIF:
if (!card->flags & EICON_FLAGS_RUNNING)
return -ENODEV;
if (!card->Feature & PROTCAP_MANIF)
if (!card->d)
return -ENODEV;
if (!card->d->features & DI_MANAGE)
return -ENODEV;
ret = eicon_idi_manage(
card,
@ -596,57 +455,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
return ret;
case EICON_IOCTL_GETXLOG:
if (!card->flags & EICON_FLAGS_RUNNING)
return XLOG_ERR_CARD_STATE;
ret = eicon_xlog(card, (xlogreq_t *)a);
return ret;
#if CONFIG_PCI
case EICON_IOCTL_LOADPCI:
if (card->flags & EICON_FLAGS_RUNNING)
return -EBUSY;
if (card->bus == EICON_BUS_PCI) {
switch(card->type) {
case EICON_CTYPE_MAESTRA:
ret = eicon_pci_load_bri(
&(card->hwif.pci),
&(((eicon_codebuf *)a)->pci));
break;
return -ENODEV;
case EICON_CTYPE_MAESTRAP:
ret = eicon_pci_load_pri(
&(card->hwif.pci),
&(((eicon_codebuf *)a)->pci));
break;
}
if (!ret) {
card->flags |= EICON_FLAGS_LOADED;
card->flags |= EICON_FLAGS_RUNNING;
if (card->hwif.pci.channels > 1) {
cmd.command = ISDN_STAT_ADDCH;
cmd.driver = card->myid;
cmd.arg = card->hwif.pci.channels - 1;
card->interface.statcallb(&cmd);
}
cmd.command = ISDN_STAT_RUN;
cmd.driver = card->myid;
cmd.arg = 0;
card->interface.statcallb(&cmd);
}
return ret;
} else return -ENODEV;
#endif
#if 0
case EICON_IOCTL_SETMSN:
if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp))))
return -EFAULT;
if ((ret = eicon_set_msn(card, tmp)))
return ret;
#if 0
if (card->flags & EICON_FLAGS_RUNNING)
return(eicon_capi_manufacturer_req_msn(card));
#endif
return 0;
#endif
case EICON_IOCTL_ADDCARD:
if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))
return -EFAULT;
@ -660,11 +470,77 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
#ifdef MODULE
case EICON_IOCTL_FREEIT:
while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT;
MOD_INC_USE_COUNT;
mod_inc_use_count();
return 0;
#endif
default:
case EICON_IOCTL_LOADPCI:
eicon_log(card, 1, "Eicon: Wrong version of load-utility,\n");
eicon_log(card, 1, "Eicon: re-compile eiconctrl !\n");
eicon_log(card, 1, "Eicon: Maybe update of utility is necessary !\n");
return -EINVAL;
default:
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if (c->arg < EICON_IOCTL_DIA_OFFSET)
return -EINVAL;
if (copy_from_user(&dstart, (char *)a, sizeof(dstart)))
return -1;
if (!(card = eicon_findnpcicard(dstart.card_id)))
return -EINVAL;
ret = do_ioctl(NULL, NULL,
c->arg - EICON_IOCTL_DIA_OFFSET,
(unsigned long) a);
if (((c->arg - EICON_IOCTL_DIA_OFFSET)==DIA_IOCTL_START) && (!ret)) {
if (card->type != EICON_CTYPE_MAESTRAQ) {
EtdM_DIDD_Read(idi_d, &idi_dlength);
card->d = &idi_d[idi_dlength - 1];
card->flags |= EICON_FLAGS_LOADED;
card->flags |= EICON_FLAGS_RUNNING;
eicon_pci_init_conf(card);
if (card->d->channels > 1) {
cmd.command = ISDN_STAT_ADDCH;
cmd.driver = card->myid;
cmd.arg = card->d->channels - 1;
card->interface.statcallb(&cmd);
}
cmd.command = ISDN_STAT_RUN;
cmd.driver = card->myid;
cmd.arg = 0;
card->interface.statcallb(&cmd);
eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x)\n",
(card->type == EICON_CTYPE_MAESTRA) ? "BRI" : "PRI",
card->d->channels, card->d->features);
} else {
int i;
EtdM_DIDD_Read(idi_d, &idi_dlength);
for(i = 3; i >= 0; i--) {
if (!(card = eicon_findnpcicard(dstart.card_id - i)))
return -EINVAL;
card->flags |= EICON_FLAGS_LOADED;
card->flags |= EICON_FLAGS_RUNNING;
card->d = &idi_d[idi_dlength - (i+1)];
eicon_pci_init_conf(card);
if (card->d->channels > 1) {
cmd.command = ISDN_STAT_ADDCH;
cmd.driver = card->myid;
cmd.arg = card->d->channels - 1;
card->interface.statcallb(&cmd);
}
cmd.command = ISDN_STAT_RUN;
cmd.driver = card->myid;
cmd.arg = 0;
card->interface.statcallb(&cmd);
eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x)\n",
4-i, card->d->channels, card->d->features);
}
}
}
return ret;
#else
return -EINVAL;
#endif
#endif /* CONFIG_PCI */
}
break;
case ISDN_CMD_DIAL:
@ -672,20 +548,15 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x1f)))
break;
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
eicon_log(card, 1, "Dial on channel %d with state %d\n",
chan->No, chan->fsm_state);
return -EBUSY;
}
if (card->ptype == ISDN_PTYPE_EURO)
tmp[0] = eicon_find_msn(card, c->parm.setup.eazmsn, 1);
else
tmp[0] = c->parm.setup.eazmsn[0];
chan->fsm_state = EICON_STATE_OCALL;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
ret = idi_connect_req(card, chan, c->parm.setup.phone,
c->parm.setup.eazmsn,
@ -723,19 +594,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
return -ENODEV;
if (!(chan = find_channel(card, c->arg & 0x1f)))
break;
if (strlen(c->parm.num)) {
if (card->ptype == ISDN_PTYPE_EURO) {
chan->eazmask = eicon_find_msn(card, c->parm.num, 0);
}
if (card->ptype == ISDN_PTYPE_1TR6) {
int i;
chan->eazmask = 0;
for (i = 0; i < strlen(c->parm.num); i++)
if (isdigit(c->parm.num[i]))
chan->eazmask |= (1 << (c->parm.num[i] - '0'));
}
} else
chan->eazmask = 0x3ff;
chan->eazmask = 0x3ff;
eicon_idi_listen_req(card, chan);
return 0;
case ISDN_CMD_CLREAZ:
@ -792,10 +651,10 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n");
return 0;
case ISDN_CMD_LOCK:
MOD_INC_USE_COUNT;
mod_inc_use_count();
return 0;
case ISDN_CMD_UNLOCK:
MOD_DEC_USE_COUNT;
mod_dec_use_count();
return 0;
#ifdef CONFIG_ISDN_TTY_FAX
case ISDN_CMD_FAXCMD:
@ -885,8 +744,7 @@ if_readstatus(u_char * buf, int len, int user, int id, int channel)
if (!card->flags & EICON_FLAGS_RUNNING)
return -ENODEV;
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
while((skb = skb_dequeue(&card->statq))) {
if ((skb->len + count) > len)
@ -909,12 +767,12 @@ if_readstatus(u_char * buf, int len, int user, int id, int channel)
} else {
skb_pull(skb, cnt);
skb_queue_head(&card->statq, skb);
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
return count;
}
}
card->statq_entries = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
return count;
}
printk(KERN_ERR
@ -993,12 +851,11 @@ eicon_putstatus(eicon_card * card, char * buf)
return;
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
count = strlen(buf);
skb = alloc_skb(count, GFP_ATOMIC);
if (!skb) {
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
printk(KERN_ERR "eicon: could not alloc skb in putstatus\n");
return;
}
@ -1016,7 +873,7 @@ eicon_putstatus(eicon_card * card, char * buf)
} else
card->statq_entries++;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
if (count) {
cmd.command = ISDN_STAT_STAVAIL;
cmd.driver = card->myid;
@ -1074,9 +931,6 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
char qid[5];
#endif
eicon_card *card;
#if CONFIG_PCI
eicon_pci_card *pcic;
#endif
qloop = (Type == EICON_CTYPE_QUADRO)?2:0;
for (i = 0; i <= qloop; i++) {
@ -1186,9 +1040,9 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
card->interface.channels = 1;
break;
#endif
#if CONFIG_PCI
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
case EICON_CTYPE_MAESTRA:
(eicon_pci_card *)pcic = (eicon_pci_card *)membase;
card->bus = EICON_BUS_PCI;
card->interface.features |=
ISDN_FEATURE_L2_V11096 |
@ -1199,11 +1053,26 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
ISDN_FEATURE_L3_TRANSDSP |
ISDN_FEATURE_L3_FCLASS2;
card->hwif.pci.card = (void *)card;
card->hwif.pci.PCIreg = pcic->PCIreg;
card->hwif.pci.PCIcfg = pcic->PCIcfg;
card->hwif.pci.master = 1;
card->hwif.pci.mvalid = pcic->mvalid;
card->hwif.pci.ivalid = 0;
card->hwif.pci.irq = irq;
card->hwif.pci.type = Type;
card->flags = 0;
card->nchannels = 2;
card->interface.channels = 1;
break;
case EICON_CTYPE_MAESTRAQ:
card->bus = EICON_BUS_PCI;
card->interface.features |=
ISDN_FEATURE_L2_V11096 |
ISDN_FEATURE_L2_V11019 |
ISDN_FEATURE_L2_V11038 |
ISDN_FEATURE_L2_MODEM |
ISDN_FEATURE_L2_FAX |
ISDN_FEATURE_L3_TRANSDSP |
ISDN_FEATURE_L3_FCLASS2;
card->hwif.pci.card = (void *)card;
card->hwif.pci.master = 1;
card->hwif.pci.irq = irq;
card->hwif.pci.type = Type;
card->flags = 0;
@ -1212,7 +1081,6 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
break;
case EICON_CTYPE_MAESTRAP:
(eicon_pci_card *)pcic = (eicon_pci_card *)membase;
card->bus = EICON_BUS_PCI;
card->interface.features |=
ISDN_FEATURE_L2_V11096 |
@ -1223,13 +1091,6 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
ISDN_FEATURE_L3_TRANSDSP |
ISDN_FEATURE_L3_FCLASS2;
card->hwif.pci.card = (void *)card;
card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
card->hwif.pci.PCIreg = pcic->PCIreg;
card->hwif.pci.PCIram = pcic->PCIram;
card->hwif.pci.PCIcfg = pcic->PCIcfg;
card->hwif.pci.master = 1;
card->hwif.pci.mvalid = pcic->mvalid;
card->hwif.pci.ivalid = 0;
card->hwif.pci.irq = irq;
card->hwif.pci.type = Type;
card->flags = 0;
@ -1237,6 +1098,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
card->interface.channels = 1;
break;
#endif
#endif
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_ISABRI:
if (membase == -1)
@ -1295,6 +1157,53 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
skb_queue_head_init(&card->bch[j].e.X);
skb_queue_head_init(&card->bch[j].e.R);
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
/* *** Diva Server *** */
if (!(card->dbuf = (DBUFFER *) kmalloc((sizeof(DBUFFER) * (card->nchannels + 1))*2
, GFP_KERNEL))) {
eicon_log(card, 1,
"eicon: (%s) Could not allocate DBUFFER-struct.\n", id);
kfree(card);
kfree(card->bch);
return;
}
if (!(card->sbuf = (BUFFERS *) kmalloc((sizeof(BUFFERS) * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
eicon_log(card, 1,
"eicon: (%s) Could not allocate BUFFERS-struct.\n", id);
kfree(card);
kfree(card->bch);
kfree(card->dbuf);
return;
}
if (!(card->sbufp = (char *) kmalloc((270 * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
eicon_log(card, 1,
"eicon: (%s) Could not allocate BUFFERSP-struct.\n", id);
kfree(card);
kfree(card->bch);
kfree(card->dbuf);
kfree(card->sbuf);
return;
}
for (j=0; j< (card->nchannels + 1); j++) {
memset((char *)&card->dbuf[j], 0, sizeof(DBUFFER));
card->bch[j].de.RBuffer = (DBUFFER *)&card->dbuf[j];
memset((char *)&card->dbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
card->bch[j].be.RBuffer = (DBUFFER *)&card->dbuf[j+(card->nchannels+1)];
memset((char *)&card->sbuf[j], 0, sizeof(BUFFERS));
card->bch[j].de.X = (BUFFERS *)&card->sbuf[j];
memset((char *)&card->sbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
card->bch[j].be.X = (BUFFERS *)&card->sbuf[j+(card->nchannels+1)];
memset((char *)&card->sbufp[j], 0, 270);
card->bch[j].de.X->P = (char *)&card->sbufp[j * 270];
memset((char *)&card->sbufp[j+(card->nchannels+1)], 0, 270);
card->bch[j].be.X->P = (char *)&card->sbufp[(j+(card->nchannels+1)) * 270];
}
/* *** */
#endif /* CONFIG_ISDN_DRV_EICON_PCI */
card->next = cards;
cards = card;
}
@ -1318,10 +1227,7 @@ eicon_registercard(eicon_card * card)
#endif /* CONFIG_MCA */
#endif
case EICON_BUS_PCI:
#if CONFIG_PCI
eicon_pci_printpar(&card->hwif.pci);
break;
#endif
default:
eicon_log(card, 1,
"eicon_registercard: Illegal BUS type %d\n",
@ -1358,10 +1264,7 @@ unregister_card(eicon_card * card)
break;
#endif
case EICON_BUS_PCI:
#if CONFIG_PCI
eicon_pci_release(&card->hwif.pci);
break;
#endif
default:
eicon_log(card, 1,
"eicon: Invalid BUS type %d\n",
@ -1393,7 +1296,11 @@ eicon_freecard(eicon_card *card) {
while((skb = skb_dequeue(&card->statq)))
dev_kfree_skb(skb);
eicon_clear_msn(card);
#ifdef CONFIG_ISDN_DRV_EICON_PCI
kfree(card->sbufp);
kfree(card->sbuf);
kfree(card->dbuf);
#endif
kfree(card->bch);
kfree(card);
}
@ -1431,11 +1338,13 @@ eicon_addcard(int Type, int membase, int irq, char *id)
break;
#endif
case EICON_BUS_PCI:
#if CONFIG_PCI
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if (eicon_registercard(p))
break;
registered = 1;
break;
#endif
#endif
default:
printk(KERN_ERR
@ -1469,8 +1378,6 @@ eicon_addcard(int Type, int membase, int irq, char *id)
return (added - failed);
}
#define DRIVERNAME "Eicon active ISDN driver"
#define DRIVERRELEASE "1"
#ifdef MODULE
#define eicon_init init_module
@ -1480,35 +1387,30 @@ int
eicon_init(void)
{
int card_count = 0;
int release = 0;
char tmprev[50];
DebugVar = 1;
eicon_lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
printk(KERN_INFO "%s Rev: ", DRIVERNAME);
strcpy(tmprev, eicon_revision);
printk("%s/", eicon_getrev(tmprev));
release += getrel(tmprev);
strcpy(tmprev, eicon_pci_revision);
#if CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
printk("%s/", eicon_getrev(tmprev));
#else
printk("---/");
#endif
release += getrel(tmprev);
strcpy(tmprev, eicon_isa_revision);
#ifdef CONFIG_ISDN_DRV_EICON_ISA
printk("%s/", eicon_getrev(tmprev));
#else
printk("---/");
#endif
release += getrel(tmprev);
strcpy(tmprev, eicon_idi_revision);
printk("%s\n", eicon_getrev(tmprev));
release += getrel(tmprev);
sprintf(tmprev,"%d", release);
printk(KERN_INFO "%s Release: %s.%s%s\n", DRIVERNAME,
DRIVERRELEASE, tmprev, DRIVERPATCH);
printk(KERN_INFO "%s Release: %s%s (%s)\n", DRIVERNAME,
DRIVERRELEASE, DRIVERPATCH, file_check());
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
@ -1529,14 +1431,19 @@ eicon_init(void)
#endif /* CONFIG_MCA */
#endif /* CONFIG_ISDN_DRV_EICON_ISA */
#if CONFIG_PCI
#ifdef CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
DivasCardsDiscover();
card_count += eicon_pci_find_card(id);
#endif
#endif
if (!cards) {
#ifdef MODULE
#ifndef CONFIG_PCI
#ifndef CONFIG_ISDN_DRV_EICON_PCI
#ifndef CONFIG_ISDN_DRV_EICON_ISA
printk(KERN_INFO "Eicon: Driver is neither ISA nor PCI compiled !\n");
printk(KERN_INFO "Eicon: Driver not loaded !\n");
#else
printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n");
#endif
@ -1549,17 +1456,47 @@ eicon_init(void)
} else
printk(KERN_INFO "Eicon: %d card%s added\n", card_count,
(card_count>1)?"s":"");
/* No symbols to export, hide all symbols */
EXPORT_NO_SYMBOLS;
return 0;
}
#ifdef MODULE
void mod_inc_use_count(void)
{
MOD_INC_USE_COUNT;
}
void mod_dec_use_count(void)
{
MOD_DEC_USE_COUNT;
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
void EtdM_DIDD_Write(DESCRIPTOR *, int);
EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Read);
EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Write);
EXPORT_SYMBOL_NOVERS(DivasPrintf);
#else
int DivasCardNext;
card_t DivasCards[1];
#endif
void
cleanup_module(void)
{
#if CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
card_t *pCard;
word wCardIndex;
extern int Divas_major;
int iTmp = 0;
#endif
#endif
eicon_card *card = cards;
eicon_card *last;
while (card) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
#ifdef CONFIG_MCA
@ -1579,6 +1516,54 @@ cleanup_module(void)
card = card->next;
eicon_freecard(last);
}
#if CONFIG_PCI
#ifdef CONFIG_ISDN_DRV_EICON_PCI
pCard = DivasCards;
for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
{
if ((pCard->hw) && (pCard->hw->in_use))
{
(*pCard->card_reset)(pCard);
UxIsrRemove(pCard->hw, pCard);
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
if(pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
{
release_region(pCard->hw->io_base,0x20);
release_region(pCard->hw->reset_base,0x80);
}
// If this is a 4BRI ...
if (pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
{
// Skip over the next 3 virtual adapters
wCardIndex += 3;
// But free their handles
for (iTmp = 0; iTmp < 3; iTmp++)
{
pCard++;
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
}
}
}
pCard++;
}
unregister_chrdev(Divas_major, "Divas");
#endif
#endif /* CONFIG_PCI */
printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
}

View File

@ -26,6 +26,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.11 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
*
* Revision 1.10 1999/08/22 20:26:49 calle
* backported changes from kernel 2.3.14:
* - several #include "config.h" gone, others come.
@ -76,894 +80,75 @@
#include "eicon.h"
#include "eicon_pci.h"
#undef N_DATA
#include "adapter.h"
#include "uxio.h"
char *eicon_pci_revision = "$Revision$";
#if CONFIG_PCI /* intire stuff is only for PCI */
#undef EICON_PCI_DEBUG
#ifdef CONFIG_ISDN_DRV_EICON_PCI
int eicon_pci_find_card(char *ID)
{
if (pci_present()) {
struct pci_dev *pdev = NULL;
int pci_nextindex=0, pci_cards=0, pci_akt=0;
int pci_type = PCI_MAESTRA;
int NoMorePCICards = FALSE;
char *ram, *reg, *cfg;
unsigned int pram=0, preg=0, pcfg=0;
char did[12];
eicon_pci_card *aparms;
int pci_cards = 0;
int ctype = 0;
char did[20];
card_t *pCard;
word wCardIndex;
if (!(aparms = (eicon_pci_card *) kmalloc(sizeof(eicon_pci_card), GFP_KERNEL))) {
printk(KERN_WARNING
"eicon_pci: Could not allocate card-struct.\n");
return 0;
}
for (pci_cards = 0; pci_cards < 0x0f; pci_cards++)
{
do {
if ((pdev = pci_find_device(PCI_VENDOR_EICON,
pci_type,
pdev)))
pCard = DivasCards;
for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
{
pci_nextindex++;
break;
}
else {
pci_nextindex = 0;
switch (pci_type) /* switch to next card type */
{
case PCI_MAESTRA:
pci_type = PCI_MAESTRAQ; break;
case PCI_MAESTRAQ:
pci_type = PCI_MAESTRAQ_U; break;
case PCI_MAESTRAQ_U:
pci_type = PCI_MAESTRAP; break;
default:
case PCI_MAESTRAP:
NoMorePCICards = TRUE;
}
}
}
while (!NoMorePCICards);
if (NoMorePCICards)
{
if (pci_cards < 1) {
printk(KERN_INFO "Eicon: No supported PCI cards found.\n");
kfree(aparms);
return 0;
}
else
{
printk(KERN_INFO "Eicon: %d PCI card%s registered.\n",
pci_cards, (pci_cards > 1) ? "s":"");
kfree(aparms);
return (pci_cards);
}
}
pci_akt = 0;
switch(pci_type)
{
case PCI_MAESTRA:
printk(KERN_INFO "Eicon: DIVA Server BRI/PCI detected !\n");
aparms->type = EICON_CTYPE_MAESTRA;
aparms->irq = pdev->irq;
preg = get_pcibase(pdev, 2) & 0xfffffffc;
pcfg = get_pcibase(pdev, 1) & 0xffffff80;
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", preg);
printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", pcfg);
#endif
pci_akt = 1;
break;
case PCI_MAESTRAQ:
case PCI_MAESTRAQ_U:
printk(KERN_ERR "Eicon: DIVA Server 4BRI/PCI detected but not supported !\n");
pci_cards--;
pci_akt = 0;
break;
case PCI_MAESTRAP:
printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n");
aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/
aparms->irq = pdev->irq;
pram = get_pcibase(pdev, 0) & 0xfffff000;
preg = get_pcibase(pdev, 2) & 0xfffff000;
pcfg = get_pcibase(pdev, 4) & 0xfffff000;
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
printk(KERN_DEBUG "eicon_pci: ram=0x%x\n",
(pram));
printk(KERN_DEBUG "eicon_pci: reg=0x%x\n",
(preg));
printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n",
(pcfg));
#endif
pci_akt = 1;
break;
default:
printk(KERN_ERR "eicon_pci: Unknown PCI card detected !\n");
pci_cards--;
pci_akt = 0;
break;
}
if (pci_akt) {
/* remapping memory */
switch(pci_type)
if ((pCard->hw) && (pCard->hw->in_use))
{
case PCI_MAESTRA:
aparms->PCIreg = (unsigned int) preg;
aparms->PCIcfg = (unsigned int) pcfg;
if (check_region((aparms->PCIreg), 0x20)) {
printk(KERN_WARNING "eicon_pci: reg port already in use !\n");
aparms->PCIreg = 0;
break;
} else {
request_region(aparms->PCIreg, 0x20, "eicon reg");
switch(pCard->hw->card_type) {
case DIA_CARD_TYPE_DIVA_SERVER:
ctype = EICON_CTYPE_MAESTRAP;
break;
case DIA_CARD_TYPE_DIVA_SERVER_B:
ctype = EICON_CTYPE_MAESTRA;
break;
case DIA_CARD_TYPE_DIVA_SERVER_Q:
ctype = EICON_CTYPE_MAESTRAQ;
break;
default:
}
if (check_region((aparms->PCIcfg), 0x80)) {
printk(KERN_WARNING "eicon_pci: cfg port already in use !\n");
aparms->PCIcfg = 0;
release_region(aparms->PCIreg, 0x20);
break;
} else {
request_region(aparms->PCIcfg, 0x80, "eicon cfg");
}
break;
case PCI_MAESTRAQ:
case PCI_MAESTRAQ_U:
case PCI_MAESTRAP:
aparms->shmem = (eicon_pci_shmem *) ioremap(pram, 0x10000);
ram = (u8 *) ((u32)aparms->shmem + MP_SHARED_RAM_OFFSET);
reg = ioremap(preg, 0x4000);
cfg = ioremap(pcfg, 0x1000);
aparms->PCIram = (unsigned int) ram;
aparms->PCIreg = (unsigned int) reg;
aparms->PCIcfg = (unsigned int) cfg;
break;
}
if ((!aparms->PCIreg) || (!aparms->PCIcfg)) {
printk(KERN_ERR "eicon_pci: Card could not be added !\n");
pci_cards--;
} else {
aparms->mvalid = 1;
sprintf(did, "%s%d", (strlen(ID) < 1) ? "eicon":ID, pci_cards);
printk(KERN_INFO "%s: DriverID: '%s'\n",eicon_ctype_name[aparms->type] , did);
if (!(eicon_addcard(aparms->type, (int) aparms, aparms->irq, did))) {
if ((!ctype) || (!(eicon_addcard(ctype, 0, pCard->hw->irq, did)))) {
printk(KERN_ERR "eicon_pci: Card could not be added !\n");
pci_cards--;
} else {
pci_cards++;
printk(KERN_INFO "%s: DriverID: '%s'\n",eicon_ctype_name[ctype] , did);
}
}
pCard++;
}
}
} else
printk(KERN_ERR "eicon_pci: Kernel compiled with PCI but no PCI-bios found !\n");
return 0;
}
/*
* Checks protocol file id for "F#xxxx" string fragment to
* extract the features, supported by this protocol version.
* binary representation of the feature string value is returned
* in *value. The function returns 0 if feature string was not
* found or has a wrong format, else 1.
*/
static int GetProtFeatureValue(char *sw_id, int *value)
{
__u8 i, offset;
while (*sw_id)
{
if ((sw_id[0] == 'F') && (sw_id[1] == '#'))
{
sw_id = &sw_id[2];
for (i=0, *value=0; i<4; i++, sw_id++)
{
if ((*sw_id >= '0') && (*sw_id <= '9'))
{
offset = '0';
}
else if ((*sw_id >= 'A') && (*sw_id <= 'F'))
{
offset = 'A' + 10;
}
else if ((*sw_id >= 'a') && (*sw_id <= 'f'))
{
offset = 'a' + 10;
}
else
{
return 0;
}
*value |= (*sw_id - offset) << (4*(3-i));
}
return 1;
}
else
{
sw_id++;
}
}
return 0;
}
void
eicon_pci_printpar(eicon_pci_card *card) {
switch (card->type) {
case EICON_CTYPE_MAESTRA:
printk(KERN_INFO "%s at 0x%x / 0x%x, irq %d\n",
eicon_ctype_name[card->type],
(unsigned int)card->PCIreg,
(unsigned int)card->PCIcfg,
card->irq);
break;
case EICON_CTYPE_MAESTRAQ:
case EICON_CTYPE_MAESTRAQ_U:
case EICON_CTYPE_MAESTRAP:
printk(KERN_INFO "%s at 0x%x, irq %d\n",
eicon_ctype_name[card->type],
(unsigned int)card->shmem,
card->irq);
#ifdef EICON_PCI_DEBUG
printk(KERN_INFO "eicon_pci: remapped ram= 0x%x\n",(unsigned int)card->PCIram);
printk(KERN_INFO "eicon_pci: remapped reg= 0x%x\n",(unsigned int)card->PCIreg);
printk(KERN_INFO "eicon_pci: remapped cfg= 0x%x\n",(unsigned int)card->PCIcfg);
#endif
break;
}
}
static void
eicon_pci_release_shmem(eicon_pci_card *card) {
if (!card->master)
return;
if (card->mvalid) {
switch (card->type) {
case EICON_CTYPE_MAESTRA:
/* reset board */
outb(0, card->PCIcfg + 0x4c); /* disable interrupts from PLX */
outb(0, card->PCIreg + M_RESET);
SLEEP(20);
outb(0, card->PCIreg + M_ADDRH);
outw(0, card->PCIreg + M_ADDR);
outw(0, card->PCIreg + M_DATA);
release_region(card->PCIreg, 0x20);
release_region(card->PCIcfg, 0x80);
break;
case EICON_CTYPE_MAESTRAQ:
case EICON_CTYPE_MAESTRAQ_U:
case EICON_CTYPE_MAESTRAP:
/* reset board */
writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
SLEEP(20);
writeb(0, card->PCIreg + MP_RESET);
SLEEP(20);
iounmap((void *)card->shmem);
iounmap((void *)card->PCIreg);
iounmap((void *)card->PCIcfg);
break;
}
}
card->mvalid = 0;
}
static void
eicon_pci_release_irq(eicon_pci_card *card) {
if (!card->master)
return;
if (card->ivalid)
free_irq(card->irq, card);
card->ivalid = 0;
return pci_cards;
}
void
eicon_pci_release(eicon_pci_card *card) {
eicon_pci_release_irq(card);
eicon_pci_release_shmem(card);
}
/*
* Upload buffer content to adapters shared memory
* on verify error, 1 is returned and a message is printed on screen
* else 0 is returned
* Can serve IO-Type and Memory type adapters
*/
int eicon_upload(t_dsp_download_space *p_para,
__u16 length, /* byte count */
__u8 *buffer,
int verify)
eicon_pci_init_conf(eicon_card *card)
{
__u32 i, dwdata = 0, val = 0, timeout;
__u16 data;
eicon_pci_boot *boot = 0;
int j;
switch (p_para->type) /* actions depend on type of union */
{
case DL_PARA_IO_TYPE:
for (i=0; i<length; i+=2)
{
outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR);
/* outw (((u16 *)code)[i >> 1], p_para->dat.io.ioDATA); */
outw (*(u16 *)&buffer[i], p_para->dat.io.ioDATA);
}
if (verify) /* check written block */
{
for (i=0; i<length; i+=2)
{
outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR);
data = inw(p_para->dat.io.ioDATA);
if (data != *(u16 *)&buffer[i])
{
p_para->dat.io.r3addr += i;
p_para->dat.io.BadData = data;
p_para->dat.io.GoodData = *(u16 *)&buffer[i];
return 1;
}
}
}
break;
/* initializing some variables */
card->ReadyInt = 0;
case DL_PARA_MEM_TYPE:
boot = p_para->dat.mem.boot;
writel(p_para->dat.mem.r3addr, &boot->addr);
for (i=0; i<length; i+=4)
{
writel(((u32 *)buffer)[i >> 2], &boot->data[i]);
}
if (verify) /* check written block */
{
for (i=0; i<length; i+=4)
{
dwdata = readl(&boot->data[i]);
if (((u32 *)buffer)[i >> 2] != dwdata)
{
p_para->dat.mem.r3addr += i;
p_para->dat.mem.BadData = dwdata;
p_para->dat.mem.GoodData = ((u32 *)buffer)[i >> 2];
return 1;
}
}
}
writel(((length + 3) / 4), &boot->len); /* len in dwords */
writel(2, &boot->cmd);
for(j = 0; j < 256; j++)
card->IdTable[j] = NULL;
timeout = jiffies + 20;
while (timeout > jiffies) {
val = readl(&boot->cmd);
if (!val) break;
SLEEP(2);
for(j = 0; j < (card->d->channels + 1); j++) {
card->bch[j].e.busy = 0;
card->bch[j].e.D3Id = 0;
card->bch[j].e.B2Id = 0;
card->bch[j].e.ref = 0;
card->bch[j].e.Req = 0;
card->bch[j].e.complete = 1;
card->bch[j].fsm_state = EICON_STATE_NULL;
}
if (val)
{
p_para->dat.mem.timeout = 1;
return 1;
}
break;
}
return 0;
}
/* show header information of code file */
static
int eicon_pci_print_hdr(unsigned char *code, int offset)
{
unsigned char hdr[80];
int i, fvalue = 0;
i = 0;
while ((i < (sizeof(hdr) -1))
&& (code[offset + i] != '\0')
&& (code[offset + i] != '\r')
&& (code[offset + i] != '\n'))
{
hdr[i] = code[offset + i];
i++;
}
hdr[i] = '\0';
printk(KERN_DEBUG "Eicon: loading %s\n", hdr);
if (GetProtFeatureValue(hdr, &fvalue)) return(fvalue);
else return(0);
}
/*
* Configure a card, download code into BRI card,
* check if we get interrupts and return 0 on succes.
* Return -ERRNO on failure.
*/
int
eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
int i,j;
int timeout;
unsigned int offset, offp=0, size, length;
int signature = 0;
int FeatureValue = 0;
eicon_pci_codebuf cbuf;
t_dsp_download_space dl_para;
t_dsp_download_desc dsp_download_table;
unsigned char *code;
unsigned int reg;
unsigned int cfg;
if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
return -EFAULT;
reg = card->PCIreg;
cfg = card->PCIcfg;
/* reset board */
outb(0, reg + M_RESET);
SLEEP(10);
outb(0, reg + M_ADDRH);
outw(0, reg + M_ADDR);
outw(0, reg + M_DATA);
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: reset card\n");
#endif
/* clear shared memory */
outb(0xff, reg + M_ADDRH);
outw(0, reg + M_ADDR);
for(i = 0; i < 0xffff; i++) outw(0, reg + M_DATA);
SLEEP(10);
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: clear shared memory\n");
#endif
/* download protocol and dsp file */
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
#endif
/* Allocate code-buffer */
if (!(code = kmalloc(400, GFP_KERNEL))) {
printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
return -ENOMEM;
}
/* prepare protocol upload */
dl_para.type = DL_PARA_IO_TYPE;
dl_para.dat.io.ioADDR = reg + M_ADDR;
dl_para.dat.io.ioADDRH = reg + M_ADDRH;
dl_para.dat.io.ioDATA = reg + M_DATA;
for (j = 0; j <= cbuf.dsp_code_num; j++)
{
if (j == 0) size = cbuf.protocol_len;
else size = cbuf.dsp_code_len[j];
offset = 0;
if (j == 0) dl_para.dat.io.r3addr = 0;
if (j == 1) dl_para.dat.io.r3addr = M_DSP_CODE_BASE +
((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
if (j == 2) dl_para.dat.io.r3addr = M_DSP_CODE_BASE;
if (j == 3) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + sizeof(__u32);
do /* download block of up to 400 bytes */
{
length = ((size - offset) >= 400) ? 400 : (size - offset);
if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
kfree(code);
return -EFAULT;
}
if ((offset == 0) && (j < 2)) {
FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80);
#ifdef EICON_PCI_DEBUG
if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%04x.\n", FeatureValue);
#endif
if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
kfree(code);
return -EFAULT;
}
((eicon_card *)card->card)->Feature = FeatureValue;
}
if (eicon_upload(&dl_para, length, code, 1))
{
printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
kfree(code);
return -EIO;
}
/* move onto next block */
offset += length;
dl_para.dat.io.r3addr += length;
} while (offset < size);
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "Eicon: %d bytes loaded.\n", offset);
#endif
offp += size;
}
kfree(code);
/* clear signature */
outb(0xff, reg + M_ADDRH);
outw(0x1e, reg + M_ADDR);
outw(0, reg + M_DATA);
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
#endif
/* copy configuration data into shared memory */
outw(8, reg + M_ADDR); outb(cbuf.tei, reg + M_DATA);
outw(9, reg + M_ADDR); outb(cbuf.nt2, reg + M_DATA);
outw(10,reg + M_ADDR); outb(0, reg + M_DATA);
outw(11,reg + M_ADDR); outb(cbuf.WatchDog, reg + M_DATA);
outw(12,reg + M_ADDR); outb(cbuf.Permanent, reg + M_DATA);
outw(13,reg + M_ADDR); outb(0, reg + M_DATA); /* XInterface */
outw(14,reg + M_ADDR); outb(cbuf.StableL2, reg + M_DATA);
outw(15,reg + M_ADDR); outb(cbuf.NoOrderCheck, reg + M_DATA);
outw(16,reg + M_ADDR); outb(0, reg + M_DATA); /* HandsetType */
outw(17,reg + M_ADDR); outb(0, reg + M_DATA); /* SigFlags */
outw(18,reg + M_ADDR); outb(cbuf.LowChannel, reg + M_DATA);
outw(19,reg + M_ADDR); outb(cbuf.ProtVersion, reg + M_DATA);
outw(20,reg + M_ADDR); outb(cbuf.Crc4, reg + M_DATA);
outw(21,reg + M_ADDR); outb((cbuf.Loopback) ? 2:0, reg + M_DATA);
for (i=0;i<32;i++)
{
outw( 32+i, reg + M_ADDR); outb(cbuf.l[0].oad[i], reg + M_DATA);
outw( 64+i, reg + M_ADDR); outb(cbuf.l[0].osa[i], reg + M_DATA);
outw( 96+i, reg + M_ADDR); outb(cbuf.l[0].spid[i], reg + M_DATA);
outw(128+i, reg + M_ADDR); outb(cbuf.l[1].oad[i], reg + M_DATA);
outw(160+i, reg + M_ADDR); outb(cbuf.l[1].osa[i], reg + M_DATA);
outw(192+i, reg + M_ADDR); outb(cbuf.l[1].spid[i], reg + M_DATA);
}
#ifdef EICON_PCI_DEBUG
printk(KERN_ERR "eicon_pci: starting CPU...\n");
#endif
/* let the CPU run */
outw(0x08, reg + M_RESET);
timeout = jiffies + (5*HZ);
while (timeout > jiffies) {
outw(0x1e, reg + M_ADDR);
signature = inw(reg + M_DATA);
if (signature == DIVAS_SIGNATURE) break;
SLEEP(2);
}
if (signature != DIVAS_SIGNATURE)
{
#ifdef EICON_PCI_DEBUG
printk(KERN_ERR "eicon_pci: signature 0x%x expected 0x%x\n",signature,DIVAS_SIGNATURE);
#endif
printk(KERN_ERR "eicon_pci: Timeout, protocol code not running !\n");
return -EIO;
}
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
#endif
/* get serial number and number of channels supported by card */
outb(0xff, reg + M_ADDRH);
outw(0x3f6, reg + M_ADDR);
card->channels = inw(reg + M_DATA);
card->serial = (u32)inw(cfg + 0x22) << 16 | (u32)inw(cfg + 0x26);
printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
/* test interrupt */
card->irqprobe = 1;
if (!card->ivalid) {
if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card))
{
printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
return -EIO;
}
}
card->ivalid = 1;
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
#endif
/* Trigger an interrupt and check if it is delivered */
outb(0x41, cfg + 0x4c); /* enable PLX for interrupts */
outb(0x89, reg + M_RESET); /* place int request */
timeout = jiffies + 20;
while (timeout > jiffies) {
if (card->irqprobe != 1) break;
SLEEP(5);
}
if (card->irqprobe == 1) {
free_irq(card->irq, card);
card->ivalid = 0;
printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
return -EIO;
}
/* initializing some variables */
((eicon_card *)card->card)->ReadyInt = 0;
for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
for(j=0; j< (card->channels + 1); j++) {
((eicon_card *)card->card)->bch[j].e.busy = 0;
((eicon_card *)card->card)->bch[j].e.D3Id = 0;
((eicon_card *)card->card)->bch[j].e.B2Id = 0;
((eicon_card *)card->card)->bch[j].e.ref = 0;
((eicon_card *)card->card)->bch[j].e.Req = 0;
((eicon_card *)card->card)->bch[j].e.complete = 1;
((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
}
printk(KERN_INFO "Eicon: Card successfully started\n");
return 0;
}
/*
* Configure a card, download code into PRI card,
* check if we get interrupts and return 0 on succes.
* Return -ERRNO on failure.
*/
int
eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
eicon_pci_boot *boot;
eicon_pr_ram *prram;
int i,j;
int timeout;
int FeatureValue = 0;
unsigned int offset, offp=0, size, length;
unsigned long int signature = 0;
t_dsp_download_space dl_para;
t_dsp_download_desc dsp_download_table;
eicon_pci_codebuf cbuf;
unsigned char *code;
unsigned char req_int;
char *ram, *reg, *cfg;
if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
return -EFAULT;
boot = &card->shmem->boot;
ram = (char *)card->PCIram;
reg = (char *)card->PCIreg;
cfg = (char *)card->PCIcfg;
prram = (eicon_pr_ram *)ram;
/* reset board */
writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
SLEEP(20);
writeb(0, card->PCIreg + MP_RESET);
SLEEP(20);
/* set command count to 0 */
writel(0, &boot->reserved);
/* check if CPU increments the life word */
i = readw(&boot->live);
SLEEP(20);
if (i == readw(&boot->live)) {
printk(KERN_ERR "eicon_pci: card is reset, but CPU not running !\n");
return -EIO;
}
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: reset card OK (CPU running)\n");
#endif
/* download firmware : DSP and Protocol */
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
#endif
/* Allocate code-buffer */
if (!(code = kmalloc(400, GFP_KERNEL))) {
printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
return -ENOMEM;
}
/* prepare protocol upload */
dl_para.type = DL_PARA_MEM_TYPE;
dl_para.dat.mem.boot = boot;
for (j = 0; j <= cbuf.dsp_code_num; j++)
{
if (j==0) size = cbuf.protocol_len;
else size = cbuf.dsp_code_len[j];
if (j==1) writel(MP_DSP_ADDR, &boot->addr); /* DSP code entry point */
if (j == 0) dl_para.dat.io.r3addr = MP_PROTOCOL_ADDR;
if (j == 1) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE +
((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
if (j == 2) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE;
if (j == 3) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + sizeof(__u32);
offset = 0;
do /* download block of up to 400 bytes */
{
length = ((size - offset) >= 400) ? 400 : (size - offset);
if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
kfree(code);
return -EFAULT;
}
if ((offset == 0) && (j < 2)) {
FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80);
#ifdef EICON_PCI_DEBUG
if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%x.\n", FeatureValue);
#endif
if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
kfree(code);
return -EFAULT;
}
((eicon_card *)card->card)->Feature = FeatureValue;
}
if (eicon_upload(&dl_para, length, code, 1))
{
if (dl_para.dat.mem.timeout == 0)
printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
else
printk(KERN_ERR "eicon_pci: timeout, no ACK to load !\n");
kfree(code);
return -EIO;
}
/* move onto next block */
offset += length;
dl_para.dat.mem.r3addr += length;
} while (offset < size);
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: %d bytes loaded.\n", offset);
#endif
offp += size;
}
kfree(code);
/* initialize the adapter data structure */
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
#endif
/* clear out config space */
for (i = 0; i < 256; i++) writeb(0, &ram[i]);
/* copy configuration down to the card */
writeb(cbuf.tei, &ram[8]);
writeb(cbuf.nt2, &ram[9]);
writeb(0, &ram[10]);
writeb(cbuf.WatchDog, &ram[11]);
writeb(cbuf.Permanent, &ram[12]);
writeb(cbuf.XInterface, &ram[13]);
writeb(cbuf.StableL2, &ram[14]);
writeb(cbuf.NoOrderCheck, &ram[15]);
writeb(cbuf.HandsetType, &ram[16]);
writeb(0, &ram[17]);
writeb(cbuf.LowChannel, &ram[18]);
writeb(cbuf.ProtVersion, &ram[19]);
writeb(cbuf.Crc4, &ram[20]);
for (i = 0; i < 32; i++)
{
writeb(cbuf.l[0].oad[i], &ram[32 + i]);
writeb(cbuf.l[0].osa[i], &ram[64 + i]);
writeb(cbuf.l[0].spid[i], &ram[96 + i]);
writeb(cbuf.l[1].oad[i], &ram[128 + i]);
writeb(cbuf.l[1].osa[i], &ram[160 + i]);
writeb(cbuf.l[1].spid[i], &ram[192 + i]);
}
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: configured card OK\n");
#endif
/* start adapter */
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: tell card to start...\n");
#endif
writel(MP_PROTOCOL_ADDR, &boot->addr); /* RISC code entry point */
writel(3, &boot->cmd); /* DIVAS_START_CMD */
/* wait till card ACKs */
timeout = jiffies + (5*HZ);
while (timeout > jiffies) {
signature = readl(&boot->signature);
if ((signature >> 16) == DIVAS_SIGNATURE) break;
SLEEP(2);
}
if ((signature >> 16) != DIVAS_SIGNATURE)
{
#ifdef EICON_PCI_DEBUG
printk(KERN_ERR "eicon_pci: signature 0x%lx expected 0x%x\n",(signature >> 16),DIVAS_SIGNATURE);
#endif
printk(KERN_ERR "eicon_pci: timeout, protocol code not running !\n");
return -EIO;
}
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
#endif
/* get serial number and number of channels supported by card */
card->channels = readb(&ram[0x3f6]);
card->serial = readl(&ram[0x3f0]);
printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
/* test interrupt */
readb(&ram[0x3fe]);
writeb(0, &ram[0x3fe]); /* reset any pending interrupt */
readb(&ram[0x3fe]);
writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
writew(0, &cfg[MP_IRQ_RESET + 2]);
card->irqprobe = 1;
if (!card->ivalid) {
if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card))
{
printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
return -EIO;
}
}
card->ivalid = 1;
req_int = readb(&prram->ReadyInt);
#ifdef EICON_PCI_DEBUG
printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
#endif
req_int++;
/* Trigger an interrupt and check if it is delivered */
writeb(req_int, &prram->ReadyInt);
timeout = jiffies + 20;
while (timeout > jiffies) {
if (card->irqprobe != 1) break;
SLEEP(2);
}
if (card->irqprobe == 1) {
free_irq(card->irq, card);
card->ivalid = 0;
printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
return -EIO;
}
/* initializing some variables */
((eicon_card *)card->card)->ReadyInt = 0;
for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
for(j=0; j< (card->channels + 1); j++) {
((eicon_card *)card->card)->bch[j].e.busy = 0;
((eicon_card *)card->card)->bch[j].e.D3Id = 0;
((eicon_card *)card->card)->bch[j].e.B2Id = 0;
((eicon_card *)card->card)->bch[j].e.ref = 0;
((eicon_card *)card->card)->bch[j].e.Req = 0;
((eicon_card *)card->card)->bch[j].e.complete = 1;
((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
}
printk(KERN_INFO "Eicon: Card successfully started\n");
return 0;
}
#endif /* CONFIG_PCI */

View File

@ -20,6 +20,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.4 2000/01/23 21:21:23 armin
* Added new trace capability and some updates.
* DIVA Server BRI now supports data for ISDNLOG.
*
* Revision 1.3 1999/03/29 11:19:51 armin
* I/O stuff now in seperate file (eicon_io.c)
* Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
@ -42,145 +46,17 @@
#ifdef __KERNEL__
#define PCI_VENDOR_EICON 0x1133
#define PCI_DIVA_PRO20 0xe001 /* Not supported */
#define PCI_DIVA20 0xe002 /* Not supported */
#define PCI_DIVA_PRO20_U 0xe003 /* Not supported */
#define PCI_DIVA20_U 0xe004 /* Not supported */
#define PCI_MAESTRA 0xe010
#define PCI_MAESTRAQ 0xe012
#define PCI_MAESTRAQ_U 0xe013
#define PCI_MAESTRAP 0xe014
#define DIVA_PRO20 1
#define DIVA20 2
#define DIVA_PRO20_U 3
#define DIVA20_U 4
#define MAESTRA 5
#define MAESTRAQ 6
#define MAESTRAQ_U 7
#define MAESTRAP 8
#define TRUE 1
#define FALSE 0
#define DIVAS_SIGNATURE 0x4447
/* MAESTRA BRI PCI */
#define M_RESET 0x10 /* offset of reset register */
#define M_DATA 0x00 /* offset of data register */
#define M_ADDR 0x04 /* offset of address register */
#define M_ADDRH 0x0c /* offset of high address register */
#define M_DSP_CODE_LEN 0xbf7d0000
#define M_DSP_CODE 0xbf7d0004 /* max 128K DSP-Code */
#define M_DSP_CODE_BASE 0xbf7a0000
#define M_MAX_DSP_CODE_SIZE 0x00050000 /* max 320K DSP-Code (Telindus) */
/* MAESTRA PRI PCI */
#define MP_SHARED_RAM_OFFSET 0x1000 /* offset of shared RAM base in the DRAM memory bar */
#define MP_IRQ_RESET 0xc18 /* offset of interrupt status register in the CONFIG memory bar */
#define MP_IRQ_RESET_VAL 0xfe /* value to clear an interrupt */
#define MP_PROTOCOL_ADDR 0xa0011000 /* load address of protocol code */
#define MP_DSP_ADDR 0xa03c0000 /* load address of DSP code */
#define MP_MAX_PROTOCOL_CODE_SIZE 0x000a0000 /* max 640K Protocol-Code */
#define MP_DSP_CODE_BASE 0xa03a0000
#define MP_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code */
#define MP_RESET 0x20 /* offset of RESET register in the DEVICES memory bar */
/* RESET register bits */
#define _MP_S2M_RESET 0x10 /* active lo */
#define _MP_LED2 0x08 /* 1 = on */
#define _MP_LED1 0x04 /* 1 = on */
#define _MP_DSP_RESET 0x02 /* active lo */
#define _MP_RISC_RESET 0x81 /* active hi, bit 7 for compatibility with old boards */
/* boot interface structure */
typedef struct {
__u32 cmd __attribute__ ((packed));
__u32 addr __attribute__ ((packed));
__u32 len __attribute__ ((packed));
__u32 err __attribute__ ((packed));
__u32 live __attribute__ ((packed));
__u32 reserved[(0x1020>>2)-6] __attribute__ ((packed));
__u32 signature __attribute__ ((packed));
__u8 data[1]; /* real interface description */
} eicon_pci_boot;
#define DL_PARA_IO_TYPE 0
#define DL_PARA_MEM_TYPE 1
typedef struct tag_dsp_download_space
{
__u16 type; /* see definitions above to differ union elements */
union
{
struct
{
__u32 r3addr;
__u16 ioADDR;
__u16 ioADDRH;
__u16 ioDATA;
__u16 BadData; /* in case of verify error */
__u16 GoodData;
} io; /* for io based adapters */
struct
{
__u32 r3addr;
eicon_pci_boot *boot;
__u32 BadData; /* in case of verify error */
__u32 GoodData;
__u16 timeout;
} mem; /* for memory based adapters */
} dat;
} t_dsp_download_space;
/* Shared memory */
typedef union {
eicon_pci_boot boot;
} eicon_pci_shmem;
/*
* card's description
*/
typedef struct {
int ramsize;
int irq; /* IRQ */
unsigned int PCIram;
unsigned int PCIreg;
unsigned int PCIcfg;
long int serial; /* Serial No. */
int channels; /* No. of supported channels */
void* card;
eicon_pci_shmem* shmem; /* Shared-memory area */
unsigned char* intack; /* Int-Acknowledge */
unsigned char* stopcpu; /* Writing here stops CPU */
unsigned char* startcpu; /* Writing here starts CPU */
unsigned char type; /* card type */
unsigned char irqprobe; /* Flag: IRQ-probing */
unsigned char mvalid; /* Flag: Memory is valid */
unsigned char ivalid; /* Flag: IRQ is valid */
unsigned char master; /* Flag: Card is Quadro 1/4 */
void* generic; /* Ptr to generic card struct */
} eicon_pci_card;
extern int eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb);
extern int eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb);
extern void eicon_pci_release(eicon_pci_card *card);
extern void eicon_pci_printpar(eicon_pci_card *card);
extern int eicon_pci_find_card(char *ID);
#endif /* __KERNEL__ */

View File

@ -0,0 +1,33 @@
/* $Id$
*
* (c) 2000 Cytronics & Melware
*
* This file is (c) under GNU PUBLIC LICENSE
* For changes and modifications please read
* ../../../Documentation/isdn/README.eicon
*
* $Log$
*
*
*/
#include <linux/kernel.h>
char *
file_check(void) {
#ifdef FILECHECK
#if FILECHECK == 0
return("verified");
#endif
#if FILECHECK == 1
return("modified");
#endif
#if FILECHECK == 127
return("verification failed");
#endif
#else
return("not verified");
#endif
}

View File

@ -0,0 +1,531 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.4
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* Diva Server 4BRI specific part of initialisation */
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "constant.h"
#include "adapter.h"
#include "uxio.h"
#define TEST_INT_DIVAS_Q 0x13
#define DIVAS_MAINT_OFFSET 0xff00 /* value for 4BRI card */
#define MQ_BOARD_DSP_OFFSET 0x00a00000
#define MQ_DSP1_ADDR_OFFSET 0x00000008
#define MQ_DSP_JUNK_OFFSET 0x00000400
#define MQ_DSP1_DATA_OFFSET 0x00000000
#define MQ_BOARD_ISAC_DSP_RESET 0x00800028
#define MQ_BREG_RISC 0x1200 /* RISC Reset */
#define MQ_ISAC_DSP_RESET 0x0028 /* ISAC and DSP reset address offset */
#define MQ_RISC_COLD_RESET_MASK 0x0001 /* RISC Cold reset */
#define MQ_RISC_WARM_RESET_MASK 0x0002 /* RISC Warm reset */
#define MQ_IRQ_REQ_ON 0x1
#define MQ_IRQ_REQ_OFF 0x0
#define MQ_BREG_IRQ_TEST 0x0608
#define PLX9054_INTCSR 0x69
#define PLX9054_INT_ENA 0x09
byte mem_in(ADAPTER *a, void *adr);
word mem_inw(ADAPTER *a, void *adr);
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
void mem_out(ADAPTER *a, void *adr, byte data);
void mem_outw(ADAPTER *a, void *adr, word data);
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_inc(ADAPTER *a, void *adr);
int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg);
int FPGA_Download(word, dword, byte *, byte *, int);
extern byte FPGA_Bytes[];
extern void *get_card(int);
void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
word GetProtFeatureValue(char *sw_id);
void memcp(byte *dst, byte *src, dword dwLen);
int memcm(byte *dst, byte *src, dword dwLen);
static int diva_server_4bri_reset(card_t *card)
{
byte *ctl;
DPRINTF(("divas: reset Diva Server 4BRI"));
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
/* stop RISC, DSP's and ISAC */
UxCardMemOut(card->hw, &ctl[MQ_BREG_RISC], 0);
UxCardMemOut(card->hw, &ctl[MQ_ISAC_DSP_RESET], 0);
UxCardMemDetach(card->hw, ctl);
return 0;
}
static int diva_server_4bri_config(card_t *card, dia_config_t *config)
{
byte *shared;
int i, j;
DPRINTF(("divas: configure Diva Server 4BRI"));
shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
for (i=0; i<256; i++)
{
UxCardMemOut(card->hw, &shared[i], 0);
}
UxCardMemOut(card->hw, &shared[ 8], config->tei);
UxCardMemOut(card->hw, &shared[ 9], config->nt2);
UxCardMemOut(card->hw, &shared[10], 0);
UxCardMemOut(card->hw, &shared[11], config->watchdog);
UxCardMemOut(card->hw, &shared[12], config->permanent);
UxCardMemOut(card->hw, &shared[13], config->x_interface);
UxCardMemOut(card->hw, &shared[14], config->stable_l2);
UxCardMemOut(card->hw, &shared[15], config->no_order_check);
UxCardMemOut(card->hw, &shared[16], config->handset_type);
UxCardMemOut(card->hw, &shared[17], 0);
UxCardMemOut(card->hw, &shared[18], config->low_channel);
UxCardMemOut(card->hw, &shared[19], config->prot_version);
UxCardMemOut(card->hw, &shared[20], config->crc4);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
DPRINTF(("divas: Signifying V.90"));
UxCardMemOut(card->hw, &shared[22], 4);
}
else
{
UxCardMemOut(card->hw, &shared[22], 0);
}
for (i=0; i<2; i++)
{
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
}
}
UxCardMemDetach(card->hw, shared);
return 0;
}
static
void diva_server_4bri_reset_int(card_t *card)
{
byte *ctl;
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
UxCardMemDetach(card->hw, ctl);
return;
}
static int diva_server_4bri_test_int(card_t *card)
{
byte *ctl, i;
byte *reg;
DPRINTF(("divas: test interrupt for Diva Server 4BRI"));
/* We get the last (dummy) adapter in so we need to go back to the first */
card = get_card(card->cfg.card_id - 3);
/* Enable interrupts on PLX chip */
reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
UxCardPortIoOut(card->hw, reg, PLX9054_INTCSR, PLX9054_INT_ENA);
UxCardMemDetach(card->hw, reg);
/* Set the test interrupt flag */
card->test_int_pend = TEST_INT_DIVAS_Q;
/* Now to trigger the interrupt */
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_ON);
UxCardMemDetach(card->hw, ctl);
for (i = 0; i < 50; i++)
{
if (!card->test_int_pend)
{
break;
}
UxPause(10);
}
if (card->test_int_pend)
{
DPRINTF(("active: timeout waiting for card to interrupt"));
return (-1);
}
return 0;
}
static void print_hdr(unsigned char *code, int offset)
{
unsigned char hdr[80];
int i;
i = 0;
while ((i < (DIM(hdr) -1)) &&
(code[offset + i] != '\0') &&
(code[offset + i] != '\r') &&
(code[offset + i] != '\n'))
{
hdr[i] = code[offset + i];
i++;
}
hdr[i] = '\0';
DPRINTF(("divas: loading %s", hdr));
}
static int diva_server_4bri_load(card_t *card, dia_load_t *load)
{
byte *pRAM=NULL;
int download_offset=0;
card_t *FirstCard;
byte sw_id[80];
DPRINTF(("divas: loading Diva Server 4BRI[%d]", load->card_id));
switch(load->code_type)
{
case DIA_CPU_CODE:
DPRINTF(("divas: RISC code LRLRLRLR"));
print_hdr(load->code, 0x80);
card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
download_offset = 0; // Protocol code written to offset 0
pRAM = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
break;
case DIA_DSP_CODE:
DPRINTF(("divas: DSP code"));
print_hdr(load->code, 0x0);
FirstCard = get_card(load->card_id - 3);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
download_offset = MQ_V90D_DSP_CODE_BASE;
}
else
{
download_offset = MQ_ORG_DSP_CODE_BASE;
}
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
download_offset += (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC);
break;
case DIA_TABLE_CODE:
DPRINTF(("divas: TABLE code"));
FirstCard = get_card(load->card_id - 3);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
download_offset = MQ_V90D_DSP_CODE_BASE + sizeof(dword);
}
else
{
download_offset = MQ_ORG_DSP_CODE_BASE + sizeof(dword);
}
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
break;
case DIA_CONT_CODE:
DPRINTF(("divas: continuation code"));
break;
case DIA_DLOAD_CNT:
DPRINTF(("divas: COUNT code"));
FirstCard = get_card(load->card_id - 3);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
download_offset = MQ_V90D_DSP_CODE_BASE;
}
else
{
download_offset = MQ_ORG_DSP_CODE_BASE;
}
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
break;
case DIA_FPGA_CODE:
DPRINTF(("divas: 4BRI FPGA download - %d bytes", load->length));
if (FPGA_Download(IDI_ADAPTER_MAESTRAQ,
card->hw->io_base,
sw_id,
load->code,
load->length
) == -1)
{
DPRINTF(("divas: FPGA download failed"));
return -1;
}
/* NOW reset the 4BRI */
diva_server_4bri_reset(card);
return 0; // No need for anything further loading
default:
DPRINTF(("divas: unknown code type"));
return -1;
}
memcp(pRAM + (download_offset & 0x3FFFFF), load->code, load->length);
{
int mism_off;
if ((mism_off = memcm(pRAM + (download_offset & 0x3FFFFF), load->code, load->length)))
{
DPRINTF(("divas: memory mismatch at offset %d", mism_off));
UxCardMemDetach(card->hw, pRAM);
return -1;
}
}
UxCardMemDetach(card->hw, pRAM);
return 0;
}
static int diva_server_4bri_start(card_t *card, byte *channels)
{
byte *ctl;
byte *shared, i;
int adapter_num;
DPRINTF(("divas: start Diva Server 4BRI"));
*channels = 0;
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_COLD_RESET_MASK);
UxPause(2);
UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
UxPause(10);
UxCardMemDetach(card->hw, ctl);
shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
for ( i = 0 ; i < 300 ; ++i )
{
UxPause (10) ;
if ( UxCardMemInW(card->hw, &shared[0x1E]) == 0x4447 )
{
DPRINTF(("divas: Protocol startup time %d.%02d seconds",
(i / 100), (i % 100) ));
break;
}
}
if (i==300)
{
DPRINTF(("divas: Timeout starting card"));
DPRINTF(("divas: Signature == 0x%04X", UxCardMemInW(card->hw, &shared[0x1E])));
UxCardMemDetach(card->hw, shared);
return -1;
}
UxCardMemDetach(card->hw, shared);
for (adapter_num=3; adapter_num >= 0; adapter_num--)
{
card_t *qbri_card;
qbri_card = get_card(card->cfg.card_id - adapter_num);
if (qbri_card)
{
shared = UxCardMemAttach(qbri_card->hw, DIVAS_SHARED_MEMORY);
*channels += UxCardMemIn(qbri_card->hw, &shared[0x3F6]);
UxCardMemDetach(qbri_card->hw, shared);
}
else
{
DPRINTF(("divas: Couldn't get card info %d", card->cfg.card_id));
}
}
diva_server_4bri_test_int(card);
return 0;
}
static
int diva_server_4bri_mem_get(card_t *card, mem_block_t *mem_block)
{
byte *a;
byte *card_addr;
word length = 0;
int i;
a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
card_addr = a;
card_addr += mem_block->addr;
for (i=0; i < sizeof(mem_block->data); i++)
{
mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
card_addr++;
length++;
}
UxCardMemDetach(card->hw, a);
return length;
}
/*
* Initialise 4BRI specific entry points
*/
int Divas4BriInit(card_t *card, dia_card_t *cfg)
{
// byte sw_id[80];
// extern int FPGA_Done;
DPRINTF(("divas: initialise Diva Server 4BRI"));
if (Divas4BRIInitPCI(card, cfg) == -1)
{
return -1;
}
/* Need to download the FPGA */
/* if (!FPGA_Done)
{
int retVal;
retVal=FPGA_Download(IDI_ADAPTER_MAESTRAQ,
cfg->io_base,
sw_id,
FPGA_Bytes
);
if(retVal==-1)
{
DPRINTF(("divas: FPGA Download Failed"));
return -1;
}
FPGA_Done = 1;
} */
card->card_reset = diva_server_4bri_reset;
card->card_load = diva_server_4bri_load;
card->card_config = diva_server_4bri_config;
card->card_start = diva_server_4bri_start;
card->reset_int = diva_server_4bri_reset_int;
card->card_mem_get = diva_server_4bri_mem_get;
card->xlog_offset = DIVAS_MAINT_OFFSET;
card->out = DivasOut;
card->test_int = DivasTestInt;
card->dpc = DivasDpc;
card->clear_int = DivasClearInt;
card->a.ram_out = mem_out;
card->a.ram_outw = mem_outw;
card->a.ram_out_buffer = mem_out_buffer;
card->a.ram_inc = mem_inc;
card->a.ram_in = mem_in;
card->a.ram_inw = mem_inw;
card->a.ram_in_buffer = mem_in_buffer;
card->a.ram_look_ahead = mem_look_ahead;
return 0;
}
void memcp(byte *dst, byte *src, dword dwLen)
{
while (dwLen)
{
*dst = *src;
dst++; src++;
dwLen--;
}
}
int memcm(byte *dst, byte *src, dword dwLen)
{
int offset = 0;
while (offset < dwLen)
{
if(*dst != *src)
return (offset+1);
offset++;
src++;
dst++;
}
return 0;
}

158
drivers/isdn/eicon/fpga.c Normal file
View File

@ -0,0 +1,158 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "sys.h"
#include "idi.h"
#include "uxio.h"
#define FPGA_PORT 0x6E
#define FPGA_DLOAD_BUFLEN 256
#define NAME_OFFSET 0x10
#define NAME_MAXLEN 12
#define DATE_OFFSET 0x2c
#define DATE_MAXLEN 10
word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
void UxPause(long int);
/*-------------------------------------------------------------------------*/
/* Loads the FPGA configuration file onto the hardware. */
/* Function returns 0 on success, else an error number. */
/* On success, an identifier string is returned in the buffer */
/* */
/* A buffer of FPGA_BUFSIZE, a handle to the already opened bitstream */
/* file and a file read function has to be provided by the operating */
/* system part. */
/* ----------------------------------------------------------------------- */
int FPGA_Download( word cardtype,
dword RegBase,
byte *strbuf,
byte FPGA_SRC[],
int FPGA_LEN
)
{
word i, j, k;
word baseval, Mask_PROGRAM, Mask_DONE, Mask_CCLK, Mask_DIN;
dword addr;
byte *pFPGA;
//--- check for legal cardtype
switch (cardtype)
{
case IDI_ADAPTER_MAESTRAQ:
addr = RegBase ; // address where to access FPGA
Mask_PROGRAM = 0x0001; // FPGA pins at address
Mask_DONE = 0x0002;
Mask_CCLK = 0x0100;
Mask_DIN = 0x0400;
baseval = 0x000d; // PROGRAM hi, CCLK lo, DIN lo by default
break;
default:
DPRINTF(("divas: FPGA Download ,Illegal Card"));
return -1; // illegal card
}
//--- generate id string from file content
for (j=NAME_OFFSET, k=0; j<(NAME_OFFSET+NAME_MAXLEN); j++, k++) //name
{
if (!FPGA_SRC[j]) break;
strbuf[k] = FPGA_SRC[j];
}
strbuf[k++] = ' ';
for (j=DATE_OFFSET; j<(DATE_OFFSET+DATE_MAXLEN); j++, k++) // date
{
if (!FPGA_SRC[j]) break;
strbuf[k] = FPGA_SRC[j];
}
strbuf[k] = 0;
DPRINTF(("divas: FPGA Download - %s", strbuf));
//--- prepare download, Pulse PROGRAM pin down.
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval &~Mask_PROGRAM); // PROGRAM low pulse
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // release
UxPause(50); // wait until FPGA finised internal memory clear
//--- check done pin, must be low
if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE)
{
DPRINTF(("divas: FPGA_ERR_DONE_WRONG_LEVEL"));
return -1;
}
pFPGA = FPGA_SRC;
i = 0;
/* Move past the header */
while ((FPGA_SRC[i] != 0xFF) && (i < FPGA_LEN))
{
i++;
}
// We've hit the 0xFF so move on to the next byte
// i++;
DPRINTF(("divas: FPGA Code starts at offset %d", i));
//--- put data onto the FPGA
for (;i<FPGA_LEN; i++)
{
//--- put byte onto FPGA
for (j=0; j<8; j++)
{
if (FPGA_SRC[i] &(0x80>>j)) baseval |= Mask_DIN; // write a hi
else baseval &=~Mask_DIN; // write a lo
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval);
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK); // set CCLK hi
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // set CCLK lo
}
}
//--- add some additional startup clock cycles and check done pin
for (i=0; i<5; i++)
{
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK); // set CCLK hi
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // set CCLK lo
}
UxPause(100);
if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE)
{
DPRINTF(("divas: FPGA download successful"));
}
else
{
DPRINTF(("divas: FPGA download failed - 0x%x", UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT)));
return -1;
}
return 0;
}

885
drivers/isdn/eicon/idi.c Normal file
View File

@ -0,0 +1,885 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.6
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Core driver for Diva Server cards
* Implements the IDI interface
*/
#include "idi.h"
#include "adapter.h"
#include "pc.h"
#include "pr_pc.h"
#include "sys.h"
#include "uxio.h"
/* IDI request functions */
static void request(card_t *card, ENTITY *e);
static void req_0(ENTITY *e) { request(&DivasCards[ 0], e); }
static void req_1(ENTITY *e) { request(&DivasCards[ 1], e); }
static void req_2(ENTITY *e) { request(&DivasCards[ 2], e); }
static void req_3(ENTITY *e) { request(&DivasCards[ 3], e); }
static void req_4(ENTITY *e) { request(&DivasCards[ 4], e); }
static void req_5(ENTITY *e) { request(&DivasCards[ 5], e); }
static void req_6(ENTITY *e) { request(&DivasCards[ 6], e); }
static void req_7(ENTITY *e) { request(&DivasCards[ 7], e); }
static void req_8(ENTITY *e) { request(&DivasCards[ 8], e); }
static void req_9(ENTITY *e) { request(&DivasCards[ 9], e); }
static void req_10(ENTITY *e) { request(&DivasCards[10], e); }
static void req_11(ENTITY *e) { request(&DivasCards[11], e); }
static void req_12(ENTITY *e) { request(&DivasCards[12], e); }
static void req_13(ENTITY *e) { request(&DivasCards[13], e); }
static void req_14(ENTITY *e) { request(&DivasCards[14], e); }
static void req_15(ENTITY *e) { request(&DivasCards[15], e); }
IDI_CALL DivasIdiRequest[16] =
{
&req_0, &req_1, &req_2, &req_3,
&req_4, &req_5, &req_6, &req_7,
&req_8, &req_9, &req_10, &req_11,
&req_12, &req_13, &req_14, &req_15
};
#define PR_RAM ((struct pr_ram *)0)
#define RAM ((struct dual *)0)
/*------------------------------------------------------------------*/
/* local function prototypes */
/*------------------------------------------------------------------*/
static byte isdn_rc(ADAPTER *, byte, byte, byte, word);
static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
/*
* IDI related functions
*/
static
ENTITY *entity_ptr(ADAPTER *a, byte e_no)
{
card_t *card;
card = a->io;
return card->e_tbl[e_no].e;
}
static
void CALLBACK(ADAPTER *a, ENTITY *e)
{
card_t *card = a->io;
if (card->log_types & DIVAS_LOG_IDI)
{
DivasLogIdi(card, e, FALSE);
}
(*e->callback)(e);
}
static
void *PTR_P(ADAPTER *a, ENTITY *e, void *P)
{
return(P);
}
static
void *PTR_R(ADAPTER *a, ENTITY *e)
{
return(e->R);
}
static
void *PTR_X(ADAPTER *a, ENTITY *e)
{
return(e->X);
}
static
void free_entity(ADAPTER *a, byte e_no)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_tbl[e_no].e = NULL;
card->e_count--;
UxCardUnlock(card->hw, ipl);
return;
}
static
void assign_queue(ADAPTER * a, byte e_no, word ref)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_tbl[e_no].assign_ref = ref;
card->e_tbl[e_no].next = card->assign;
card->assign = e_no;
UxCardUnlock(card->hw, ipl);
return;
}
static
byte get_assign(ADAPTER *a, word ref)
{
card_t *card;
byte e_no;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
e_no = card->assign;
while (e_no)
{
if (card->e_tbl[e_no].assign_ref == ref)
{
break;
}
e_no = card->e_tbl[e_no].next;
}
UxCardUnlock(card->hw, ipl);
return e_no;
}
static
void req_queue(ADAPTER * a, byte e_no)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_tbl[e_no].next = 0;
if (card->e_head)
{
card->e_tbl[card->e_tail].next = e_no;
card->e_tail = e_no;
}
else
{
card->e_head = e_no;
card->e_tail = e_no;
}
UxCardUnlock(card->hw, ipl);
return;
}
static
byte look_req(ADAPTER * a)
{
card_t *card;
card = a->io;
return(card->e_head);
}
static
void next_req(ADAPTER * a)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_head = card->e_tbl[card->e_head].next;
if (!card->e_head)
{
card->e_tail = 0;
}
UxCardUnlock(card->hw, ipl);
return;
}
/*
* IDI request function for active cards
*/
static
void request(card_t *card, ENTITY *e)
{
word *special_req;
int i;
int ipl;
if (card->log_types & DIVAS_LOG_IDI)
{
DivasLogIdi(card, e, TRUE);
}
if (!e->Req)
{
special_req = (word *) e;
switch (*special_req)
{
case REQ_REMOVE:
return;
case REQ_NAME:
for (i=0; i < DIM(card->cfg.name); i++)
{
((struct get_name_s *) e)->name[i] = card->cfg.name[i];
}
return;
case REQ_SERIAL:
case REQ_XLOG:
DPRINTF(("IDI: attempted REQ_SERIAL or REQ_XLOG"));
return;
default:
return;
}
}
ipl = UxCardLock(card->hw);
if (!(e->Id & 0x1f))
{
DPRINTF(("IDI: ASSIGN req"));
for (i = 1; i < card->e_max; i++)
{
if (!card->e_tbl[i].e)
{
break;
}
}
if (i == card->e_max)
{
DPRINTF(("IDI: request all ids in use (IDI req ignored)"));
UxCardUnlock(card->hw, ipl);
e->Rc = OUT_OF_RESOURCES;
return;
}
card->e_tbl[i].e = e;
card->e_count++;
e->No = (byte) i;
e->More = 0;
e->RCurrent = 0xff;
}
else
{
i = e->No;
}
if (e->More & XBUSY)
{
DPRINTF(("IDI: request - entity is busy"));
UxCardUnlock(card->hw, ipl);
return;
}
e->More |= XBUSY;
e->More &= ~ XMOREF;
e->XCurrent = 0;
e->XOffset = 0;
card->e_tbl[i].next = 0;
if(card->e_head)
{
card->e_tbl[card->e_tail].next = i;
card->e_tail = i;
}
else
{
card->e_head = i;
card->e_tail = i;
}
UxCardUnlock(card->hw, ipl);
card->out(&card->a);
return;
}
static byte pr_ready(ADAPTER * a)
{
byte ReadyCount;
ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
a->ram_in(a, &PR_RAM->ReqInput));
if(!ReadyCount) {
if(!a->ReadyInt) {
a->ram_inc(a, &PR_RAM->ReadyInt);
a->ReadyInt++;
}
}
return ReadyCount;
}
/*------------------------------------------------------------------*/
/* output function */
/*------------------------------------------------------------------*/
void DivasOut(ADAPTER * a)
{
byte e_no;
ENTITY * this = NULL;
BUFFERS *X;
word length;
word i;
word clength;
REQ * ReqOut;
byte more;
byte ReadyCount;
byte ReqCount;
byte Id;
/* while a request is pending ... */
e_no = look_req(a);
if(!e_no)
{
return;
}
ReadyCount = pr_ready(a);
if(!ReadyCount)
{
DPRINTF(("IDI: card not ready for next request"));
return;
}
ReqCount = 0;
while(e_no && ReadyCount) {
next_req(a);
this = entity_ptr(a, e_no);
#ifdef USE_EXTENDED_DEBUGS
if ( !this )
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DBG_FTL(("!A%d ==> NULL entity ptr - try to ignore", (int)io->ANum))
e_no = look_req(a) ;
ReadyCount-- ;
continue ;
}
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DPRINTF(("IDI: >A%d Id=0x%x Req=0x%x", io->ANum, this->Id, this->Req))
}
#else
DPRINTF(("IDI: >REQ=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
#endif
/* get address of next available request buffer */
ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
/* now copy the data from the current data buffer into the */
/* adapters request buffer */
length = 0;
i = this->XCurrent;
X = PTR_X(a,this);
while(i<this->XNum && length<270) {
clength = MIN((word)(270-length),X[i].PLength-this->XOffset);
a->ram_out_buffer(a,
&ReqOut->XBuffer.P[length],
PTR_P(a,this,&X[i].P[this->XOffset]),
clength);
length +=clength;
this->XOffset +=clength;
if(this->XOffset==X[i].PLength) {
this->XCurrent = (byte)++i;
this->XOffset = 0;
}
}
#if 0
{
byte prot_str[4];
DivasPrintf("IDI:ReqLength:%d",length);
a->ram_in_buffer(a, (char *) 0x80, prot_str, 3);
prot_str[3] = 0;
if (!strcmp(prot_str, "TE_"))
{
DivasPrintf("IDI: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
}
#endif
a->ram_outw(a, &ReqOut->XBuffer.length, length);
a->ram_out(a, &ReqOut->ReqId, this->Id);
a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
/* if its a specific request (no ASSIGN) ... */
if(this->Id &0x1f) {
/* if buffers are left in the list of data buffers do */
/* do chaining (LL_MDATA, N_MDATA) */
this->More++;
if(i<this->XNum && this->MInd) {
a->ram_out(a, &ReqOut->Req, this->MInd);
more = TRUE;
}
else {
this->More |=XMOREF;
a->ram_out(a, &ReqOut->Req, this->Req);
more = FALSE;
}
/* if we did chaining, this entity is put back into the */
/* request queue */
if(more) {
req_queue(a,this->No);
}
}
/* else it's a ASSIGN */
else {
/* save the request code used for buffer chaining */
this->MInd = 0;
if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
if (this->Id==NL_ID ||
this->Id==TASK_ID ||
this->Id==MAN_ID
) this->MInd = N_MDATA;
/* send the ASSIGN */
this->More |=XMOREF;
a->ram_out(a, &ReqOut->Req, this->Req);
/* save the reference of the ASSIGN */
assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
}
a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
ReadyCount--;
ReqCount++;
e_no = look_req(a);
}
/* send the filled request buffers to the ISDN adapter */
a->ram_out(a, &PR_RAM->ReqInput,
(byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
/* if it is a 'unreturncoded' UREMOVE request, remove the */
/* Id from our table after sending the request */
if(this->Req==UREMOVE && this->Id) {
Id = this->Id;
e_no = a->IdTable[Id];
free_entity(a, e_no);
a->IdTable[Id] = 0;
this->Id = 0;
}
}
/*------------------------------------------------------------------*/
/* isdn interrupt handler */
/*------------------------------------------------------------------*/
byte DivasDpc(ADAPTER * a)
{
byte Count;
RC * RcIn;
IND * IndIn;
byte c;
byte RNRId;
byte Rc;
byte Ind;
/* if return codes are available ... */
if((Count = a->ram_in(a, &PR_RAM->RcOutput))) {
DPRINTF(("IDI: #Rc=%x",Count));
/* get the buffer address of the first return code */
RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
/* for all return codes do ... */
while(Count--) {
if((Rc=a->ram_in(a, &RcIn->Rc))) {
/* call return code handler, if it is not our return code */
/* the handler returns 2 */
/* for all return codes we process, we clear the Rc field */
isdn_rc(a,
Rc,
a->ram_in(a, &RcIn->RcId),
a->ram_in(a, &RcIn->RcCh),
a->ram_inw(a, &RcIn->Reference));
a->ram_out(a, &RcIn->Rc, 0);
}
/* get buffer address of next return code */
RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
}
/* clear all return codes (no chaining!) */
a->ram_out(a, &PR_RAM->RcOutput ,0);
/* call output function */
DivasOut(a);
}
/* clear RNR flag */
RNRId = 0;
/* if indications are available ... */
if((Count = a->ram_in(a, &PR_RAM->IndOutput))) {
DPRINTF(("IDI: #Ind=%x",Count));
/* get the buffer address of the first indication */
IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
/* for all indications do ... */
while(Count--) {
/* if the application marks an indication as RNR, all */
/* indications from the same Id delivered in this interrupt */
/* are marked RNR */
if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
a->ram_out(a, &IndIn->Ind, 0);
a->ram_out(a, &IndIn->RNR, TRUE);
}
else {
Ind = a->ram_in(a, &IndIn->Ind);
if(Ind) {
RNRId = 0;
/* call indication handler, a return value of 2 means chain */
/* a return value of 1 means RNR */
/* for all indications we process, we clear the Ind field */
c = isdn_ind(a,
Ind,
a->ram_in(a, &IndIn->IndId),
a->ram_in(a, &IndIn->IndCh),
&IndIn->RBuffer,
a->ram_in(a, &IndIn->MInd),
a->ram_inw(a, &IndIn->MLength));
if(c==1) {
DPRINTF(("IDI: RNR"));
a->ram_out(a, &IndIn->Ind, 0);
RNRId = a->ram_in(a, &IndIn->IndId);
a->ram_out(a, &IndIn->RNR, TRUE);
}
}
}
/* get buffer address of next indication */
IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
}
a->ram_out(a, &PR_RAM->IndOutput, 0);
}
return FALSE;
}
byte DivasTestInt(ADAPTER * a)
{
return a->ram_in(a,(void *)0x3fe);
}
void DivasClearInt(ADAPTER * a)
{
a->ram_out(a,(void *)0x3fe,0);
}
/*------------------------------------------------------------------*/
/* return code handler */
/*------------------------------------------------------------------*/
static
byte isdn_rc(ADAPTER * a,
byte Rc,
byte Id,
byte Ch,
word Ref)
{
ENTITY * this;
byte e_no;
#ifdef USE_EXTENDED_DEBUGS
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DPRINTF(("IDI: <A%d Id=0x%x Rc=0x%x", io->ANum, Id, Rc))
}
#else
DPRINTF(("IDI: <RC(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch));
#endif
/* check for ready interrupt */
if(Rc==READY_INT) {
if(a->ReadyInt) {
a->ReadyInt--;
return 0;
}
return 2;
}
/* if we know this Id ... */
e_no = a->IdTable[Id];
if(e_no) {
this = entity_ptr(a,e_no);
this->RcCh = Ch;
/* if it is a return code to a REMOVE request, remove the */
/* Id from our table */
if(this->Req==REMOVE && Rc==OK) {
free_entity(a, e_no);
a->IdTable[Id] = 0;
this->Id = 0;
/**************************************************************/
if ((this->More & XMOREC) > 1) {
this->More &= ~XMOREC;
this->More |= 1;
DPRINTF(("isdn_rc, Id=%x, correct More on REMOVE", Id));
}
}
if (Rc==OK_FC) {
this->Rc = Rc;
this->More = (this->More & (~XBUSY | XMOREC)) | 1;
this->complete = 0xFF;
CALLBACK(a, this);
return 0;
}
if(this->More &XMOREC)
this->More--;
/* call the application callback function */
if(this->More &XMOREF && !(this->More &XMOREC)) {
this->Rc = Rc;
this->More &=~XBUSY;
this->complete=0xff;
CALLBACK(a, this);
}
return 0;
}
/* if it's an ASSIGN return code check if it's a return */
/* code to an ASSIGN request from us */
if((Rc &0xf0)==ASSIGN_RC) {
e_no = get_assign(a, Ref);
if(e_no) {
this = entity_ptr(a,e_no);
this->Id = Id;
/* call the application callback function */
this->Rc = Rc;
this->More &=~XBUSY;
this->complete=0xff;
CALLBACK(a, this);
if(Rc==ASSIGN_OK) {
a->IdTable[Id] = e_no;
}
else
{
free_entity(a, e_no);
a->IdTable[Id] = 0;
this->Id = 0;
}
return 1;
}
}
return 2;
}
/*------------------------------------------------------------------*/
/* indication handler */
/*------------------------------------------------------------------*/
static
byte isdn_ind(ADAPTER * a,
byte Ind,
byte Id,
byte Ch,
PBUFFER * RBuffer,
byte MInd,
word MLength)
{
ENTITY * this;
word clength;
word offset;
BUFFERS *R;
#ifdef USE_EXTENDED_DEBUGS
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DPRINTF(("IDI: <A%d Id=0x%x Ind=0x%x", io->ANum, Id, Ind))
}
#else
DPRINTF(("IDI: <IND(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch));
#endif
if(a->IdTable[Id]) {
this = entity_ptr(a,a->IdTable[Id]);
this->IndCh = Ch;
/* if the Receive More flag is not yet set, this is the */
/* first buffer of the packet */
if(this->RCurrent==0xff) {
/* check for receive buffer chaining */
if(Ind==this->MInd) {
this->complete = 0;
this->Ind = MInd;
}
else {
this->complete = 1;
this->Ind = Ind;
}
/* call the application callback function for the receive */
/* look ahead */
this->RLength = MLength;
a->ram_look_ahead(a, RBuffer, this);
this->RNum = 0;
CALLBACK(a, this);
/* map entity ptr, selector could be re-mapped by call to */
/* IDI from within callback */
this = entity_ptr(a,a->IdTable[Id]);
/* check for RNR */
if(this->RNR==1) {
this->RNR = 0;
return 1;
}
/* if no buffers are provided by the application, the */
/* application want to copy the data itself including */
/* N_MDATA/LL_MDATA chaining */
if(!this->RNR && !this->RNum) {
return 0;
}
/* if there is no RNR, set the More flag */
this->RCurrent = 0;
this->ROffset = 0;
}
if(this->RNR==2) {
if(Ind!=this->MInd) {
this->RCurrent = 0xff;
this->RNR = 0;
}
return 0;
}
/* if we have received buffers from the application, copy */
/* the data into these buffers */
offset = 0;
R = PTR_R(a,this);
do {
if(this->ROffset==R[this->RCurrent].PLength) {
this->ROffset = 0;
this->RCurrent++;
}
clength = MIN(a->ram_inw(a, &RBuffer->length)-offset,
R[this->RCurrent].PLength-this->ROffset);
if(R[this->RCurrent].P) {
a->ram_in_buffer(a,
&RBuffer->P[offset],
PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
clength);
}
offset +=clength;
this->ROffset +=clength;
} while(offset<(a->ram_inw(a, &RBuffer->length)));
/* if it's the last buffer of the packet, call the */
/* application callback function for the receive complete */
/* call */
if(Ind!=this->MInd) {
R[this->RCurrent].PLength = this->ROffset;
if(this->ROffset) this->RCurrent++;
this->RNum = this->RCurrent;
this->RCurrent = 0xff;
this->Ind = Ind;
this->complete = 2;
#if 0
DivasPrintf("IDI:IndLength:%d", a->ram_inw(a, &RBuffer->length));
#endif
CALLBACK(a, this);
}
return 0;
}
return 2;
}

145
drivers/isdn/eicon/idi.h Normal file
View File

@ -0,0 +1,145 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* External IDI interface */
#if !defined(IDI_H)
#define IDI_H
#include "sys.h"
/* typedefs for our data structures */
typedef struct get_name_s GET_NAME;
typedef struct entity_s ENTITY;
typedef struct buffers_s BUFFERS;
/* IDI request/callback function pointer */
typedef void (* IDI_CALL)(ENTITY *);
typedef struct {
word length; /* length of data/parameter field */
byte P[270]; /* data/parameter field */
} DBUFFER;
#define REQ_NAME 0x0100
#define BOARD_NAME_LENGTH 9
struct get_name_s {
word command; /* command = 0x0100 */
byte name[BOARD_NAME_LENGTH];
};
#define REQ_REMOVE 0x0000 /* pointer to word which is 0 */
#define REQ_SERIAL 0x0200
struct get_serial_s {
word command; /* command = 0x0200 */
dword serial; /* serial number */
};
#define REQ_POSTCALL 0x0300
struct postcall_s {
word command; /* command = 0x0300 */
word dummy; /* not used */
IDI_CALL callback; /* routine adress to call back */
ENTITY *contxt; /* ptr to entity to use */
};
#define REQ_XLOG 0x0400 /* structure is card dependent/defined locally */
struct buffers_s {
word PLength;
byte *P;
};
struct entity_s {
byte Req; /* pending request */
byte Rc; /* return code received */
byte Ind; /* indication received */
byte ReqCh; /* channel of current Req */
byte RcCh; /* channel of current Rc */
byte IndCh; /* channel of current Ind */
byte Id; /* ID used by this entity */
byte GlobalId; /* reserved field */
byte XNum; /* number of X-buffers */
byte RNum; /* number of R-buffers */
BUFFERS *X; /* pointer to X-buffer list */
BUFFERS *R; /* pointer to R-buffer list */
word RLength; /* length of current R-data */
DBUFFER *RBuffer; /* buffer of current R-data */
byte RNR; /* receive not ready flag */
byte complete; /* receive complete status */
IDI_CALL callback;
word user[2];
/* fields used by the driver internally */
byte No; /* entity number */
byte reserved2; /* reserved field */
byte More; /* R/X More flags */
byte MInd; /* MDATA coding for this ID */
byte XCurrent; /* current transmit buffer */
byte RCurrent; /* current receive buffer */
word XOffset; /* offset in x-buffer */
word ROffset; /* offset in r-buffer */
};
typedef struct {
byte type;
byte channels;
word features;
IDI_CALL request;
} DESCRIPTOR;
extern void EtdM_DIDD_Read(DESCRIPTOR *, int *);
/* descriptor type field coding */
#define IDI_ADAPTER_S 1
#define IDI_ADAPTER_PR 2
#define IDI_ADAPTER_DIVA 3
#define IDI_ADAPTER_MAESTRA 4
#define IDI_ADAPTER_MAESTRAQ 5
#define IDI_ADAPTER_MAESTRAP 6
#define IDI_VADAPTER 0x40
#define IDI_DRIVER 0x80
#define IDI_DIMAINT 0xff
/* feature bit mask values */
#define DI_VOICE 0x0 /* obsolete define */
#define DI_FAX3 0x1
#define DI_MODEM 0x2
#define DI_POST 0x4
#define DI_V110 0x8
#define DI_V120 0x10
#define DI_POTS 0x20
#define DI_CODEC 0x40
#define DI_MANAGE 0x80
#define DI_V_42 0x0100
#define DI_EXTD_FAX 0x0200 /* Extended FAX (ECM, 2D, T.6, Polling) */
#endif /* IDI_H */

View File

@ -0,0 +1,538 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Source file for kernel interface to kernel log facility
*/
#include "sys.h"
#include <stdarg.h>
#undef MAX
#undef MIN
#include <sys/types.h>
#include <sys/param.h>
#include "divas.h"
#include "divalog.h"
#include "uxio.h"
/*
* Implementation of printf and sprintf for kernel
*/
#define MAX_BUFF (80) /* limit size of temporary buffers */
#define WRITE_CHAR(BUFFER, SIZE, C) \
if (--(SIZE) < 0) { (BUFFER)--; *(BUFFER) = '\0'; return; } *(BUFFER)++ = (C)
/*
* convert a number to decimal ASCII
*/
static
void do_decimal( char *temp,
int temp_len,
unsigned int value,
char *s)
{
int i;
temp[0] = '\0';
for (i = 1; i < temp_len; i++)
{
temp[i] = (char) ((value % 10) + (int) '0');
value /= 10;
}
for (i = (temp_len - 1); temp[i] == '0'; i--)
{
;
}
if (i == 0)
{
i++;
}
while (i >= 0)
{
*s++ = temp[i--];
}
return;
}
/*
* convert a number to octal ASCII
*/
static
void do_octal( char *temp,
unsigned int value,
char *s)
{
int i;
temp[0] = '\0';
for (i = 1; i <= 11; i++)
{
temp[i] = (char) ((value & 07) + (int) '0');
value >>= 3;
}
temp[11] &= '3';
for (i = 11; temp[i] == '0'; i--)
{
;
}
if (i == 0)
{
i++;
}
while (i >= 0)
{
*s++ = temp[i--];
}
return;
}
/*
* convert a number to hex ASCII
*/
static
void do_hex( char *temp,
unsigned int value,
char *s)
{
int i;
static
char *dec_to_hex = "0123456789abcdef";
temp[0] = '\0';
for (i = 1; i <= 8; i++)
{
temp[i] = dec_to_hex[value & 0x0f];
value >>= 4;
}
for (i = 8; temp[i] == '0'; i--)
{
;
}
if (i == 0)
{
i++;
}
while (i >= 0)
{
*s++ = temp[i--];
}
return;
}
/*
* convert a buffer to ASCII HEX
*/
static
void do_buffer( char *buffer,
int length,
char *s)
{
static
char hex_char [] = "0123456789abcdef";
char *b = buffer;
int hex_byte;
int nybble;
length = (length >= ((MAX_BUFF / 3) + 1)) ? (MAX_BUFF / 3) : length;
while (length)
{
hex_byte = (int) *b++;
nybble = (hex_byte >> 4) & 0xf;
*s++ = hex_char[nybble];
nybble = hex_byte & 0xf;
*s++ = hex_char[nybble];
*s++ = ' ';
length--;
}
*s = '\0';
return;
}
/*
* Body of sprintf function: behaves just like standard sprintf, except we
* have an extra argument (buffer size) which we use to ensure we don't
* overflow
*/
void Divas_vsprintf( char *buffer,
int size,
char *fmt,
va_list argptr)
{
char c; /* single character buffer */
int i; /* handy scratch counter */
int f; /* format character (after %) */
char *str; /* pointer into string */
char temp[20]; /* temp buffer used in printing numbers */
char string[MAX_BUFF]; /* output from number conversion */
int length; /* length of string "str" */
char fill; /* fill character ' ' or '0' */
boolean_t leftjust; /* TRUE if left justified, else right justified */
int fmax, fmin; /* field specifiers % MIN . MAX s */
int leading; /* number of leading/trailing fill characters */
char sign; /* set to '-' for negative decimals */
int number; /* numeric argument */
char *buff_ptr; /* pointer to user's buffer of hex data */
int buff_len; /* length of hex data */
/* make sure we have somthing to write into */
if ((!buffer) || (size <= 0))
{
return;
}
while (TRUE)
{
/* echo characters until end or '%' encountered */
while ((c = *fmt++) != '%')
{
if (!c)
{
*buffer = '\0';
return;
}
WRITE_CHAR(buffer, size, c);
}
/* echo %% as % */
if (*fmt == '%')
{
WRITE_CHAR(buffer, size, *fmt);
continue;
}
/* %- turns on left-justify */
if ((leftjust = (boolean_t) ((*fmt == '-') ? TRUE : FALSE)))
{
fmt++;
}
/* %0 turns on zero filling */
if (*fmt == '0')
{
fill = '0';
}
else
{
fill = ' ';
}
/* minium field width specifier for %d, u, x, c, s */
fmin = 0;
if (*fmt == '*')
{
fmin = va_arg(argptr, int);
fmt++;
}
else
{
while ('0' <= *fmt && *fmt <= '9')
{
fmin = (fmin * 10) + (*fmt++ - '0');
}
}
/* maximum string width specifier for %s */
fmax = 0;
if (*fmt == '.')
{
if (*(++fmt) == '*')
{
fmax = va_arg(argptr, int);
fmt++;
}
else
{
while ('0' <= *fmt && *fmt <= '9')
{
fmax = (fmax * 10) + (*fmt++ - '0');
}
}
}
/* skip over 'l' option (ints are assumed same size as longs) */
if (*fmt == 'l')
{
fmt++;
}
/* get the format chacater */
if (!(f = *fmt++))
{
WRITE_CHAR(buffer, size, '%');
*buffer = '\0';
return;
}
sign = '\0'; /* sign == '-' for negative decimal */
str = string;
switch (f)
{
case 'c' :
string[0] = va_arg(argptr, char);
string[1] = '\0';
fmax = 0;
fill = ' ';
break;
case 's' :
str = va_arg(argptr, char *);
fill = ' ';
break;
case 'D' :
case 'd' :
number = va_arg(argptr, int);
if (number < 0)
{
sign = '-';
number = -number;
}
do_decimal(temp, DIM(temp), (unsigned int) number, str);
fmax = 0;
break;
case 'U' :
case 'u' :
number = va_arg(argptr, int);
do_decimal(temp, DIM(temp), (unsigned int) number, str);
fmax = 0;
break;
case 'O' :
case 'o' :
number = va_arg(argptr, int);
do_octal(temp, (unsigned int) number, str);
fmax = 0;
break;
case 'X' :
case 'x' :
number = va_arg(argptr, int);
do_hex(temp, (unsigned int) number, str);
fmax = 0;
break;
case 'H' :
case 'h' :
buff_ptr = va_arg(argptr, char *);
buff_len = va_arg(argptr, int);
do_buffer(buff_ptr, buff_len, str);
fmax = 0;
break;
default :
WRITE_CHAR(buffer, size, ((char) f));
break;
}
/* get the length of the string */
length = 0;
while (str[length])
{
length++;
}
/* make sure we have fmax and fmin values that are O.K. */
if (fmin > DIM(string) || fmin < 0)
{
fmin = 0;
}
if (fmax > DIM(string) || fmax < 0)
{
fmax = 0;
}
/* figure out how many leading characters thare are */
leading = 0;
if (fmax || fmin)
{
if (fmax)
{
if (length > fmax)
{
length = fmax;
}
}
if (fmin)
{
leading = fmin - length;
}
if (sign == '-')
{
leading--;
}
}
/* output sign now, if fill is numeric */
if (sign == '-' && fill == '0')
{
WRITE_CHAR(buffer, size, '-');
}
/* if right justified, output fill characters */
if (!leftjust)
{
for (i = 0; i < leading; i++)
{
WRITE_CHAR(buffer, size, fill);
}
}
/* output sign now, if fill is spaces */
if (sign == '-' && fill == ' ')
{
WRITE_CHAR(buffer, size, '-');
}
/* now the actual value */
for (i = 0; i < length; i++)
{
WRITE_CHAR(buffer, size, str[i]);
}
/* if left justified, fill out with the fill character */
if (leftjust)
{
for (i = 0; i < leading; i++)
{
WRITE_CHAR(buffer, size, fill);
}
}
}
}
/*
* sprintf for kernel
*
* call our vsprintf assuming user has a big buffer....
*/
void DivasSprintf(char *buffer, char *fmt, ...)
{
va_list argptr; /* pointer to additional args */
va_start(argptr, fmt);
Divas_vsprintf(buffer, 1024, fmt, argptr);
va_end(argptr);
return;
}
void DivasPrintf(char *fmt, ...)
{
klog_t log; /* log entry buffer */
va_list argptr; /* pointer to additional args */
va_start(argptr, fmt);
/* clear log entry */
bzero((caddr_t) &log, sizeof(klog_t));
log.card = -1;
log.type = KLOG_TEXT_MSG;
/* time stamp the entry */
log.time_stamp = UxTimeGet();
/* call vsprintf to format the user's information */
Divas_vsprintf(log.buffer, DIM(log.buffer), fmt, argptr);
va_end(argptr);
/* send to the log streams driver and return */
DivasLogAdd(&log, sizeof(klog_t));
return;
}

410
drivers/isdn/eicon/lincfg.c Normal file
View File

@ -0,0 +1,410 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.9
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/fs.h>
#undef N_DATA /* Because we have our own definition */
#include <asm/segment.h>
#include <asm/io.h>
#include "sys.h"
#include "idi.h"
#include "constant.h"
#include "divas.h"
#undef ID_MASK
#include "pc.h"
#include "pr_pc.h"
#include "adapter.h"
#include "uxio.h"
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#define HW_ID_EICON_PCI 0x1133
#define HW_ID_DIVA_SERVER_P 0xE014
#define HW_ID_DIVA_SERVER_B_ST 0xE010
#define HW_ID_DIVA_SERVER_B_U 0xE013
#define HW_ID_DIVA_SERVER_Q 0xE012
struct file_operations Divas_fops;
int Divas_major;
extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
unsigned int command, unsigned long arg);
extern unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable);
extern ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset);
extern int do_open(struct inode *, struct file *);
extern int do_release(struct inode *, struct file *);
int FPGA_Done=0;
int DivasCardsDiscover(void)
{
word wNumCards = 0, wDeviceIndex = 0;
byte byBus, byFunc;
word wPCIConsultation, PCItmp;
dword j, i;
unsigned int PCIserial;
dia_card_t Card;
byte *b;
while (wDeviceIndex < 10)
{
wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
HW_ID_DIVA_SERVER_B_ST,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwPLXIOBase, dwDivasIOBase;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
dwPLXIOBase &= 0xFFFFFF80;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFFFC;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
Card.card_id = wNumCards;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
Card.bus_type = DIA_BUS_TYPE_PCI;
Card.irq = byIRQ;
Card.reset_base = dwPLXIOBase;
Card.io_base = dwDivasIOBase;
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'B';
Card.name[6] = '\0';
if (check_region(Card.io_base, 0x20))
{
printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
wDeviceIndex++;
continue;
}
if (check_region(Card.reset_base, 0x80))
{
printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0xFF);
wDeviceIndex++;
continue;
}
if (DivasCardNew(&Card) != 0)
{
wDeviceIndex++;
continue;
}
wNumCards++;
}
wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
HW_ID_DIVA_SERVER_B_U,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwPLXIOBase, dwDivasIOBase;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
dwPLXIOBase &= 0xFFFFFF80;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFFFC;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
Card.card_id = wNumCards;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
Card.bus_type = DIA_BUS_TYPE_PCI;
Card.irq = byIRQ;
Card.reset_base = dwPLXIOBase;
Card.io_base = dwDivasIOBase;
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'B';
Card.name[6] = '\0';
if (check_region(Card.io_base, 0x20))
{
printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
wDeviceIndex++;
continue;
}
if (check_region(Card.reset_base, 0x80))
{
printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0xFF);
wDeviceIndex++;
continue;
}
if (DivasCardNew(&Card) != 0)
{
wDeviceIndex++;
continue;
}
wNumCards++;
}
wDeviceIndex++;
}
wDeviceIndex = 0;
while (wDeviceIndex < 10)
{
wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
HW_ID_DIVA_SERVER_P,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwRAM, dwREG, dwCFG;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM);
dwRAM &= 0xFFFFF000;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG);
dwREG &= 0xFFFFF000;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG);
dwCFG &= 0xFFFFF000;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
/* pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
dwPLXIOBase &= 0xFFFFFFFc;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFF80;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
*/
Card.card_id = wNumCards;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
Card.bus_type = DIA_BUS_TYPE_PCI;
Card.irq = byIRQ;
/* Card.reset_base = dwPLXIOBase;
Card.io_base = dwDivasIOBase;*/
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'P';
Card.name[6] = '\0';
if (DivasCardNew(&Card) != 0)
{
wDeviceIndex++;
continue;
}
wNumCards++;
}
wDeviceIndex++;
}
wDeviceIndex = 0;
while (wDeviceIndex < 10)
{
wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI,
HW_ID_DIVA_SERVER_Q,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwRAM, dwDivasIOBase, dwCFG, dwCTL;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM);
dwRAM &= 0xFFC00000;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFF00;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG);
dwCFG &= 0xFFFFFF00;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL);
dwCTL &= 0xFFFFE000;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
/* Retrieve the serial number */
pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC);
for (j=0, PCItmp=0; j<10000 && !PCItmp; j++)
{
pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp);
PCItmp &= 0x8000; // extract done flag
}
pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial);
Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
Card.io_base=dwDivasIOBase;
Card.irq = byIRQ;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
Card.bus_type = DIA_BUS_TYPE_PCI;
FPGA_Done = 0;
/* Create four virtual card structures as we want to treat
the 4Bri card as 4 Bri cards*/
for(i=0;i<4;i++)
{
b=Card.memory[DIVAS_RAM_MEMORY];
b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1);
DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
Card.memory[DIVAS_RAM_MEMORY]=b;
b = Card.memory[DIVAS_RAM_MEMORY];
b += MQ_SM_OFFSET;
Card.memory[DIVAS_SHARED_MEMORY] = b;
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
/* Fill in Name */
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'Q';
Card.name[6] = '0' + i;
Card.name[7] = '\0';
Card.serial = PCIserial;
Card.card_id = wNumCards;
if (DivasCardNew(&Card) != 0)
{
// Force for loop to terminate
i = 4;
continue;
}
wNumCards++;
}//for
}
wDeviceIndex++;
}
printk(KERN_INFO "Divas: %d cards detected\n", wNumCards);
if(wNumCards == 0)
{
return -1;
}
Divas_fops.ioctl = do_ioctl;
Divas_fops.poll = do_poll;
Divas_fops.read = do_read;
Divas_fops.open = do_open;
Divas_fops.release = do_release;
Divas_major = register_chrdev(0, "Divas", &Divas_fops);
if (Divas_major < 0)
{
printk(KERN_WARNING "Divas: Unable to register character driver\n");
return -1;
}
return 0;
}
/* Error return -1 */
int DivasConfigGet(dia_card_t *card)
{
/* Retrieve Config from O/S? Not in Linux */
return 0;
}
dia_config_t *DivasConfig(card_t *card, dia_config_t *config)
{
/* If config retrieved from OS then copy the data into a dia_config_t structure here
and return the pointer here. If the config 'came from above' then just
return config;
*/
return config;
}

274
drivers/isdn/eicon/linchr.c Normal file
View File

@ -0,0 +1,274 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.12
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/malloc.h>
#undef N_DATA
#include "adapter.h"
#include "divas.h"
#include "divalog.h"
extern int DivasCardNext;
void UxPause(long ms);
void bcopy(void *pSource, void *pDest, dword dwLength);
int DivasGetMem(mem_block_t *);
#define DIA_IOCTL_UNLOCK 12
void UnlockDivas(void);
int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
unsigned int command, unsigned long arg)
{
dia_load_t *pDivaLoad;
dia_start_t *pDivaStart;
dia_config_t *pDivaConfig;
dia_log_t *pDivaLog;
byte *pUserCards, card_i;
word wCardNum;
mem_block_t *mem_block;
switch (command)
{
case DIA_IOCTL_CONFIG:
pDivaConfig = (dia_config_t *) arg;
if (!verify_area(VERIFY_READ, pDivaConfig, sizeof(dia_config_t)))
{
DivasCardConfig(pDivaConfig);
}
else
{
printk(KERN_WARNING "Divas: Unable to complete CONFIG ioctl (verify area failed)\n");
return -1;
}
return 0;
case DIA_IOCTL_DETECT:
pUserCards = (byte *) arg;
if (!verify_area(VERIFY_WRITE, pUserCards, 20))
{
put_user(DivasCardNext, pUserCards++);
for (card_i=1; card_i < 20; card_i++)
{
put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++);
}
}
else
{
printk(KERN_WARNING "Divas: Unable to complete DETECT ioctl (verify area failed)\n");
return -1;
}
return 0;
case DIA_IOCTL_START:
pDivaStart = (dia_start_t *) arg;
if (!verify_area(VERIFY_READ, pDivaStart, sizeof(dia_start_t)))
{
return DivasCardStart(pDivaStart->card_id);
}
else
{
printk(KERN_WARNING "Divas: Unable to complete START ioctl (verify area failed)\n");
return -1;
}
case DIA_IOCTL_FLAVOUR:
return 0;
case DIA_IOCTL_LOAD:
pDivaLoad = (dia_load_t *) arg;
if (!verify_area(VERIFY_READ, pDivaLoad->code,pDivaLoad->length))
{
if (DivasCardLoad(pDivaLoad))
{
printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n");
return -EINVAL;
}
}
else
{
printk(KERN_WARNING "Divas: Error in LOAD parameters (verify failed)\n");
return -EINVAL;
}
return 0;
case DIA_IOCTL_LOG:
pDivaLog = (dia_log_t *) arg;
if (!verify_area(VERIFY_READ, pDivaLog, sizeof(dia_log_t)))
{
DivasLog(pDivaLog);
}
else
{
printk(KERN_WARNING "Divas: Unable to complete LOG ioctl (verify area failed)\n");
return -1;
}
return 0;
case DIA_IOCTL_XLOG_REQ:
if (!verify_area(VERIFY_READ, (void *)arg, sizeof(word)))
{
wCardNum = * (word *) arg;
DivasXlogReq(wCardNum);
}
else
{
printk(KERN_WARNING "Divas: Unable to complete XLOG_REQ ioctl (verify area failed)\n");
return -1;
}
return 0;
case DIA_IOCTL_GET_NUM:
if (!verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)))
{
* (int *) arg = DivasCardNext;
}
else
{
printk(KERN_WARNING "Divas: Unable to complete GET_NUM ioctl (verify area failed)\n");
return -1;
}
return 0;
case DIA_IOCTL_GET_LIST:
DPRINTF(("divas: DIA_IOCTL_GET_LIST"));
if (!verify_area(VERIFY_WRITE, (void *)arg, sizeof(dia_card_list_t)))
{
DivasGetList((dia_card_list_t *)arg);
}
else
{
printk(KERN_WARNING "Divas: Unable to complete GET_LIST ioctl (verify area failed)\n");
return -1;
}
return 0;
case DIA_IOCTL_GET_MEM:
mem_block = (mem_block_t *) arg;
if (!verify_area(VERIFY_WRITE, mem_block, sizeof(mem_block_t)))
{
DivasGetMem(mem_block);
}
else
{
printk(KERN_WARNING "Divas: Unable to complete GET_MEM ioctl (verify area failed)\n");
return -1;
}
return 0;
case DIA_IOCTL_UNLOCK:
UnlockDivas();
return 0;
default:
printk(KERN_WARNING "Divas: Unknown IOCTL Received by DIVA Server Driver(%d)\n", command);
return -EINVAL;
}
return -EINVAL;
}
unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable)
{
word wMask = 0;
if (!DivasLogFifoEmpty())
{
wMask |= POLLIN | POLLRDNORM;
}
return wMask;
}
ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset)
{
klog_t *pClientLogBuffer = (klog_t *) pUserBuffer;
klog_t *pHeadItem;
if (BufferSize < sizeof(klog_t))
{
printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
BufferSize, sizeof(klog_t));
return 0;
}
pHeadItem = (klog_t *) DivasLogFifoRead();
if (pHeadItem)
{
bcopy(pHeadItem, pClientLogBuffer, sizeof(klog_t));
kfree(pHeadItem);
return sizeof(klog_t);
}
return 0;
}
int private_usage_count;
extern void mod_inc_use_count(void);
extern void mod_dec_use_count(void);
int do_open(struct inode *pInode, struct file *pFile)
{
#if defined(MODULE)
mod_inc_use_count();
private_usage_count++;
#endif
return 0;
}
int do_release(struct inode *pInode, struct file *pFile)
{
#if defined(MODULE)
mod_dec_use_count();
private_usage_count--;
#endif
return 0;
}
void UnlockDivas(void)
{
while (private_usage_count > 0)
{
private_usage_count--;
#if defined(MODULE)
mod_dec_use_count();
#endif
}
}

705
drivers/isdn/eicon/linio.c Normal file
View File

@ -0,0 +1,705 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.11
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#define N_DATA
#include <asm/io.h>
#include <asm/system.h>
#include <linux/malloc.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/isdn_compat.h>
#undef N_DATA
#include "uxio.h"
static
int log_on;
int Divasdevflag = 0;
static
ux_diva_card_t card_pool[MAX_CARDS];
void UxPause(long int ms)
{
int timeout = (ms * HZ) / 1000;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(timeout);
}
int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
{
int i;
ux_diva_card_t *c;
if (cfg->bus_type != DIA_BUS_TYPE_PCI)
{
DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
return -1;
}
for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
{
;
}
if (i == DIM(card_pool))
{
DPRINTF(("divas hw: card_pool exhausted"));
return -1;
}
c = *card = &card_pool[i];
switch (cfg->bus_type)
{
case DIA_BUS_TYPE_PCI:
c->bus_num = cfg->bus_num;
c->func_num = cfg->func_num;
c->io_base = cfg->io_base;
c->reset_base = cfg->reset_base;
c->card_type = cfg->card_type;
c->mapped = NULL;
c->slot = cfg->slot;
c->irq = (int) cfg->irq;
c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
c->pCONTROL = cfg->memory[DIVAS_CTL_MEMORY];
/* c->bus_type = DIA_BUS_TYPE_PCI;
c->bus_num = cfg->bus_num & 0x3f;
c->slot = cfg->slot;
c->irq = (int) cfg->irq;
c->int_priority = (int) cfg->int_priority;
c->card_type = cfg->card_type;
c->io_base = cfg->io_base;
c->reset_base = cfg->reset_base;
c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/
break;
default:
break;
}
c->in_use = TRUE;
return 0;
}
void UxCardHandleFree(ux_diva_card_t *card)
{
card->in_use = FALSE;
}
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
void *UxCardMemAttach(ux_diva_card_t *card, int id)
{
if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
{
switch (id)
{
case DIVAS_SHARED_MEMORY:
card->mapped = card->pSHARED;
return card->pSHARED;
break;
case DIVAS_RAM_MEMORY:
card->mapped = card->pDRAM;
return card->pDRAM;
break;
case DIVAS_REG_MEMORY:
card->mapped = card->pDEVICES;
return card->pDEVICES;
break;
case DIVAS_CFG_MEMORY:
card->mapped = card->pCONFIG;
return card->pCONFIG;
break;
default:
ASSERT(FALSE);
card->mapped = NULL;
return (void *) 0;
}
}
else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
{
switch (id)
{
case PLX_IOBASE:
return (void *) card->reset_base;
break;
case DIVAS_IOBASE:
return (void *) card->io_base;
break;
default:
ASSERT(FALSE);
return 0;
}
}
else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
{
switch (id)
{
case DIVAS_SHARED_MEMORY:
card->mapped = card->pSHARED;
return card->pSHARED;
break;
case DIVAS_RAM_MEMORY:
card->mapped = card->pDRAM;
return card->pDRAM;
break;
case DIVAS_REG_MEMORY:
card->mapped = (void *) card->io_base;
return (void *) card->io_base;
break;
case DIVAS_CTL_MEMORY:
card->mapped = card->pCONTROL;
return card->pCONTROL;
break;
default:
// ASSERT(FALSE);
DPRINTF(("divas: Trying to attach to mem %d", id));
card->mapped = NULL;
return (void *) 0;
}
} else
DPRINTF(("divas: Tried to attach to unknown card"));
/* Unknown card type */
return NULL;
}
void UxCardMemDetach(ux_diva_card_t *card, void *address)
{
return; // Just a place holder. No un-mapping done.
}
void UxCardLog(int turn_on)
{
log_on = turn_on;
}
/*
* Control Register I/O Routines to be performed on Attached I/O ports
*/
void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
{
word base = (word) (dword) AttachedBase;
base += offset;
outb(the_byte, base);
}
void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
{
word base = (word) (dword) AttachedBase;
base += offset;
outw(the_word, base);
}
void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
{
word base = (word) (dword) AttachedBase;
base += offset;
outl(the_dword, base);
}
byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
{
word base = (word) (dword) AttachedBase;
base += offset;
return inb(base);
}
word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
{
word base = (word) (dword) AttachedBase;
base += offset;
return inw(base);
}
/*
* Memory mapped card I/O functions
*/
byte UxCardMemIn(ux_diva_card_t *card, void *address)
{
byte b;
b = (byte) * ((byte *) address);
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
}
return (byte) * ((byte *) address);
}
word UxCardMemInW(ux_diva_card_t *card, void *address)
{
word w;
w = (word) * ((word *) address);
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
}
return w;
}
dword UxCardMemInD(ux_diva_card_t *card, void *address)
{
dword dw;
dw = (dword) * ((dword *) address);
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
}
return dw;
}
void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
{
byte *pSource = address;
byte *pDest = buffer;
while (length--)
{
*pDest++ = *pSource++;
}
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
pDest = buffer;
DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
a));
}
return;
}
void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
{
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
}
* ((byte *) address) = data & 0xFF;
return;
}
void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
{
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
}
*((word *)address) = data & 0xFFFF;
return;
}
void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
{
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
}
*((dword *)address) = data & 0xFFFFFFFF;
return;
}
void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
{
byte *pSource = buffer;
byte *pDest = address;
while (length--)
{
*pDest++ = *pSource++;
}
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
pDest = buffer;
DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
a));
}
return;
}
/*
* Memory mapped card I/O functions
*/
byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{
byte the_byte;
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
the_byte = inb(card->io_base);
if (log_on)
{
DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)",
the_byte & 0xff, address));
}
return the_byte;
}
word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{
word the_word;
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
the_word = inw(card->io_base);
if (log_on)
{
DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)",
the_word & 0xffff, address));
}
return the_word;
}
dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{
dword the_dword;
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
the_dword = inl(card->io_base);
if (log_on)
{
DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)",
the_dword, address));
}
return the_dword;
}
void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
{
byte *pSource = address;
byte *pDest = buffer;
if ((word) (dword) address & 0x1)
{
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pSource, card->io_base + 4);
*pDest = (byte) inb(card->io_base);
pDest++;
pSource++;
length--;
if (!length)
{
return;
}
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pSource, card->io_base + 4);
insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
if (log_on)
{
pDest = buffer;
DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
address));
}
return;
}
/* Output */
void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
{
if (log_on)
{
DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)",
data & 0xff, address));
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
outb((byte) data & 0xFF, card->io_base);
return;
}
void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
{
if (log_on)
{
DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)",
data & 0xffff, address));
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
outw((word) data & 0xFFFF, card->io_base);
return;
}
void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
{
if (log_on)
{
DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
outl((dword) data & 0xFFFFFFFF, card->io_base);
return;
}
void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
{
byte *pSource = buffer;
byte *pDest = address;
if ((word) (dword) address & 1)
{
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pDest, card->io_base + 4);
outb(*pSource, card->io_base);
pSource++;
pDest++;
length--;
if (!length)
{
return;
}
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pDest, card->io_base + 4);
outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
if (log_on)
{
pDest = buffer;
DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
address));
}
return;
}
void Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
{
int i;
card_t *card = NULL;
ux_diva_card_t *ux_ref = NULL;
DPRINTF(("divas: interrupt received"));
for (i = 0; i < DivasCardNext; i++)
{
if (arg == DivasCards[i].cfg.irq)
{
card = &DivasCards[i];
ux_ref = card->hw;
if (ux_ref)
{
(*ux_ref->user_isr)(ux_ref->user_isr_arg);
}
else DPRINTF(("divas: ISR couldn't locate card"));
}
}
return;
}
int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
{
int result;
card->user_isr = isr_fn;
card->user_isr_arg = isr_arg;
result = request_irq(card->irq, Divasintr, SA_INTERRUPT, "Divas", (void *) NULL);
return result;
}
void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
{
free_irq(card->irq, NULL);
}
void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
{
switch (size)
{
case sizeof(byte):
pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
break;
case sizeof(word):
pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
break;
case sizeof(dword):
pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
break;
default:
printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
}
}
void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
{
switch (size)
{
case sizeof(byte):
pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
break;
case sizeof(word):
pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
break;
case sizeof(dword):
pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
break;
default:
printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
}
}
void *UxAlloc(unsigned int size)
{
void *m;
m = kmalloc(size, GFP_ATOMIC);
return m;
}
void UxFree(void *ptr)
{
kfree(ptr);
}
int UxCardLock(ux_diva_card_t *card)
{
unsigned long flags;
save_flags(flags);
cli();
return flags;
}
void UxCardUnlock(ux_diva_card_t *card, int ipl)
{
restore_flags(ipl);
}
dword UxTimeGet(void)
{
return jiffies;
}

154
drivers/isdn/eicon/linsys.c Normal file
View File

@ -0,0 +1,154 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.8
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/sched.h>
#undef N_DATA
#include <linux/tqueue.h>
#include <linux/smp.h>
struct pt_regs;
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include "sys.h"
#include "divas.h"
#include "adapter.h"
#include "divalog.h"
#include "uxio.h"
void bcopy(void *pSource, void *pDest, dword dwLength)
{
memcpy(pDest, pSource, dwLength);
}
void bzero(void *pDataArea, dword dwLength)
{
memset(pDataArea, 0, dwLength);
}
int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg)
{
/* Use UxPciConfigWrite routines to initialise PCI config space */
/* wPCIcommand = 0x03;
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
wPCIcommand = 0x280;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
bPCIcommand = 0x30;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
*/
return 0;
}
int DivasPRIInitPCI(card_t *card, dia_card_t *cfg)
{
/* Use UxPciConfigWrite routines to initialise PCI config space */
/* wPCIcommand = 0x03;
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
wPCIcommand = 0x280;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
bPCIcommand = 0x30;
cm_write_devconfig8(CMKey, PCI_LATENCY, &bPCIcommand);*/
return 0;
}
int DivasBRIInitPCI(card_t *card, dia_card_t *cfg)
{
/* Need to set these platform dependent values after patching */
card->hw->reset_base = card->cfg.reset_base;
card->hw->io_base = card->cfg.io_base;
request_region(card->hw->reset_base,0x80,"Divas");
request_region(card->hw->io_base,0x20,"Divas");
/* Same as for PRI */
return DivasPRIInitPCI(card, cfg);
}
/* ######################### Stubs of routines that are not done yet ################## */
/*void DivasLogIdi(card_t *card, ENTITY *e, int request)
{
}
*/
struct tq_struct DivasTask;
int DivasDpcSchedule(void)
{
DivasTask.routine = DivasDoDpc;
DivasTask.data = (void *) 0;
queue_task(&DivasTask, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return 0;
}
void DivasLogAdd(void *buffer, int length)
{
static
boolean_t overflow = FALSE;
static
boolean_t busy = FALSE;
/* make sure we're not interrupting ourselves */
if (busy)
{
printk(KERN_DEBUG "Divas: Logging interrupting self !\n");
return;
}
busy = TRUE;
/* ignore call if daemon isn't running and we've reached limit */
if (DivasLogFifoFull())
{
if (!overflow)
{
printk(KERN_DEBUG "Divas: Trace buffer full\n");
overflow = TRUE;
}
busy = FALSE;
return;
}
DivasLogFifoWrite(buffer, length);
busy = FALSE;
return;
}
/* #################################################################################### */

179
drivers/isdn/eicon/log.c Normal file
View File

@ -0,0 +1,179 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.5
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Source file for diva log facility
*/
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "adapter.h"
#include "divalog.h"
#include "uxio.h"
/*Counter to monitor number of messages */
static int m_count;
#define MAX_BUFFERED_MSGS (1000)
/* Our Linked List Structure to hold message */
typedef struct klog_link{
klog_t klog;
struct klog_link *next;
}KNODE;
/* First & Last structures in list*/
KNODE *head;
KNODE *tail;
/*
* retrieve message from FIFO buffer
* returns NULL if buffer empty
* otherwise returns pointer to entry
*/
char *DivasLogFifoRead(void)
{
KNODE *old_head;
if(head==NULL)
{
/* Buffer Empty - No Messages */
return NULL;
}
m_count--;
/* Keep track of message to be read & increment to next message*/
old_head = head;
head = head->next;
/*Return ptr to Msg */
return((char *)old_head);
}
/*
* write message into FIFO buffer
*/
void DivasLogFifoWrite(char *entry, int length)
{
KNODE *new_klog;
if(head == NULL)
{
/* No Entries in Log */
tail=NULL;
m_count=0;
new_klog=UxAlloc(sizeof(KNODE));
if(new_klog==NULL)
{
return;
}
m_count++;
bzero(new_klog,sizeof(KNODE));
/* Set head & tail to point to the new Msg Struct */
head=tail=new_klog;
tail->next=NULL;
}
else
{
new_klog=UxAlloc(sizeof(KNODE));
if(new_klog==NULL)
{
return;
}
m_count++;
bzero(new_klog,sizeof(KNODE));
/* Let last Msg Struct point to new Msg Struct & inc tail */
tail->next=new_klog;
tail=new_klog;
tail->next=NULL;
}
if (length > sizeof(klog_t))
{
length = sizeof(klog_t);
}
bcopy(entry,&tail->klog,length);
return;
}
/*
* DivaslogFifoEmpty:return TRUE if FIFO buffer is empty,otherwise FALSE
*/
int DivasLogFifoEmpty(void)
{
return (m_count == 0);
}
/*
*DivasLogFifoFull:return TRUE if FIFO buffer is full,otherwise FALSE
*/
int DivasLogFifoFull(void)
{
return (m_count == MAX_BUFFERED_MSGS);
}
/*
* generate an IDI log entry
*/
void DivasLogIdi(card_t *card, ENTITY *e, int request)
{
klog_t klog;
bzero(&klog, sizeof(klog));
klog.time_stamp = UxTimeGet();
klog.length = sizeof(ENTITY) > sizeof(klog.buffer) ?
sizeof(klog.buffer) : sizeof(ENTITY);
klog.card = (int) (card - DivasCards);
klog.type = request ? KLOG_IDI_REQ : KLOG_IDI_CALLBACK;
klog.code = 0;
bcopy(e, klog.buffer, klog.length);
/* send to the log driver and return */
DivasLogAdd(&klog, sizeof(klog));
return;
}

320
drivers/isdn/eicon/pc.h Normal file
View File

@ -0,0 +1,320 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PC_H_INCLUDED
#define PC_H_INCLUDED
#define byte unsigned char
#define word unsigned short
#define dword unsigned long
#if !defined(MIN)
#define MIN(a,b) ((a)>(b) ? (b) : (a))
#endif
#if !defined(MAX)
#define MAX(a,b) ((a)>(b) ? (a) : (b))
#endif
/*------------------------------------------------------------------*/
/* buffer definition */
/*------------------------------------------------------------------*/
typedef struct {
word length; /* length of data/parameter field */
byte P[270]; /* data/parameter field */
} PBUFFER;
/*------------------------------------------------------------------*/
/* dual port ram structure */
/*------------------------------------------------------------------*/
struct dual
{
byte Req; /* request register */
byte ReqId; /* request task/entity identification */
byte Rc; /* return code register */
byte RcId; /* return code task/entity identification */
byte Ind; /* Indication register */
byte IndId; /* Indication task/entity identification */
byte IMask; /* Interrupt Mask Flag */
byte RNR; /* Receiver Not Ready (set by PC) */
byte XLock; /* XBuffer locked Flag */
byte Int; /* ISDN-S interrupt */
byte ReqCh; /* Channel field for layer-3 Requests */
byte RcCh; /* Channel field for layer-3 Returncodes */
byte IndCh; /* Channel field for layer-3 Indications */
byte MInd; /* more data indication field */
word MLength; /* more data total packet length */
byte ReadyInt; /* request field for ready interrupt */
byte SWReg; /* Software register for special purposes */
byte Reserved[11]; /* reserved space */
byte InterfaceType; /* interface type 1=16K interface */
word Signature; /* ISDN-S adapter Signature (GD) */
PBUFFER XBuffer; /* Transmit Buffer */
PBUFFER RBuffer; /* Receive Buffer */
};
/*------------------------------------------------------------------*/
/* SWReg Values (0 means no command) */
/*------------------------------------------------------------------*/
#define SWREG_DIE_WITH_LEDON 0x01
#define SWREG_HALT_CPU 0x02 /* Push CPU into a while(1) loop */
/*------------------------------------------------------------------*/
/* Id Fields Coding */
/*------------------------------------------------------------------*/
#define ID_MASK 0xe0 /* Mask for the ID field */
#define GL_ERR_ID 0x1f /* ID for error reporting on global requests*/
#define DSIG_ID 0x00 /* ID for D-channel signaling */
#define NL_ID 0x20 /* ID for network-layer access (B or D) */
#define BLLC_ID 0x60 /* ID for B-channel link level access */
#define TASK_ID 0x80 /* ID for dynamic user tasks */
#define TIMER_ID 0xa0 /* ID for timer task */
#define TEL_ID 0xc0 /* ID for telephone support */
#define MAN_ID 0xe0 /* ID for management */
/*------------------------------------------------------------------*/
/* ASSIGN and REMOVE requests are the same for all entities */
/*------------------------------------------------------------------*/
#define ASSIGN 0x01
#define UREMOVE 0xfe /* without returncode */
#define REMOVE 0xff
/*------------------------------------------------------------------*/
/* Timer Interrupt Task Interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TIM 0x01
#define REMOVE_TIM 0xff
/*------------------------------------------------------------------*/
/* dynamic user task interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TSK 0x01
#define REMOVE_TSK 0xff
#define LOAD 0xf0
#define RELOCATE 0xf1
#define START 0xf2
#define LOAD2 0xf3
#define RELOCATE2 0xf4
/*------------------------------------------------------------------*/
/* dynamic user task messages */
/*------------------------------------------------------------------*/
#define TSK_B2 0x0000
#define TSK_WAKEUP 0x2000
#define TSK_TIMER 0x4000
#define TSK_TSK 0x6000
#define TSK_PC 0xe000
/*------------------------------------------------------------------*/
/* LL management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_LL 1 /* assign logical link */
#define REMOVE_LL 0xff /* remove logical link */
/*------------------------------------------------------------------*/
/* LL service primitives */
/*------------------------------------------------------------------*/
#define LL_UDATA 1 /* link unit data request/indication */
#define LL_ESTABLISH 2 /* link establish request/indication */
#define LL_RELEASE 3 /* link release request/indication */
#define LL_DATA 4 /* data request/indication */
#define LL_LOCAL 5 /* switch to local operation (COM only) */
#define LL_DATA_PEND 5 /* data pending indication (SDLC SHM only) */
#define LL_REMOTE 6 /* switch to remote operation (COM only) */
#define LL_TEST 8 /* link test request */
#define LL_MDATA 9 /* more data request/indication */
#define LL_BUDATA 10 /* broadcast unit data request/indication */
#define LL_XID 12 /* XID command request/indication */
#define LL_XID_R 13 /* XID response request/indication */
/*------------------------------------------------------------------*/
/* NL service primitives */
/*------------------------------------------------------------------*/
#define N_MDATA 1 /* more data to come REQ/IND */
#define N_CONNECT 2 /* OSI N-CONNECT REQ/IND */
#define N_CONNECT_ACK 3 /* OSI N-CONNECT CON/RES */
#define N_DISC 4 /* OSI N-DISC REQ/IND */
#define N_DISC_ACK 5 /* OSI N-DISC CON/RES */
#define N_RESET 6 /* OSI N-RESET REQ/IND */
#define N_RESET_ACK 7 /* OSI N-RESET CON/RES */
#define N_DATA 8 /* OSI N-DATA REQ/IND */
#define N_EDATA 9 /* OSI N-EXPEDITED DATA REQ/IND */
#define N_UDATA 10 /* OSI D-UNIT-DATA REQ/IND */
#define N_BDATA 11 /* BROADCAST-DATA REQ/IND */
#define N_DATA_ACK 12 /* data ack ind for D-bit procedure */
#define N_EDATA_ACK 13 /* data ack ind for INTERRUPT */
#define N_Q_BIT 0x10 /* Q-bit for req/ind */
#define N_M_BIT 0x20 /* M-bit for req/ind */
#define N_D_BIT 0x40 /* D-bit for req/ind */
/*------------------------------------------------------------------*/
/* Signaling management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_SIG 1 /* assign signaling task */
#define UREMOVE_SIG 0xfe /* remove signaling task without returncode */
#define REMOVE_SIG 0xff /* remove signaling task */
/*------------------------------------------------------------------*/
/* Signaling service primitives */
/*------------------------------------------------------------------*/
#define CALL_REQ 1 /* call request */
#define CALL_CON 1 /* call confirmation */
#define CALL_IND 2 /* incoming call connected */
#define LISTEN_REQ 2 /* listen request */
#define HANGUP 3 /* hangup request/indication */
#define SUSPEND 4 /* call suspend request/confirm */
#define RESUME 5 /* call resume request/confirm */
#define SUSPEND_REJ 6 /* suspend rejected indication */
#define USER_DATA 8 /* user data for user to user signaling */
#define CONGESTION 9 /* network congestion indication */
#define INDICATE_REQ 10 /* request to indicate an incoming call */
#define INDICATE_IND 10 /* indicates that there is an incoming call */
#define CALL_RES 11 /* accept an incoming call */
#define CALL_ALERT 12 /* send ALERT for incoming call */
#define INFO_REQ 13 /* INFO request */
#define INFO_IND 13 /* INFO indication */
#define REJECT 14 /* reject an incoming call */
#define RESOURCES 15 /* reserve B-Channel hardware resources */
#define TEL_CTRL 16 /* Telephone control request/indication */
#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */
#define FAC_REG_REQ 18 /* connection idependent fac registration */
#define FAC_REG_ACK 19 /* fac registration acknowledge */
#define FAC_REG_REJ 20 /* fac registration reject */
#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */
#define FACILITY_REQ 22 /* send a Facility Message type */
#define FACILITY_IND 22 /* Facility Message type indication */
#define SIG_CTRL 29 /* Control for signalling hardware */
#define DSP_CTRL 30 /* Control for DSPs */
#define LAW_REQ 31 /* Law config request for (returns info_i) */
/*------------------------------------------------------------------*/
/* management service primitives */
/*------------------------------------------------------------------*/
#define MAN_READ 2
#define MAN_WRITE 3
#define MAN_EXECUTE 4
#define MAN_EVENT_ON 5
#define MAN_EVENT_OFF 6
#define MAN_LOCK 7
#define MAN_UNLOCK 8
#define MAN_INFO_IND 2
#define MAN_EVENT_IND 3
#define MAN_TRACE_IND 4
#define MAN_ESC 0x80
/*------------------------------------------------------------------*/
/* return code coding */
/*------------------------------------------------------------------*/
#define UNKNOWN_COMMAND 0x01 /* unknown command */
#define WRONG_COMMAND 0x02 /* wrong command */
#define WRONG_ID 0x03 /* unknown task/entity id */
#define WRONG_CH 0x04 /* wrong task/entity id */
#define UNKNOWN_IE 0x05 /* unknown information el. */
#define WRONG_IE 0x06 /* wrong information el. */
#define OUT_OF_RESOURCES 0x07 /* ISDN-S card out of res. */
#define ADAPTER_DEAD 0x08 /* ISDN card CPU halted */
#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */
#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */
#define ASSIGN_OK 0xef /* ASSIGN OK */
#define OK_FC 0xfc /* Flow-Control RC */
#define READY_INT 0xfd /* Ready interrupt */
#define TIMER_INT 0xfe /* timer interrupt */
#define OK 0xff /* command accepted */
/*------------------------------------------------------------------*/
/* information elements */
/*------------------------------------------------------------------*/
#define SHIFT 0x90 /* codeset shift */
#define MORE 0xa0 /* more data */
#define CL 0xb0 /* congestion level */
/* codeset 0 */
#define BC 0x04 /* Bearer Capability */
#define CAU 0x08 /* cause */
#define CAD 0x0c /* Connected address */
#define CAI 0x10 /* call identity */
#define CHI 0x18 /* channel identification */
#define LLI 0x19 /* logical link id */
#define CHA 0x1a /* charge advice */
#define DT 0x29 /* ETSI date/time */
#define KEY 0x2c /* keypad information element */
#define FTY 0x1c /* facility information element */
#define DSP 0x28 /* display */
#define OAD 0x6c /* origination address */
#define OSA 0x6d /* origination sub-address */
#define CPN 0x70 /* called party number */
#define DSA 0x71 /* destination sub-address */
#define RDX 0x73 /* redirected number extended */
#define RDN 0x74 /* redirected number */
#define LLC 0x7c /* low layer compatibility */
#define HLC 0x7d /* high layer compatibility */
#define UUI 0x7e /* user user information */
#define ESC 0x7f /* escape extension */
#define DLC 0x20 /* data link layer configuration */
#define NLC 0x21 /* network layer configuration */
/* codeset 6 */
#define SIN 0x01 /* service indicator */
#define CIF 0x02 /* charging information */
#define DATE 0x03 /* date */
#define CPS 0x07 /* called party status */
/*------------------------------------------------------------------*/
/* TEL_CTRL contents */
/*------------------------------------------------------------------*/
#define RING_ON 0x01
#define RING_OFF 0x02
#define HANDS_FREE_ON 0x03
#define HANDS_FREE_OFF 0x04
#define ON_HOOK 0x80
#define OFF_HOOK 0x90
#endif

View File

@ -0,0 +1,165 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef PC_MAINT_H
#define PC_MAINT_H
#if !defined(MIPS_SCOM)
#define BUFFER_SZ 48
#define MAINT_OFFS 0x380
#else
#define BUFFER_SZ 128
#define MAINT_OFFS 0xff00
#endif
#define MIPS_BUFFER_SZ 128
#define MIPS_MAINT_OFFS 0xff00
#define DO_LOG 1
#define MEMR 2
#define MEMW 3
#define IOR 4
#define IOW 5
#define B1TEST 6
#define B2TEST 7
#define BTESTOFF 8
#define DSIG_STATS 9
#define B_CH_STATS 10
#define D_CH_STATS 11
#define BL1_STATS 12
#define BL1_STATS_C 13
#define GET_VERSION 14
#define OS_STATS 15
#define XLOG_SET_MASK 16
#define XLOG_GET_MASK 17
#define DSP_READ 20
#define DSP_WRITE 21
#define OK 0xff
#define MORE_EVENTS 0xfe
#define NO_EVENT 1
struct DSigStruc
{
byte Id;
byte uX;
byte listen;
byte active;
byte sin[3];
byte bc[6];
byte llc[6];
byte hlc[6];
byte oad[20];
};
struct BL1Struc {
dword cx_b1;
dword cx_b2;
dword cr_b1;
dword cr_b2;
dword px_b1;
dword px_b2;
dword pr_b1;
dword pr_b2;
word er_b1;
word er_b2;
};
struct L2Struc {
dword XTotal;
dword RTotal;
word XError;
word RError;
};
struct OSStruc {
word free_n;
};
typedef union
{
struct DSigStruc DSigStats;
struct BL1Struc BL1Stats;
struct L2Struc L2Stats;
struct OSStruc OSStats;
byte b[BUFFER_SZ];
word w[BUFFER_SZ>>1];
word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
dword d[BUFFER_SZ>>2];
} BUFFER;
typedef union
{
struct DSigStruc DSigStats;
struct BL1Struc BL1Stats;
struct L2Struc L2Stats;
struct OSStruc OSStats;
byte b[MIPS_BUFFER_SZ];
word w[MIPS_BUFFER_SZ>>1];
word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
dword d[MIPS_BUFFER_SZ>>2];
} MIPS_BUFFER;
#if !defined(MIPS_SCOM)
struct pc_maint
{
byte req;
byte rc;
byte *mem; /*far*/
short length;
word port;
byte fill[6];
BUFFER data;
};
#else
struct pc_maint
{
byte req;
byte rc;
byte reserved[2]; /* R3000 alignment ... */
byte far *mem;
short length;
word port;
byte fill[4]; /* data at offset 16 */
BUFFER data;
};
#endif
struct mi_pc_maint
{
byte req;
byte rc;
byte reserved[2]; /* R3000 alignment ... */
byte *mem; /*far*/
short length;
word port;
byte fill[4]; /* data at offset 16 */
MIPS_BUFFER data;
};
#endif /* PC_MAINT_H */

View File

@ -0,0 +1,86 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#if !defined(PR_PC_H)
#define PR_PC_H
struct pr_ram {
word NextReq; /* pointer to next Req Buffer */
word NextRc; /* pointer to next Rc Buffer */
word NextInd; /* pointer to next Ind Buffer */
byte ReqInput; /* number of Req Buffers sent */
byte ReqOutput; /* number of Req Buffers returned */
byte ReqReserved; /* number of Req Buffers reserved */
byte Int; /* ISDN-P interrupt */
byte XLock; /* Lock field for arbitration */
byte RcOutput; /* number of Rc buffers received */
byte IndOutput; /* number of Ind buffers received */
byte IMask; /* Interrupt Mask Flag */
byte Reserved1[2]; /* reserved field, do not use */
byte ReadyInt; /* request field for ready interrupt */
byte Reserved2[12]; /* reserved field, do not use */
byte InterfaceType; /* interface type 1=16K interface */
word Signature; /* ISDN-P initialized indication */
byte B[1]; /* buffer space for Req,Ind and Rc */
};
typedef struct {
word next;
byte Req;
byte ReqId;
byte ReqCh;
byte Reserved1;
word Reference;
byte Reserved[8];
PBUFFER XBuffer;
} REQ;
typedef struct {
word next;
byte Rc;
byte RcId;
byte RcCh;
byte Reserved1;
word Reference;
byte Reserved2[8];
} RC;
typedef struct {
word next;
byte Ind;
byte IndId;
byte IndCh;
byte MInd;
word MLength;
word Reference;
byte RNR;
byte Reserved;
dword Ack;
PBUFFER RBuffer;
} IND;
#endif

503
drivers/isdn/eicon/pri.c Normal file
View File

@ -0,0 +1,503 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* Diva Server PRI specific part of initialisation */
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "adapter.h"
#include "uxio.h"
#define DIVAS_LOAD_CMD 0x02
#define DIVAS_START_CMD 0x03
#define DIVAS_IRQ_RESET 0xC18
#define DIVAS_IRQ_RESET_VAL 0xFE
#define TEST_INT_DIVAS 0x11
#define TEST_INT_DIVAS_BRI 0x12
#define DIVAS_RESET 0x81
#define DIVAS_LED1 0x04
#define DIVAS_LED2 0x08
#define DIVAS_LED3 0x20
#define DIVAS_LED4 0x40
#define DIVAS_RESET_REG 0x20
#define DIVAS_SIGNATURE 0x4447
/* offset to start of MAINT area (used by xlog) */
#define DIVAS_MAINT_OFFSET 0xef00 /* value for PRI card */
#define MP_PROTOCOL_ADDR 0xA0011000
#define MP_DSP_CODE_BASE 0xa03a0000
typedef struct {
dword cmd;
dword addr;
dword len;
dword err;
dword live;
dword reserved[(0x1020>>2)-6];
dword signature;
byte data[1];
} diva_server_boot_t;
byte mem_in(ADAPTER *a, void *adr);
word mem_inw(ADAPTER *a, void *adr);
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
void mem_out(ADAPTER *a, void *adr, byte data);
void mem_outw(ADAPTER *a, void *adr, word data);
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_inc(ADAPTER *a, void *adr);
int DivasPRIInitPCI(card_t *card, dia_card_t *cfg);
static int diva_server_reset(card_t *card)
{
byte *reg;
diva_server_boot_t *boot = NULL;
dword live = 0;
int i = 0;
dword dwWait;
DPRINTF(("divas: reset Diva Server PRI"));
reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], DIVAS_RESET |
DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4);
for (dwWait = 0x000fffff; dwWait; dwWait--)
;
UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], 0x00);
for (dwWait = 0x000fffff; dwWait; dwWait--)
;
UxCardMemDetach(card->hw, reg);
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
UxCardMemOutD(card->hw, boot->reserved, 0);
live = UxCardMemInD(card->hw, &boot->live);
for (i=0; i<5; i++)
{
if (live != UxCardMemInD(card->hw, &boot->live))
{
break;
}
UxPause(10);
}
if (i == 5)
{
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: card is reset but CPU not running"));
return -1;
}
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: card reset after %d ms", i * 10));
return 0;
}
static int diva_server_config(card_t *card, dia_config_t *config)
{
byte *shared;
int i, j;
DPRINTF(("divas: configure Diva Server PRI"));
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
UxCardLog(0);
for (i=0; i<256; i++)
{
UxCardMemOut(card->hw, &shared[i], 0);
}
UxCardMemOut(card->hw, &shared[ 8], config->tei);
UxCardMemOut(card->hw, &shared[ 9], config->nt2);
UxCardMemOut(card->hw, &shared[10], 0);
UxCardMemOut(card->hw, &shared[11], config->watchdog);
UxCardMemOut(card->hw, &shared[12], config->permanent);
UxCardMemOut(card->hw, &shared[13], config->x_interface);
UxCardMemOut(card->hw, &shared[14], config->stable_l2);
UxCardMemOut(card->hw, &shared[15], config->no_order_check);
UxCardMemOut(card->hw, &shared[16], config->handset_type);
UxCardMemOut(card->hw, &shared[17], 0);
UxCardMemOut(card->hw, &shared[18], config->low_channel);
UxCardMemOut(card->hw, &shared[19], config->prot_version);
UxCardMemOut(card->hw, &shared[20], config->crc4);
for (i=0; i<2; i++)
{
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
}
}
UxCardMemDetach(card->hw, shared);
return 0;
}
static
void diva_server_reset_int(card_t *card)
{
byte *cfg;
cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET], DIVAS_IRQ_RESET_VAL);
UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET + 2], 0);
UxCardMemDetach(card->hw, cfg);
return;
}
static int diva_server_test_int(card_t *card)
{
int i;
byte *shared;
byte req_int;
DPRINTF(("divas: test interrupt for Diva Server PRI"));
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
UxCardMemIn(card->hw, &shared[0x3FE]);
UxCardMemOut(card->hw, &shared[0x3FE], 0);
UxCardMemIn(card->hw, &shared[0x3FE]);
UxCardMemDetach(card->hw, shared);
diva_server_reset_int(card);
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
card->test_int_pend = TEST_INT_DIVAS;
req_int = UxCardMemIn(card->hw, &(((struct pr_ram *)shared)->ReadyInt));
req_int++;
UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->ReadyInt), req_int);
UxCardMemDetach(card->hw, shared);
UxCardLog(0);
for (i = 0; i < 50; i++)
{
if (!card->test_int_pend)
{
break;
}
UxPause(10);
}
if (card->test_int_pend)
{
DPRINTF(("active: timeout waiting for card to interrupt"));
return (-1);
}
return 0;
}
static void print_hdr(unsigned char *code, int offset)
{
unsigned char hdr[80];
int i;
i = 0;
while ((i < (DIM(hdr) -1)) &&
(code[offset + i] != '\0') &&
(code[offset + i] != '\r') &&
(code[offset + i] != '\n'))
{
hdr[i] = code[offset + i];
i++;
}
hdr[i] = '\0';
DPRINTF(("divas: loading %s", hdr));
}
static int diva_server_load(card_t *card, dia_load_t *load)
{
diva_server_boot_t *boot;
int i, offset, length;
dword cmd;
DPRINTF(("divas: loading Diva Server PRI"));
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
switch(load->code_type)
{
case DIA_CPU_CODE:
DPRINTF(("divas: RISC code"));
print_hdr(load->code, 0x80);
UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
break;
case DIA_DSP_CODE:
DPRINTF(("divas: DSP code"));
print_hdr(load->code, 0x0);
UxCardMemOutD(card->hw, &boot->addr,
(MP_DSP_CODE_BASE + (((sizeof(dword) +
(sizeof(t_dsp_download_desc) * DSP_MAX_DOWNLOAD_COUNT))
+ ~ALIGNMENT_MASK_MAESTRA) & ALIGNMENT_MASK_MAESTRA)));
break;
case DIA_TABLE_CODE:
DPRINTF(("divas: TABLE code"));
UxCardMemOutD(card->hw, &boot->addr,
(MP_DSP_CODE_BASE + sizeof(dword)));
break;
case DIA_CONT_CODE:
DPRINTF(("divas: continuation code"));
break;
case DIA_DLOAD_CNT:
DPRINTF(("divas: COUNT code"));
UxCardMemOutD(card->hw, &boot->addr, MP_DSP_CODE_BASE);
break;
default:
DPRINTF(("divas: unknown code type"));
UxCardMemDetach(card->hw, boot);
return -1;
}
UxCardLog(0);
offset = 0;
do
{
length = (load->length - offset >= 400) ? 400 : load->length - offset;
for (i=0; i<length; i++)
{
UxCardMemOut(card->hw, &boot->data[i], load->code[offset+i]);
}
for (i=0; i<length; i++)
{
if (load->code[offset + i] != UxCardMemIn(card->hw, &boot->data[i]))
{
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: card code block verify failed"));
return -1;
}
}
UxCardMemOutD(card->hw, &boot->len, (length + 3) / 4);
UxCardMemOutD(card->hw, &boot->cmd, DIVAS_LOAD_CMD);
for (i=0; i<50000; i++)
{
cmd = UxCardMemInD(card->hw, &boot->cmd);
if (!cmd)
{
break;
}
/*UxPause(1);*/
}
if (cmd)
{
DPRINTF(("divas: timeout waiting for card to ACK load (offset = %d)", offset));
UxCardMemDetach(card->hw, boot);
return -1;
}
offset += length;
} while (offset < load->length);
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: DIVA Server card loaded"));
return 0;
}
static int diva_server_start(card_t *card, byte *channels)
{
diva_server_boot_t *boot;
byte *ram;
int i;
dword signature;
DPRINTF(("divas: start Diva Server PRI"));
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
UxCardMemOutD(card->hw, &boot->cmd, DIVAS_START_CMD);
UxCardLog(0);
for (i = 0; i < 300; i++)
{
signature = UxCardMemInD(card->hw, &boot->signature);
if ((signature >> 16) == DIVAS_SIGNATURE)
{
DPRINTF(("divas: started card after %d ms", i * 10));
break;
}
UxPause(10);
}
if ((signature >> 16) != DIVAS_SIGNATURE)
{
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: timeout waiting for card to run protocol code (sig = 0x%x)", signature));
return -1;
}
ram = (byte *) boot;
ram += DIVAS_SHARED_OFFSET;
*channels = UxCardMemIn(card->hw, &ram[0x3F6]);
card->serial_no = UxCardMemInD(card->hw, &ram[0x3F0]);
UxCardMemDetach(card->hw, boot);
if (diva_server_test_int(card))
{
DPRINTF(("divas: interrupt test failed"));
return -1;
}
DPRINTF(("divas: DIVA Server card started"));
return 0;
}
static
int diva_server_mem_get(card_t *card, mem_block_t *mem_block)
{
byte *a;
byte *card_addr;
word length = 0;
int i;
a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
card_addr = a;
card_addr += mem_block->addr;
for (i=0; i < sizeof(mem_block->data); i++)
{
mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
card_addr++;
length++;
}
UxCardMemDetach(card->hw, a);
return length;
}
/*
* Initialise PRI specific entry points
*/
int DivasPriInit(card_t *card, dia_card_t *cfg)
{
DPRINTF(("divas: initialise Diva Server PRI"));
if (DivasPRIInitPCI(card, cfg) == -1)
{
return -1;
}
card->card_reset = diva_server_reset;
card->card_load = diva_server_load;
card->card_config = diva_server_config;
card->card_start = diva_server_start;
card->reset_int = diva_server_reset_int;
card->card_mem_get = diva_server_mem_get;
card->xlog_offset = DIVAS_MAINT_OFFSET;
card->out = DivasOut;
card->test_int = DivasTestInt;
card->dpc = DivasDpc;
card->clear_int = DivasClearInt;
card->a.ram_out = mem_out;
card->a.ram_outw = mem_outw;
card->a.ram_out_buffer = mem_out_buffer;
card->a.ram_inc = mem_inc;
card->a.ram_in = mem_in;
card->a.ram_inw = mem_inw;
card->a.ram_in_buffer = mem_in_buffer;
card->a.ram_look_ahead = mem_look_ahead;
return 0;
}

119
drivers/isdn/eicon/sys.h Normal file
View File

@ -0,0 +1,119 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* Environment provided by system and miscellaneous definitions */
#if !defined(SYS_H)
#define SYS_H
/* abreviations for unsigned types */
typedef int boolean_t;
typedef unsigned char byte;
typedef unsigned long dword;
typedef unsigned short word;
/* abreviations for volatile types */
typedef volatile byte vbyte;
typedef volatile word vword;
typedef volatile dword vdword;
/* Booleans */
#if !defined(TRUE)
#define TRUE (1)
#define FALSE (0)
#endif
/* NULL pointer */
#if !defined(NULL)
#define NULL ((void *) 0)
#endif
/* MIN and MAX */
#if !defined(MIN)
#define MIN(a,b) ((a)>(b) ? (b) : (a))
#endif
#if !defined(MAX)
#define MAX(a,b) ((a)>(b) ? (a) : (b))
#endif
/* Return the dimension of an array */
#if !defined(DIM)
#define DIM(array) (sizeof (array)/sizeof ((array)[0]))
#endif
/*
* Return the number of milliseconds since last boot
*/
extern dword UxTimeGet(void);
extern void DivasSprintf(char *buffer, char *format, ...);
extern void DivasPrintf(char *format, ...);
/* fatal errors, asserts and tracing */
void HwFatalErrorFrom(char *file, int line);
void HwFatalError(void);
/* void HwAssert(char *file, int line, char *condition); */
#include <linux/kernel.h>
#define _PRINTK printk
#define _PRINTF DivasPrintf
void _PRINTF(char *format, ...);
#define PRINTF(arg_list) _PRINTF arg_list
#if defined DTRACE
# define DPRINTF(arg_list) _PRINTF arg_list
# define KDPRINTF(arg_list) _PRINTF arg_list ; _PRINTK arg_list ; _PRINTK("\n");
#else
# define DPRINTF(arg_list) (void)0
# define KDPRINTF(arg_list) _PRINTK arg_list ; _PRINTK("\n");
#endif
#if !defined(ASSERT)
#if defined DEBUG || defined DBG
# define HwFatalError() HwFatalErrorFrom(__FILE__, __LINE__)
# define ASSERT(cond) \
if (!(cond)) \
{ \
/* HwAssert(__FILE__, __LINE__, #cond);*/ \
}
#else
# define ASSERT(cond) ((void)0)
#endif
#endif /* !defined(ASSERT) */
#define TRACE (_PRINTF(__FILE__"@%d\n", __LINE__))
#endif /* SYS_H */

216
drivers/isdn/eicon/uxio.h Normal file
View File

@ -0,0 +1,216 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.4
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Interface to Unix specific code for performing card I/O
*/
#if !defined(UXIO_H)
#define UXIO_H
#include "sys.h"
#include "adapter.h"
struct pt_regs;
/* user callback, returns zero if interrupt was from this card */
typedef void isr_fn_t(void *);
struct ux_diva_card_s
{
word in_use;
int io_base;
int reset_base;
int card_type;
byte *mapped;
int bus_num;
int func_num;
int slot;
int irq;
byte *pDRAM;
byte *pDEVICES;
byte *pCONFIG;
byte *pSHARED;
byte *pCONTROL;
word features;
void *user_isr_arg;
isr_fn_t *user_isr;
};
void bcopy(void *pSource, void *pDest, dword dwLength);
void bzero(void *pDataArea, dword dwLength);
/*
* Get a card handle to enable card to be accessed
*/
int UxCardHandleGet( ux_diva_card_t **card,
dia_card_t *cfg);
/*
* Free a card handle as no longer needed
*/
void UxCardHandleFree(ux_diva_card_t *card);
/*
* Lock and unlock access to a card
*/
int UxCardLock(ux_diva_card_t *card);
void UxCardUnlock(ux_diva_card_t *card, int ipl);
/*
* Set the mapping address for PCI cards
*/
int UxCardAddrMappingSet(ux_diva_card_t *card,
int id,
void *address,
int size);
/*
* Attach card to memory to enable it to be accessed
* Returns the mapped address
*/
void *UxCardMemAttach(ux_diva_card_t *card, int id);
/*
* map card out of memory after completion of access
*/
void UxCardMemDetach(ux_diva_card_t *card, void *address);
/*
* input functions for memory-mapped cards
*/
byte UxCardMemIn(ux_diva_card_t *card, void *address);
word UxCardMemInW(ux_diva_card_t *card, void *address);
dword UxCardMemInD(ux_diva_card_t *card, void *address);
void UxCardMemInBuffer( ux_diva_card_t *card,
void *address,
void *buffer,
int length);
/*
* output functions for memory-mapped cards
*/
void UxCardMemOut(ux_diva_card_t *card, void *address, byte data);
void UxCardMemOutW(ux_diva_card_t *card, void *address, word data);
void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data);
void UxCardMemOutBuffer( ux_diva_card_t *card,
void *address,
void *buffer,
int length);
/*
* input functions for I/O-mapped cards
*/
byte UxCardIoIn(ux_diva_card_t *card, void *, void *address);
word UxCardIoInW(ux_diva_card_t *card, void *, void *address);
dword UxCardIoInD(ux_diva_card_t *card, void *, void *address);
void UxCardIoInBuffer( ux_diva_card_t *card,
void *, void *address,
void *buffer,
int length);
/*
* output functions for I/O-mapped cards
*/
void UxCardIoOut(ux_diva_card_t *card, void *, void *address, byte data);
void UxCardIoOutW(ux_diva_card_t *card, void *, void *address, word data);
void UxCardIoOutD(ux_diva_card_t *card, void *, void *address, dword data);
void UxCardIoOutBuffer( ux_diva_card_t *card,
void *, void *address,
void *buffer,
int length);
/*
* Get specified PCI config
*/
void UxPciConfigRead(ux_diva_card_t *card,
int size,
int offset,
void *value);
/*
* Set specified PCI config
*/
void UxPciConfigWrite(ux_diva_card_t *card,
int size,
int offset,
void *value);
/* allocate memory, returning NULL if none available */
void *UxAlloc(unsigned int size);
void UxFree(void *);
/*
* Pause for specified number of milli-seconds
*/
void UxPause(long ms);
/*
* Install an ISR for the specified card
*/
int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg);
/*
* Remove an ISR for the specified card
*/
void UxIsrRemove(ux_diva_card_t *card, void *);
/*
* DEBUG function to turn logging ON or OFF
*/
void UxCardLog(int turn_on);
#endif /* of UXIO_H */

183
drivers/isdn/eicon/xlog.c Normal file
View File

@ -0,0 +1,183 @@
/*
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* This source file is supplied for the exclusive use with Eicon
* Technology Corporation's range of DIVA Server Adapters.
*
* Eicon File Revision : 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Unix Eicon active card driver
* XLOG related functions
*/
#include "sys.h"
#include "idi.h"
#include "pc.h"
#include "pc_maint.h"
#include "divalog.h"
#include "adapter.h"
#include "uxio.h"
/*
* convert/copy XLOG info into a KLOG entry
*/
static
void xlog_to_klog(byte *b, int size, int card_num)
{
typedef struct
{
word code;
word time_hi;
word time_lo;
word xcode;
byte data[2];
} card_xlog_t;
card_xlog_t *x;
klog_t klog;
x = (card_xlog_t *) b;
bzero(&klog, sizeof(klog));
klog.time_stamp = (dword) x->time_hi;
klog.time_stamp = (klog.time_stamp << 16) | (dword) x->time_lo;
klog.length = size > sizeof(klog.buffer) ? sizeof(klog.buffer) : size;
klog.card = card_num;
if (x->code == 1)
{
klog.type = KLOG_XTXT_MSG;
klog.code = 0;
bcopy(&x->xcode, klog.buffer, klog.length);
}
else if (x->code == 2)
{
klog.type = KLOG_XLOG_MSG;
klog.code = x->xcode;
bcopy(&x->data, klog.buffer, klog.length);
}
else
{
char *c; int i;
klog.type = KLOG_TEXT_MSG;
klog.code = 0;
c = "divas: invalid xlog message code from card";
i = 0;
while (*c)
{
klog.buffer[i] = *c;
c++;
i++;
}
klog.buffer[i] = *c;
}
/* send to the log driver and return */
DivasLogAdd(&klog, sizeof(klog));
return;
}
/*
* send an XLOG request down to specified card
* if response available from previous request then read it
* if not then just send down new request, ready for next time
*/
void DivasXlogReq(int card_num)
{
card_t *card;
ADAPTER *a;
if ((card_num < 0) || (card_num > DivasCardNext))
{
DPRINTF(("xlog: invalid card number"));
return;
}
card = &DivasCards[card_num];
if (DivasXlogRetrieve(card))
{
return;
}
/* send down request for next time */
a = &card->a;
a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
return;
}
/*
* retrieve XLOG request from specified card
* returns non-zero if new request sent to card
*/
int DivasXlogRetrieve(card_t *card)
{
ADAPTER *a;
struct mi_pc_maint pcm;
a = &card->a;
/* get status of last request */
pcm.rc = a->ram_in(a, (word *)(card->xlog_offset + 1));
/* if nothing there from previous request, send down a new one */
if (pcm.rc == OK)
{
/* read in response */
a->ram_in_buffer(a, (word *) (dword) card->xlog_offset, &pcm, sizeof(pcm));
xlog_to_klog((byte *) &pcm.data, sizeof(pcm.data),
(int) (card - DivasCards));
}
/* if any response received from card, re-send request */
if (pcm.rc)
{
a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
return 1;
}
return 0;
}