Start of new driver V2.
This commit is contained in:
parent
c86c3637cb
commit
390db3a46d
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -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
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -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 */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* #################################################################################### */
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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, ®[DIVAS_RESET_REG], DIVAS_RESET |
|
||||
DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4);
|
||||
|
||||
for (dwWait = 0x000fffff; dwWait; dwWait--)
|
||||
;
|
||||
|
||||
UxCardMemOut(card->hw, ®[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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue