mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-16 15:11:52 +00:00
Submitted by: Juha-Matti Liukkonen (Cubical Solutions Ltd) (jml@cubical.fi)
Add a CAPI (hardware independent) driver i4bcapi(4) and hardware driver iavc (4) to support active CAPI-based BRI and PRI cards (currently AVM B1 and T1 cards) to isdn4bsd.
This commit is contained in:
parent
1166fb516b
commit
6b244dc54b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=77164
@ -2323,6 +2323,10 @@ hint.pcf.0.irq="5"
|
||||
# ifpnp - AVM Fritz!Card PnP driver
|
||||
# itjc - Siemens ISAC / TJNet Tiger300/320 chipset
|
||||
#
|
||||
# i4b active ISDN cards support contains the following hardware drivers:
|
||||
#
|
||||
# iavc - AVM B1 PCI, AVM B1 ISA, AVM T1
|
||||
#
|
||||
# Note that the ``options'' (if given) and ``device'' lines must BOTH
|
||||
# be uncommented to enable support for a given card !
|
||||
#
|
||||
@ -2459,6 +2463,17 @@ device iwic
|
||||
device itjc
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
# iavc driver (AVM active cards, needs i4bcapi driver!)
|
||||
#
|
||||
device iavc
|
||||
#
|
||||
# AVM B1 ISA bus (PnP mode not supported!)
|
||||
# ----------------------------------------
|
||||
hint.iavc.0.at="isa"
|
||||
hint.iavc.0.port="0x150"
|
||||
hint.iavc.0.irq="5"
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
# ISDN Protocol Stack - mandatory for all hardware drivers
|
||||
#
|
||||
# Q.921 / layer 2 - i4b passive cards D channel handling
|
||||
@ -2499,9 +2514,12 @@ options IPR_LOG=32
|
||||
# number of sppp device to be configured
|
||||
device "i4bisppp" 4
|
||||
#
|
||||
# B-channel inteface to the netgraph subsystem
|
||||
# B-channel interface to the netgraph subsystem
|
||||
device "i4bing" 2
|
||||
#
|
||||
# CAPI driver needed for active ISDN cards (see iavc driver above)
|
||||
device "i4bcapi"
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Parallel-Port Bus
|
||||
|
@ -654,6 +654,19 @@ i4b/driver/i4b_isppp.c count i4bisppp
|
||||
i4b/driver/i4b_ispppsubr.c optional i4bisppp
|
||||
net/slcompress.c optional i4bisppp
|
||||
#
|
||||
# isdn4bsd CAPI driver
|
||||
#
|
||||
i4b/capi/capi_l4if.c count i4bcapi
|
||||
i4b/capi/capi_llif.c optional i4bcapi
|
||||
i4b/capi/capi_msgs.c optional i4bcapi
|
||||
#
|
||||
# isdn4bsd AVM B1/T1 CAPI driver
|
||||
#
|
||||
i4b/capi/iavc/iavc_pci.c count iavc
|
||||
i4b/capi/iavc/iavc_isa.c optional iavc
|
||||
i4b/capi/iavc/iavc_lli.c optional iavc
|
||||
i4b/capi/iavc/iavc_card.c optional iavc
|
||||
#
|
||||
# isdn4bsd support
|
||||
#
|
||||
i4b/layer2/i4b_mbuf.c optional i4btrc
|
||||
|
@ -2323,6 +2323,10 @@ hint.pcf.0.irq="5"
|
||||
# ifpnp - AVM Fritz!Card PnP driver
|
||||
# itjc - Siemens ISAC / TJNet Tiger300/320 chipset
|
||||
#
|
||||
# i4b active ISDN cards support contains the following hardware drivers:
|
||||
#
|
||||
# iavc - AVM B1 PCI, AVM B1 ISA, AVM T1
|
||||
#
|
||||
# Note that the ``options'' (if given) and ``device'' lines must BOTH
|
||||
# be uncommented to enable support for a given card !
|
||||
#
|
||||
@ -2459,6 +2463,17 @@ device iwic
|
||||
device itjc
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
# iavc driver (AVM active cards, needs i4bcapi driver!)
|
||||
#
|
||||
device iavc
|
||||
#
|
||||
# AVM B1 ISA bus (PnP mode not supported!)
|
||||
# ----------------------------------------
|
||||
hint.iavc.0.at="isa"
|
||||
hint.iavc.0.port="0x150"
|
||||
hint.iavc.0.irq="5"
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
# ISDN Protocol Stack - mandatory for all hardware drivers
|
||||
#
|
||||
# Q.921 / layer 2 - i4b passive cards D channel handling
|
||||
@ -2499,9 +2514,12 @@ options IPR_LOG=32
|
||||
# number of sppp device to be configured
|
||||
device "i4bisppp" 4
|
||||
#
|
||||
# B-channel inteface to the netgraph subsystem
|
||||
# B-channel interface to the netgraph subsystem
|
||||
device "i4bing" 2
|
||||
#
|
||||
# CAPI driver needed for active ISDN cards (see iavc driver above)
|
||||
device "i4bcapi"
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Parallel-Port Bus
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
|
||||
* Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -27,11 +27,9 @@
|
||||
* i4b_debug.h - i4b debug header file
|
||||
* -----------------------------------
|
||||
*
|
||||
* $Id: i4b_debug.h,v 1.32 2000/07/24 12:22:08 hm Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Wed Oct 18 09:48:16 2000]
|
||||
* last edit-date: [Mon May 21 10:05:34 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -169,13 +167,12 @@ extern unsigned int i4b_l4_debug;
|
||||
#define L4_RBCHDBG 0x0020 /* rbch driver debug messages */
|
||||
#define L4_ISPDBG 0x0040 /* isp driver debug messages */
|
||||
#define L4_TELDBG 0x0080 /* tel driver debug messages */
|
||||
#define L4_TINADBG 0x0100 /* tina driver debug messages */
|
||||
#define L4_TINAMSG 0x0200 /* tina driver messages */
|
||||
#define L4_TINAERR 0x0400 /* tina driver error messages */
|
||||
#define L4_INGDBG 0x0800 /* ing driver debug messages */
|
||||
#define L4_INGDBG 0x0100 /* ing driver debug messages */
|
||||
#define L4_IAVCDBG 0x0200 /* AVM B1 driver debug messages */
|
||||
#define L4_CAPIDBG 0x0400 /* CAPI driver debug messages */
|
||||
|
||||
#define L4_DEBUG_MAX 0x0fff /* all messages on */
|
||||
#define L4_DEBUG_ERR (L4_ERR | L4_TINADBG | L4_TINAMSG | L4_TINAERR)
|
||||
#define L4_DEBUG_ERR L4_ERR
|
||||
|
||||
#ifndef L4_DEBUG_DEFAULT
|
||||
#ifdef DO_I4B_MAXDEBUG
|
||||
|
@ -29,7 +29,7 @@
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Fri Jan 26 13:46:50 2001]
|
||||
* last edit-date: [Fri May 25 10:04:37 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -45,9 +45,9 @@
|
||||
/*---------------------------------------------------------------------------*
|
||||
* version and release number for isdn4bsd package
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define VERSION 0 /* version number */
|
||||
#define REL 96 /* release number */
|
||||
#define STEP 3 /* release step */
|
||||
#define VERSION 1 /* version number */
|
||||
#define REL 0 /* release number */
|
||||
#define STEP 0 /* release step */
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* date/time format in i4b log messages
|
||||
@ -82,7 +82,8 @@
|
||||
#define CTRL_DAIC 2 /* Diehl active controller cards*/
|
||||
#define CTRL_TINADD 3 /* Stollmann Tina-dd active card*/
|
||||
#define CTRL_AVMB1 4 /* AVM B1 active card */
|
||||
#define CTRL_NUMTYPES 5 /* number of controller types */
|
||||
#define CTRL_CAPI 5 /* cards seen via the CAPI layer*/
|
||||
#define CTRL_NUMTYPES 6 /* number of controller types */
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* CTRL_PASSIVE: driver types
|
||||
@ -155,6 +156,14 @@
|
||||
#define CARD_TYPEA_DAIC_SCOM 3
|
||||
#define CARD_TYPEA_DAIC_QUAD 4
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* card types for CTRL_CAPI
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define CARD_TYPEC_CAPI_UNK 0
|
||||
#define CARD_TYPEC_AVM_T1_PCI 1
|
||||
#define CARD_TYPEC_AVM_B1_PCI 2
|
||||
#define CARD_TYPEC_AVM_B1_ISA 3
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* max length of some strings
|
||||
*---------------------------------------------------------------------------*/
|
||||
@ -592,6 +601,7 @@ typedef struct {
|
||||
int ctrl_type; /* controller type passive/active */
|
||||
int card_type; /* brand / version */
|
||||
int tei; /* tei controller probably has */
|
||||
int nbch; /* number of b channels provided */
|
||||
} msg_ctrl_info_req_t;
|
||||
|
||||
#define I4B_CTRL_INFO_REQ _IOWR('4', 4, msg_ctrl_info_req_t)
|
||||
|
150
sys/i4b/capi/README
Normal file
150
sys/i4b/capi/README
Normal file
@ -0,0 +1,150 @@
|
||||
$FreeBSD$
|
||||
|
||||
Message-ID: <3AF56886.7D92609A@cubical.fi>
|
||||
Date: Sun, 06 May 2001 18:06:47 +0300
|
||||
From: Juha-Matti Liukkonen <jml@cubical.fi>
|
||||
Organization: Cubical Solutions Ltd
|
||||
|
||||
Please find the attached diff and tarball for our support software for
|
||||
CAPI 2.0 and AVM's active T1 and T1-B (primary rate) and B1 (basic rate)
|
||||
ISDN adapters for isdn4bsd. The implementation has been made from
|
||||
scratch by us, based on reverse engineering of the Linux driver provided
|
||||
by AVM GmbH and available in ftp.avm.de. Cubical Solutions Ltd offers
|
||||
this implementation for the BSD community free of charge and assuming
|
||||
absolutely no liabilities whatsoever. Feel free to modify the
|
||||
implementation any way you see fit, but please retain our one-liner
|
||||
copyright statement somewhere in the comment headers in the capi and
|
||||
iavc driver modules.
|
||||
|
||||
That said, the attached tarball is i4b-00.96.00-beta with our
|
||||
modifications integrated, and the diff contains all modifications we
|
||||
have made to the original (including the new capi files). Our mods add
|
||||
pseudo-device i4bcapi, which attaches to i4b layer 4, and device iavc0,
|
||||
which implements a link layer driver for AVM's active B1 and T1 adapters
|
||||
for i4bcapi. There are also a couple of related improvements to isdnd,
|
||||
and a number of modifications to isdnd and layer 4 to implement support
|
||||
for up to 30 channels per adapter (for primary rate use).
|
||||
|
||||
We have developed the software explicitly for our telephony application,
|
||||
to be used with AVM's T1 adapters, and the implementation has been
|
||||
tested primarily with this functionality in mind. There may be
|
||||
interesting side effects with eg. the ipr and isppp drivers; we do not
|
||||
use them and therefore their testing has been cursory at best. The
|
||||
i4btel driver works well with the T1 (our primary use), and the i4brbch
|
||||
driver has been verified to work with T1, T1-B and B1 adapters (ftp'd
|
||||
some files over a dialup PPP connection with each adapter). Only the PCI
|
||||
versions of the adapters (equipped with the AMCC DMA controller) are
|
||||
supported, although the basics (PIO mode communication) for the older
|
||||
ISA model support is in place, so only the bus attachment modules should
|
||||
be required to support the older hardware.
|
||||
|
||||
All of the AVM active adapters use downloadable firmware, which is not
|
||||
included in the attached package. The firmware files (t1.t4, t1b.t4,
|
||||
b1.t4) can be found from ftp.avm.de in adapter specific subdirectories,
|
||||
or from the CDs provided with the adapters (in directory
|
||||
'cardware/firmware').
|
||||
|
||||
Our primary development platform is our own embedded build (we call it
|
||||
'ebsd') based on FreeBSD 4.2-RELEASE. The implementation has also been
|
||||
tested on standard FreeBSD 4.2-RELEASE system. The implementation should
|
||||
not contain any FreeBSD (or even FreeBSD release) specific issues, but
|
||||
it has not been tested or even compiled on any other platforms;
|
||||
specifically, only the FreeBSD overinstall.sh script is modified to
|
||||
install the capi/iavc support in the kernel source tree.
|
||||
|
||||
This code is not under active development here since the functionality
|
||||
we use (i4btel, T1) has been working since the beginning of March. We
|
||||
are also not planning on any further development (no need seen at this
|
||||
point), but I am naturally interested on whatever bugs and development
|
||||
ideas pop up on the community and will keep a keen eye on the isdn
|
||||
mailing list. I personally may be available for consultation, debugging
|
||||
and possibly development projects, but with notable reservations on my
|
||||
time (the current IT industry recession seems to be pushing even more
|
||||
work for us, which tends to keep us pretty busy these days).
|
||||
|
||||
Here are some specific technical notes:
|
||||
|
||||
* isdnd supports new keyword 'firmware=</path/to/file>' in section
|
||||
'controller'. This keyword is supported for all controller types, and
|
||||
causes I4B_CTRL_DOWNLOAD ioctl to be invoked with the specified file as
|
||||
an argument. In systems equipped with both active and passive adapters,
|
||||
and the passive cards being detected first, dummy 'controller' entries
|
||||
are required for the passive cards to get the correct firmwares to
|
||||
correct adapters. (I hope you did not have other uses for this ioctl in
|
||||
mind?)
|
||||
|
||||
* isdnd supports new keyword 'clone=<entry name>' in section 'entry'.
|
||||
This causes the entry to be copied from the existing named entry. At
|
||||
least entry specific 'name' and 'usrdeviceunit' values should be
|
||||
specified after a 'clone'. (Makes configuring 30 or 60 entries way much
|
||||
easier.)
|
||||
|
||||
* a bug in i4btel driver read routine corrected. The conditions in the
|
||||
while() clause caused the receive queue to be referenced before checking
|
||||
if a channel is connected, leading to kernel panic (do a 'dd
|
||||
if=/dev/i4btel0 of=/dev/null' on an unconnected tel device, panic will
|
||||
follow). Correction was to reorder the while clause conditions to check
|
||||
for connectedness first.
|
||||
|
||||
* isdnd and i4b layer 4 support up to CHANNELS_MAX (=30) channels per
|
||||
adapter. The msg_ctrl_info_req_t message reports the number of channels
|
||||
provided by the adapter, the number is stored in the nbchan field of the
|
||||
controller state structure. The fixed stateb1 and stateb2 entries in
|
||||
controller state stuctures are replaced with an array, and all fixed
|
||||
references there are replaced with loops up to nbchan. Passive stack
|
||||
layer 1 and 2 are not modified, layer 3 sets this field to fixed value 2
|
||||
for all adapters (but it could be delegated to the layer 1 driver's
|
||||
attach request).
|
||||
|
||||
* the i4bcapi driver maps i4b channels to logical channels identified
|
||||
with PLCI/NCCI values in the CAPI protocol using the sc_bchan[] array.
|
||||
The PLCI/NCCI handling is merged in the channel mapping and is greatly
|
||||
simplified from the reference state machine model, because in practice
|
||||
there can be only one PLCI/NCCI per channel active at any given time.
|
||||
|
||||
* the i4bcapi driver does not provide any kind of user level interface
|
||||
(such as the /dev/capi20 interface provided by the linux driver), but
|
||||
could relatively easily be extended to do so (and if done, interface
|
||||
compatibility with the linux implementation would probably be a good
|
||||
goal).
|
||||
|
||||
* there are some gritty details in the iavc driver, inherited from the
|
||||
linux code. Despite us being a legitimate company in the telecom
|
||||
business, AVM failed to produce any programming reference material for
|
||||
us (at least in a reasonable time frame), so some guesswork remains due
|
||||
to classic reverse engineering process (particularly there are a few
|
||||
magic numbers in the card initialization sequence whose meaning I do not
|
||||
know).
|
||||
|
||||
* pseudo-devices i4bq931, i4bq921 and some passive stack layer 1 driver
|
||||
(such as iwic) are required to compile, as the required ctrl_desc[]
|
||||
array is in layer 3, which requires layer 2, which requires layer 1.
|
||||
Some architectural cleanup would come in handy here, but we did not want
|
||||
to start making any major changes (and we use iwic in test setups
|
||||
anyway, so we simply always compile it in).
|
||||
|
||||
To summarize: unpack, overinstall, add the following lines (with the
|
||||
usual passive stack configuration including at least one L1 driver) to
|
||||
your kernel configuration file:
|
||||
|
||||
pseudo-device "i4bcapi"
|
||||
device iavc0
|
||||
|
||||
...and the following to your isdnd.rc:
|
||||
|
||||
controller
|
||||
firmware = /usr/lib/isdn/b1.t4
|
||||
|
||||
...compile your new kernel, make sure the firmware file is in
|
||||
/usr/lib/isdn, and your B1 adapter should boot up and Just Work (tm). If
|
||||
you have multiple adapters, you need a 'controller' section for each to
|
||||
have them loaded and booted on isdnd startup.
|
||||
|
||||
Have fun -- and let me know if there are any complications, or if I can
|
||||
be of further assistance,
|
||||
|
||||
- Juha
|
||||
--
|
||||
Juha-Matti Liukkonen, Cubical Solutions Ltd
|
||||
Phone: +358(0)405280142
|
||||
Email: jml@cubical.fi
|
129
sys/i4b/capi/capi.h
Normal file
129
sys/i4b/capi/capi.h
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi.h The CAPI device interface.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _I4B_CAPI_H_
|
||||
#define _I4B_CAPI_H_
|
||||
|
||||
/*
|
||||
// CAPI driver context: B channels and controller softcs.
|
||||
*/
|
||||
|
||||
#define INVALID -1
|
||||
|
||||
enum capi_b_state {
|
||||
B_FREE, /* channel free, ncci invalid */
|
||||
B_CONNECT_CONF, /* wait for CONNECT_CONF */
|
||||
B_CONNECT_IND, /* IND got, wait for appl RESP */
|
||||
B_CONNECT_ACTIVE_IND, /* wait for CONNECT_ACTIVE_IND */
|
||||
B_CONNECT_B3_CONF, /* wait for CONNECT_B3_CONF */
|
||||
B_CONNECT_B3_IND, /* wait for CONNECT_B3_IND */
|
||||
B_CONNECT_B3_ACTIVE_IND, /* wait for CONNECT_B3_ACTIVE_IND */
|
||||
B_CONNECTED, /* channel connected & in use */
|
||||
B_DISCONNECT_CONF, /* wait for DISCONNECT_CONF */
|
||||
B_DISCONNECT_B3_CONF, /* wait for DISCONNECT_B3_CONF */
|
||||
B_DISCONNECT_IND, /* wait for DISCONNECT_IND */
|
||||
};
|
||||
|
||||
typedef struct capi_bchan
|
||||
{
|
||||
/* Channel state */
|
||||
|
||||
int ncci;
|
||||
#define CAPI_CTRL_MASK 0x000000ff
|
||||
#define CAPI_PLCI_MASK 0x0000ffff
|
||||
#define CAPI_NCCI_MASK 0xffff0000
|
||||
u_int16_t msgid;
|
||||
int busy;
|
||||
enum capi_b_state state;
|
||||
|
||||
struct ifqueue tx_queue;
|
||||
struct ifqueue rx_queue;
|
||||
int rxcount;
|
||||
int txcount;
|
||||
|
||||
/* The rest is needed for i4b integration */
|
||||
|
||||
int bprot;
|
||||
int cdid;
|
||||
|
||||
struct mbuf *in_mbuf;
|
||||
isdn_link_t capi_isdn_linktab;
|
||||
drvr_link_t *capi_drvr_linktab;
|
||||
} capi_bchan_t;
|
||||
|
||||
enum capi_c_state {
|
||||
C_DOWN, /* controller uninitialized */
|
||||
C_READY, /* controller initialized but not listening */
|
||||
C_UP, /* controller listening */
|
||||
};
|
||||
|
||||
typedef struct capi_softc {
|
||||
int sc_unit; /* index in capi_sc[] */
|
||||
int ctrl_unit; /* index in isdn_ctrl_tab[] */
|
||||
int card_type; /* CARD_TYPEC_xxx, filled by ll driver */
|
||||
int sc_nbch; /* number of b channels on this controller */
|
||||
int sc_enabled; /* is daemon connected TRUE/FALSE */
|
||||
int sc_msgid; /* next CAPI message id */
|
||||
char sc_profile[64];/* CAPI profile data */
|
||||
enum capi_c_state sc_state;
|
||||
|
||||
capi_bchan_t sc_bchan[MAX_BCHAN];
|
||||
|
||||
/* Link layer driver context holder and methods */
|
||||
|
||||
void *ctx;
|
||||
|
||||
int (*load)(struct capi_softc *, int, u_int8_t *);
|
||||
int (*reg_appl)(struct capi_softc *, int, int);
|
||||
int (*rel_appl)(struct capi_softc *, int);
|
||||
int (*send)(struct capi_softc *, struct mbuf *);
|
||||
} capi_softc_t;
|
||||
|
||||
extern capi_softc_t *capi_sc[];
|
||||
extern int ncapi;
|
||||
|
||||
/*
|
||||
// CAPI upcalls for the link layer.
|
||||
*/
|
||||
|
||||
#define I4BCAPI_APPLID 1
|
||||
|
||||
extern int capi_ll_attach(capi_softc_t *);
|
||||
extern int capi_ll_control(capi_softc_t *, int op, int arg);
|
||||
|
||||
#define CAPI_CTRL_READY 0 /* ctrl ready, value=TRUE/FALSE */
|
||||
#define CAPI_CTRL_PROFILE 1 /* set CAPI profile */
|
||||
#define CAPI_CTRL_NEW_NCCI 2 /* new ncci value, assign bchan */
|
||||
#define CAPI_CTRL_FREE_NCCI 3 /* free ncci value, clear bchan */
|
||||
|
||||
extern int capi_ll_receive(capi_softc_t *, struct mbuf *);
|
||||
|
||||
extern int capi_start_tx(capi_softc_t *, int bchan);
|
||||
|
||||
#endif /* _I4B_CAPI_H_ */
|
450
sys/i4b/capi/capi_l4if.c
Normal file
450
sys/i4b/capi/capi_l4if.c
Normal file
@ -0,0 +1,450 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_l4if.c The CAPI i4b L4/device interface.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "i4bcapi.h"
|
||||
#if NI4BCAPI > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <machine/i4b_debug.h>
|
||||
#include <machine/i4b_ioctl.h>
|
||||
#include <machine/i4b_cause.h>
|
||||
|
||||
#include <i4b/include/i4b_l3l4.h>
|
||||
#include <i4b/include/i4b_mbuf.h>
|
||||
#include <i4b/include/i4b_global.h>
|
||||
|
||||
#include <i4b/layer4/i4b_l4.h>
|
||||
|
||||
#include <i4b/capi/capi.h>
|
||||
#include <i4b/capi/capi_msgs.h>
|
||||
|
||||
static void n_connect_request(u_int cdid);
|
||||
static void n_connect_response(u_int cdid, int response, int cause);
|
||||
static void n_disconnect_request(u_int cdid, int cause);
|
||||
static void n_alert_request(u_int cdid);
|
||||
static void n_mgmt_command(int unit, int cmd, void *parm);
|
||||
static int n_download(int unit, int, struct isdn_dr_prot *);
|
||||
|
||||
capi_softc_t *capi_sc[MAX_CONTROLLERS] = { NULL, };
|
||||
int ncapi = 0;
|
||||
|
||||
/*
|
||||
// i4b_capi_{ret,set}_linktab
|
||||
// i4b driver glue.
|
||||
//
|
||||
// i4b_capi_bch_config
|
||||
// Called by i4b driver to flush + {en,dis}able a channel.
|
||||
//
|
||||
// i4b_capi_bch_start_tx
|
||||
// Called by i4b driver to transmit a queued mbuf.
|
||||
//
|
||||
// i4b_capi_bch_stat
|
||||
// Called by i4b driver to obtain statistics information.
|
||||
*/
|
||||
|
||||
static isdn_link_t *
|
||||
i4b_capi_ret_linktab(int unit, int channel)
|
||||
{
|
||||
capi_softc_t *sc = capi_sc[unit];
|
||||
return &sc->sc_bchan[channel].capi_isdn_linktab;
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_set_linktab(int unit, int channel, drvr_link_t *dlt)
|
||||
{
|
||||
capi_softc_t *sc = capi_sc[unit];
|
||||
sc->sc_bchan[channel].capi_drvr_linktab = dlt;
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_bch_config(int unit, int chan, int bprot, int activate)
|
||||
{
|
||||
capi_softc_t *sc = capi_sc[unit];
|
||||
|
||||
i4b_Bcleanifq(&sc->sc_bchan[chan].tx_queue);
|
||||
sc->sc_bchan[chan].tx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
sc->sc_bchan[chan].txcount = 0;
|
||||
|
||||
/* The telephony drivers use rx_queue for receive. */
|
||||
|
||||
i4b_Bcleanifq(&sc->sc_bchan[chan].rx_queue);
|
||||
sc->sc_bchan[chan].rx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
sc->sc_bchan[chan].rxcount = 0;
|
||||
|
||||
/* HDLC frames are put to in_mbuf */
|
||||
|
||||
i4b_Bfreembuf(sc->sc_bchan[chan].in_mbuf);
|
||||
sc->sc_bchan[chan].in_mbuf = NULL;
|
||||
|
||||
/* Because of the difference, we need to remember the protocol. */
|
||||
|
||||
sc->sc_bchan[chan].bprot = bprot;
|
||||
sc->sc_bchan[chan].busy = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_bch_start_tx(int unit, int chan)
|
||||
{
|
||||
capi_softc_t *sc = capi_sc[unit];
|
||||
int s;
|
||||
|
||||
s = SPLI4B();
|
||||
|
||||
if (sc->sc_bchan[chan].state != B_CONNECTED) {
|
||||
splx(s);
|
||||
printf("capi%d: start_tx on unconnected channel\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc->sc_bchan[chan].busy) {
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
|
||||
capi_start_tx(sc, chan);
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static void
|
||||
i4b_capi_bch_stat(int unit, int chan, bchan_statistics_t *bsp)
|
||||
{
|
||||
capi_softc_t *sc = capi_sc[unit];
|
||||
int s = SPLI4B();
|
||||
|
||||
bsp->outbytes = sc->sc_bchan[chan].txcount;
|
||||
bsp->inbytes = sc->sc_bchan[chan].rxcount;
|
||||
|
||||
sc->sc_bchan[chan].txcount = 0;
|
||||
sc->sc_bchan[chan].rxcount = 0;
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
int capi_start_tx(capi_softc_t *sc, int chan)
|
||||
{
|
||||
struct mbuf *m_b3;
|
||||
int sent = 0;
|
||||
|
||||
_IF_DEQUEUE(&sc->sc_bchan[chan].tx_queue, m_b3);
|
||||
while (m_b3) {
|
||||
struct mbuf *m = m_b3->m_next;
|
||||
|
||||
sc->sc_bchan[chan].txcount += m_b3->m_len;
|
||||
capi_data_b3_req(sc, chan, m_b3);
|
||||
sent++;
|
||||
|
||||
m_b3 = m;
|
||||
}
|
||||
|
||||
if (sc->sc_bchan[chan].capi_drvr_linktab) {
|
||||
/* Notify i4b driver of activity, and if the queue is drained. */
|
||||
|
||||
if (sent)
|
||||
(*sc->sc_bchan[chan].capi_drvr_linktab->bch_activity)(
|
||||
sc->sc_bchan[chan].capi_drvr_linktab->unit, ACT_TX);
|
||||
|
||||
if (IF_QEMPTY(&sc->sc_bchan[chan].tx_queue))
|
||||
(*sc->sc_bchan[chan].capi_drvr_linktab->bch_tx_queue_empty)(
|
||||
sc->sc_bchan[chan].capi_drvr_linktab->unit);
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/*
|
||||
// capi_ll_attach
|
||||
// Called by a link layer driver at boot time.
|
||||
*/
|
||||
|
||||
int
|
||||
capi_ll_attach(capi_softc_t *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ncapi == (sizeof(capi_sc) / sizeof(capi_sc[0]))) {
|
||||
printf("capi%d: too many units, increase MAX_CONTROLLERS\n", ncapi);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Unit type and subtype; sc is partly filled by ll driver */
|
||||
|
||||
ctrl_desc[nctrl].unit = ncapi;
|
||||
ctrl_desc[nctrl].ctrl_type = CTRL_CAPI;
|
||||
ctrl_desc[nctrl].card_type = sc->card_type;
|
||||
|
||||
/* L4 callbacks */
|
||||
|
||||
ctrl_types[CTRL_CAPI].get_linktab = i4b_capi_ret_linktab;
|
||||
ctrl_types[CTRL_CAPI].set_linktab = i4b_capi_set_linktab;
|
||||
|
||||
ctrl_desc[nctrl].N_CONNECT_REQUEST = n_connect_request;
|
||||
ctrl_desc[nctrl].N_CONNECT_RESPONSE = n_connect_response;
|
||||
ctrl_desc[nctrl].N_DISCONNECT_REQUEST = n_disconnect_request;
|
||||
ctrl_desc[nctrl].N_ALERT_REQUEST = n_alert_request;
|
||||
ctrl_desc[nctrl].N_DOWNLOAD = n_download;
|
||||
ctrl_desc[nctrl].N_DIAGNOSTICS = NULL; /* XXX todo */
|
||||
ctrl_desc[nctrl].N_MGMT_COMMAND = n_mgmt_command;
|
||||
|
||||
/* Unit state */
|
||||
|
||||
sc->sc_enabled = FALSE;
|
||||
sc->sc_state = C_DOWN;
|
||||
sc->sc_msgid = 0;
|
||||
|
||||
ctrl_desc[nctrl].dl_est = DL_DOWN;
|
||||
ctrl_desc[nctrl].nbch = sc->sc_nbch;
|
||||
|
||||
for (i = 0; i < sc->sc_nbch; i++) {
|
||||
ctrl_desc[nctrl].bch_state[i] = BCH_ST_FREE;
|
||||
sc->sc_bchan[i].ncci = INVALID;
|
||||
sc->sc_bchan[i].msgid = 0;
|
||||
sc->sc_bchan[i].busy = 0;
|
||||
sc->sc_bchan[i].state = B_FREE;
|
||||
|
||||
memset(&sc->sc_bchan[i].tx_queue, 0, sizeof(struct ifqueue));
|
||||
memset(&sc->sc_bchan[i].rx_queue, 0, sizeof(struct ifqueue));
|
||||
sc->sc_bchan[i].tx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
sc->sc_bchan[i].rx_queue.ifq_maxlen = IFQ_MAXLEN;
|
||||
|
||||
#if defined (__FreeBSD__) && __FreeBSD__ > 4
|
||||
mtx_init(&sc->sc_bchan[i].tx_queue.ifq_mtx, "i4b_capi_tx", MTX_DEF);
|
||||
mtx_init(&sc->sc_bchan[i].rx_queue.ifq_mtx, "i4b_capi_rx", MTX_DEF);
|
||||
#endif
|
||||
|
||||
sc->sc_bchan[i].txcount = 0;
|
||||
sc->sc_bchan[i].rxcount = 0;
|
||||
|
||||
sc->sc_bchan[i].cdid = CDID_UNUSED;
|
||||
sc->sc_bchan[i].bprot = BPROT_NONE;
|
||||
sc->sc_bchan[i].in_mbuf = NULL;
|
||||
|
||||
sc->sc_bchan[i].capi_drvr_linktab = NULL;
|
||||
|
||||
sc->sc_bchan[i].capi_isdn_linktab.unit = ncapi;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.channel = i;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.bch_config = i4b_capi_bch_config;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.bch_tx_start = i4b_capi_bch_start_tx;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.bch_stat = i4b_capi_bch_stat;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.tx_queue = &sc->sc_bchan[i].tx_queue;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.rx_queue = &sc->sc_bchan[i].rx_queue;
|
||||
sc->sc_bchan[i].capi_isdn_linktab.rx_mbuf = &sc->sc_bchan[i].in_mbuf;
|
||||
}
|
||||
|
||||
ctrl_desc[nctrl].tei = -1;
|
||||
|
||||
/* Up the controller index and store the softc */
|
||||
|
||||
sc->sc_unit = ncapi;
|
||||
capi_sc[ncapi++] = sc;
|
||||
sc->ctrl_unit = nctrl++;
|
||||
|
||||
printf("capi%d: card type %d attached\n", sc->sc_unit, sc->card_type);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_mgmt_command
|
||||
// i4b L4 management command.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_mgmt_command(int unit, int op, void *arg)
|
||||
{
|
||||
capi_softc_t *sc = capi_sc[unit];
|
||||
|
||||
printf("capi%d: mgmt command %d\n", sc->sc_unit, op);
|
||||
|
||||
switch(op) {
|
||||
case CMR_DOPEN:
|
||||
sc->sc_enabled = TRUE;
|
||||
break;
|
||||
|
||||
case CMR_DCLOSE:
|
||||
sc->sc_enabled = FALSE;
|
||||
break;
|
||||
|
||||
case CMR_SETTRACE:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// n_connect_request
|
||||
// i4b L4 wants to connect. We assign a B channel to the call,
|
||||
// send a CAPI_CONNECT_REQ, and set the channel to B_CONNECT_CONF.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_connect_request(u_int cdid)
|
||||
{
|
||||
call_desc_t *cd = cd_by_cdid(cdid);
|
||||
capi_softc_t *sc;
|
||||
int bch, s;
|
||||
|
||||
if (!cd) {
|
||||
printf("capi?: invalid cdid %d\n", cdid);
|
||||
return;
|
||||
}
|
||||
|
||||
sc = capi_sc[ctrl_desc[cd->controller].unit];
|
||||
bch = cd->channelid;
|
||||
|
||||
s = SPLI4B();
|
||||
|
||||
if ((bch < 0) || (bch >= sc->sc_nbch))
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if (sc->sc_bchan[bch].state == B_FREE)
|
||||
break;
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
splx(s);
|
||||
printf("capi%d: no free B channel\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
cd->channelid = bch;
|
||||
|
||||
capi_connect_req(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_connect_response
|
||||
// i4b L4 answers a call. We send a CONNECT_RESP with the proper
|
||||
// Reject code, and set the channel to B_CONNECT_B3_IND or B_FREE,
|
||||
// depending whether we answer or not.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_connect_response(u_int cdid, int response, int cause)
|
||||
{
|
||||
call_desc_t *cd = cd_by_cdid(cdid);
|
||||
capi_softc_t *sc;
|
||||
int bch, s;
|
||||
|
||||
if (!cd) {
|
||||
printf("capi?: invalid cdid %d\n", cdid);
|
||||
return;
|
||||
}
|
||||
|
||||
sc = capi_sc[ctrl_desc[cd->controller].unit];
|
||||
bch = cd->channelid;
|
||||
|
||||
T400_stop(cd);
|
||||
|
||||
cd->response = response;
|
||||
cd->cause_out = cause;
|
||||
|
||||
s = SPLI4B();
|
||||
capi_connect_resp(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_disconnect_request
|
||||
// i4b L4 wants to disconnect. We send a DISCONNECT_REQ and
|
||||
// set the channel to B_DISCONNECT_CONF.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_disconnect_request(u_int cdid, int cause)
|
||||
{
|
||||
call_desc_t *cd = cd_by_cdid(cdid);
|
||||
capi_softc_t *sc;
|
||||
int bch, s;
|
||||
|
||||
if (!cd) {
|
||||
printf("capi?: invalid cdid %d\n", cdid);
|
||||
return;
|
||||
}
|
||||
|
||||
sc = capi_sc[ctrl_desc[cd->controller].unit];
|
||||
bch = cd->channelid;
|
||||
|
||||
cd->cause_out = cause;
|
||||
|
||||
s = SPLI4B();
|
||||
capi_disconnect_req(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_alert_request
|
||||
// i4b L4 wants to alert an incoming call. We send ALERT_REQ.
|
||||
*/
|
||||
|
||||
static void
|
||||
n_alert_request(u_int cdid)
|
||||
{
|
||||
call_desc_t *cd = cd_by_cdid(cdid);
|
||||
capi_softc_t *sc;
|
||||
int s;
|
||||
|
||||
if (!cd) {
|
||||
printf("capi?: invalid cdid %d\n", cdid);
|
||||
return;
|
||||
}
|
||||
|
||||
sc = capi_sc[ctrl_desc[cd->controller].unit];
|
||||
|
||||
s = SPLI4B();
|
||||
capi_alert_req(sc, cd);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
// n_download
|
||||
// L4 -> firmware download
|
||||
*/
|
||||
|
||||
static int
|
||||
n_download(int unit, int numprotos, struct isdn_dr_prot *protocols)
|
||||
{
|
||||
capi_softc_t *sc = capi_sc[unit];
|
||||
|
||||
if (sc->load) {
|
||||
(*capi_sc[unit]->load)(sc, protocols[0].bytecount,
|
||||
protocols[0].microcode);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif /* NI4BCAPI > 0 */
|
166
sys/i4b/capi/capi_llif.c
Normal file
166
sys/i4b/capi/capi_llif.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_llif.c The i4b CAPI link layer interface.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "i4bcapi.h"
|
||||
#if NI4BCAPI > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <machine/i4b_debug.h>
|
||||
#include <machine/i4b_ioctl.h>
|
||||
#include <machine/i4b_cause.h>
|
||||
|
||||
#include <i4b/include/i4b_l3l4.h>
|
||||
#include <i4b/include/i4b_mbuf.h>
|
||||
#include <i4b/include/i4b_global.h>
|
||||
|
||||
#include <i4b/layer4/i4b_l4.h>
|
||||
|
||||
#include <i4b/capi/capi.h>
|
||||
#include <i4b/capi/capi_msgs.h>
|
||||
|
||||
/*
|
||||
// capi_ll_control
|
||||
// CAPI link layer control routine. Called by a link layer
|
||||
// driver when its state changes.
|
||||
*/
|
||||
|
||||
int
|
||||
capi_ll_control(capi_softc_t *sc, int op, int arg)
|
||||
{
|
||||
switch (op) {
|
||||
case CAPI_CTRL_READY:
|
||||
if (arg) {
|
||||
sc->sc_state = C_READY;
|
||||
|
||||
/*
|
||||
* Register our CAPI ApplId and send CAPI_LISTEN_REQ
|
||||
* with CIP Mask value 1 (match all).
|
||||
*/
|
||||
|
||||
sc->reg_appl(sc, I4BCAPI_APPLID, sc->sc_nbch);
|
||||
capi_listen_req(sc, 0x10007);
|
||||
|
||||
} else {
|
||||
sc->sc_state = C_DOWN;
|
||||
/* XXX go through cds and notify L4 of pdeact? XXX */
|
||||
}
|
||||
break;
|
||||
|
||||
case CAPI_CTRL_PROFILE:
|
||||
bcopy((char*) arg, &sc->sc_profile, sizeof(sc->sc_profile));
|
||||
break;
|
||||
|
||||
case CAPI_CTRL_NEW_NCCI:
|
||||
case CAPI_CTRL_FREE_NCCI:
|
||||
/* We ignore the controller's NCCI notifications. */
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("capi%d: unknown control %d\n", sc->sc_unit, op);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// i4b_capi_handlers
|
||||
// Array of message-handler pairs used to dispatch CAPI
|
||||
// messages sent to I4BCAPI_APPLID.
|
||||
*/
|
||||
|
||||
static struct capi_cmdtab {
|
||||
u_int16_t cmd;
|
||||
void (*handler)(capi_softc_t *, struct mbuf *);
|
||||
} i4b_capi_handlers[] = {
|
||||
{ CAPI_LISTEN_CONF, capi_listen_conf },
|
||||
{ CAPI_INFO_IND, capi_info_ind },
|
||||
{ CAPI_ALERT_CONF, capi_alert_conf },
|
||||
{ CAPI_CONNECT_CONF, capi_connect_conf },
|
||||
{ CAPI_CONNECT_IND, capi_connect_ind },
|
||||
{ CAPI_CONNECT_ACTIVE_IND, capi_connect_active_ind },
|
||||
{ CAPI_CONNECT_B3_CONF, capi_connect_b3_conf },
|
||||
{ CAPI_CONNECT_B3_IND, capi_connect_b3_ind },
|
||||
{ CAPI_CONNECT_B3_ACTIVE_IND, capi_connect_b3_active_ind },
|
||||
{ CAPI_DATA_B3_CONF, capi_data_b3_conf },
|
||||
{ CAPI_DATA_B3_IND, capi_data_b3_ind },
|
||||
{ CAPI_DISCONNECT_B3_IND, capi_disconnect_b3_ind },
|
||||
{ CAPI_DISCONNECT_CONF, capi_disconnect_conf },
|
||||
{ CAPI_DISCONNECT_IND, capi_disconnect_ind },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
// capi_ll_receive
|
||||
// CAPI link layer receive upcall. Called by a link layer
|
||||
// driver to dispatch incoming CAPI messages.
|
||||
*/
|
||||
|
||||
int
|
||||
capi_ll_receive(capi_softc_t *sc, struct mbuf *m)
|
||||
{
|
||||
u_int8_t *p = mtod(m, u_int8_t*);
|
||||
u_int16_t len, applid, msgid, cmd;
|
||||
|
||||
capimsg_getu16(p + 0, &len);
|
||||
capimsg_getu16(p + 2, &applid);
|
||||
capimsg_getu16(p + 4, &cmd);
|
||||
capimsg_getu16(p + 6, &msgid);
|
||||
|
||||
#if 0
|
||||
printf("capi%d: ll_receive hdr %04x %04x %04x %04x\n", sc->sc_unit,
|
||||
len, applid, cmd, msgid);
|
||||
#endif
|
||||
|
||||
if (applid == I4BCAPI_APPLID) {
|
||||
struct capi_cmdtab *e;
|
||||
for (e = i4b_capi_handlers; e->cmd && e->cmd != cmd; e++);
|
||||
if (e->cmd) (*e->handler)(sc, m);
|
||||
else printf("capi%d: unknown message %04x\n", sc->sc_unit, cmd);
|
||||
|
||||
} else {
|
||||
/* XXX we could handle arbitrary ApplIds here XXX */
|
||||
printf("capi%d: message %04x for unknown applid %d\n", sc->sc_unit,
|
||||
cmd, applid);
|
||||
}
|
||||
|
||||
if (m->m_next) {
|
||||
i4b_Bfreembuf(m->m_next);
|
||||
m->m_next = NULL;
|
||||
}
|
||||
i4b_Dfreembuf(m);
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif /* NI4BCAPI > 0*/
|
948
sys/i4b/capi/capi_msgs.c
Normal file
948
sys/i4b/capi/capi_msgs.c
Normal file
@ -0,0 +1,948 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_msgs.c The CAPI i4b message handlers.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "i4bcapi.h"
|
||||
#if NI4BCAPI > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <machine/i4b_debug.h>
|
||||
#include <machine/i4b_ioctl.h>
|
||||
#include <machine/i4b_cause.h>
|
||||
|
||||
#include <i4b/include/i4b_l3l4.h>
|
||||
#include <i4b/include/i4b_mbuf.h>
|
||||
#include <i4b/include/i4b_global.h>
|
||||
|
||||
#include <i4b/layer4/i4b_l4.h>
|
||||
|
||||
#include <i4b/capi/capi.h>
|
||||
#include <i4b/capi/capi_msgs.h>
|
||||
|
||||
/*
|
||||
// Administrative messages:
|
||||
// ------------------------
|
||||
*/
|
||||
|
||||
void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 18);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msgid = sc->sc_msgid++;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_LISTEN_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, 1); /* Controller */
|
||||
msg = capimsg_setu32(msg, 0); /* Info mask */
|
||||
msg = capimsg_setu32(msg, CIP);
|
||||
msg = capimsg_setu32(msg, 0);
|
||||
msg = capimsg_setu8(msg, 0);
|
||||
msg = capimsg_setu8(msg, 0);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t Info;
|
||||
|
||||
capimsg_getu16(msg + 12, &Info);
|
||||
|
||||
if (Info == 0) {
|
||||
/* We are now listening. */
|
||||
|
||||
sc->sc_state = C_UP;
|
||||
ctrl_desc[sc->ctrl_unit].dl_est = DL_UP;
|
||||
|
||||
i4b_l4_l12stat(sc->ctrl_unit, 1, 1);
|
||||
i4b_l4_l12stat(sc->ctrl_unit, 2, 1);
|
||||
|
||||
} else {
|
||||
/* XXX sc->sc_state = C_DOWN ? XXX */
|
||||
printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
|
||||
/* i4b_l4_info_ind() */
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_INFO_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 5);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_ALERT_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
msg = capimsg_setu8(msg, 0);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_alert_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t Info;
|
||||
|
||||
msg = capimsg_getu16(msg + 12, &Info);
|
||||
|
||||
if (Info) {
|
||||
printf("capi%d: can't alert, info=%04x\n", sc->sc_unit, Info);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Outgoing call setup:
|
||||
// --------------------
|
||||
//
|
||||
// CAPI_CONNECT_REQ -->
|
||||
// <-- CAPI_CONNECT_CONF
|
||||
// (notify Layer 4)
|
||||
// <-- CAPI_CONNECT_ACTIVE_IND
|
||||
// CAPI_CONNECT_ACTIVE_RESP -->
|
||||
// CAPI_CONNECT_B3_REQ -->
|
||||
// <-- CAPI_CONNECT_B3_CONF
|
||||
// <-- CAPI_CONNECT_B3_ACTIVE_IND
|
||||
// CAPI_CONNECT_B3_ACTIVE_RESP -->
|
||||
// (notify Layer 4)
|
||||
*/
|
||||
|
||||
void capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct mbuf *m;
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
int slen = strlen(cd->src_telno);
|
||||
int dlen = strlen(cd->dst_telno);
|
||||
|
||||
m = i4b_Dgetmbuf(8 + 18 + slen + dlen);
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
cd->crflag = CRF_ORIG;
|
||||
|
||||
sc->sc_bchan[cd->channelid].cdid = cd->cdid;
|
||||
sc->sc_bchan[cd->channelid].bprot = cd->bprot;
|
||||
sc->sc_bchan[cd->channelid].state = B_CONNECT_CONF;
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_RSVD;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, 1); /* Controller */
|
||||
|
||||
switch (cd->bprot) {
|
||||
case BPROT_NONE:
|
||||
msg = capimsg_setu16(msg, 0x0010); /* Telephony */
|
||||
break;
|
||||
|
||||
case BPROT_RHDLC:
|
||||
msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
|
||||
break;
|
||||
|
||||
default:
|
||||
msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
|
||||
}
|
||||
|
||||
msg = capimsg_setu8(msg, 1 + dlen);
|
||||
msg = capimsg_setu8(msg, 0x80);
|
||||
strncpy(msg, cd->dst_telno, dlen);
|
||||
|
||||
msg = capimsg_setu8(msg + dlen, 2 + slen);
|
||||
msg = capimsg_setu8(msg, 0x00);
|
||||
msg = capimsg_setu8(msg, 0x80); /* Presentation and screening indicator */
|
||||
strncpy(msg, cd->src_telno, slen);
|
||||
|
||||
msg = capimsg_setu8(msg + slen, 0); /* Called & */
|
||||
msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
|
||||
|
||||
msg = capimsg_setu8(msg, 15); /* B protocol */
|
||||
if (cd->bprot == BPROT_NONE)
|
||||
msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
|
||||
else
|
||||
msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
|
||||
msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
|
||||
msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
|
||||
msg = capimsg_setu8(msg, 0); /* B1 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B2 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B3 parameters */
|
||||
|
||||
msg = capimsg_setu8(msg, 0); /* Bearer Capability */
|
||||
msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
|
||||
msg = capimsg_setu8(msg, 0); /* High Layer Compatibility */
|
||||
msg = capimsg_setu8(msg, 0); /* Additional Info */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
u_int16_t Info;
|
||||
int bch;
|
||||
|
||||
msg = capimsg_getu16(msg + 6, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
msg = capimsg_getu16(msg, &Info);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_CONF) &&
|
||||
(sc->sc_bchan[bch].msgid == msgid))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for connect_conf PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Info == 0) {
|
||||
sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
|
||||
sc->sc_bchan[bch].ncci = PLCI;
|
||||
|
||||
i4b_l4_proceeding_ind(cd);
|
||||
|
||||
} else {
|
||||
SET_CAUSE_TV(cd->cause_out, CAUSET_I4B, CAUSE_I4B_L1ERROR);
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
|
||||
sc->sc_bchan[bch].state = B_FREE;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
|
||||
|
||||
printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_ACTIVE_IND) &&
|
||||
(sc->sc_bchan[bch].ncci == PLCI))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for active_resp, PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_ACTIVE_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
|
||||
if (cd->crflag == CRF_ORIG) {
|
||||
capi_connect_b3_req(sc, cd);
|
||||
|
||||
} else {
|
||||
sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
|
||||
}
|
||||
}
|
||||
|
||||
void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 5);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_bchan[cd->channelid].state = B_CONNECT_B3_CONF;
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_B3_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
msg = capimsg_setu8(msg, 0); /* NCPI */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t msgid;
|
||||
u_int32_t NCCI;
|
||||
u_int16_t Info;
|
||||
int bch;
|
||||
|
||||
msg = capimsg_getu16(msg + 6, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
msg = capimsg_getu16(msg, &Info);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_B3_CONF) &&
|
||||
(sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for connect_b3_conf NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Info == 0) {
|
||||
sc->sc_bchan[bch].ncci = NCCI;
|
||||
sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
|
||||
|
||||
} else {
|
||||
SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_RSVD;
|
||||
|
||||
printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
|
||||
|
||||
capi_disconnect_req(sc, cd);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_B3_ACTIVE_IND) &&
|
||||
(sc->sc_bchan[bch].ncci == NCCI))
|
||||
break;
|
||||
|
||||
if ((bch == sc->sc_nbch) ||
|
||||
(cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
|
||||
printf("capi%d: can't find channel for b3_active_resp NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_B3_ACTIVE_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
|
||||
sc->sc_bchan[bch].state = B_CONNECTED;
|
||||
i4b_l4_connect_active_ind(cd);
|
||||
}
|
||||
|
||||
/*
|
||||
// Incoming call setup:
|
||||
// --------------------
|
||||
//
|
||||
// <-- CAPI_CONNECT_IND
|
||||
// (consult Layer 4)
|
||||
// CAPI_CONNECT_RESP -->
|
||||
// <-- CAPI_CONNECT_ACTIVE_IND
|
||||
// CAPI_CONNECT_ACTIVE_RESP -->
|
||||
// <-- CAPI_CONNECT_B3_IND
|
||||
// CAPI_CONNECT_B3_RESP -->
|
||||
// <-- CAPI_CONNECT_B3_ACTIVE_IND
|
||||
// CAPI_CONNECT_B3_ACTIVE_RESP -->
|
||||
// (notify Layer 4)
|
||||
*/
|
||||
|
||||
void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
u_int16_t CIP;
|
||||
u_int8_t x, y, z;
|
||||
int bch;
|
||||
|
||||
if ((cd = reserve_cd()) == NULL) {
|
||||
printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
cd->controller = sc->ctrl_unit;
|
||||
cd->channelexcl = FALSE;
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if (sc->sc_bchan[bch].state == B_FREE) break;
|
||||
sc->sc_bchan[bch].state = B_CONNECT_IND;
|
||||
cd->channelid = bch; /* XXX CHAN_ANY XXX */
|
||||
|
||||
cd->crflag = CRF_DEST;
|
||||
cd->cr = get_rand_cr(sc->sc_unit);
|
||||
cd->scr_ind = SCR_NONE;
|
||||
cd->prs_ind = PRS_NONE;
|
||||
cd->bprot = BPROT_NONE;
|
||||
cd->ilt = NULL;
|
||||
cd->dlt = NULL;
|
||||
cd->display[0] = '\0';
|
||||
cd->datetime[0] = '\0';
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
msg = capimsg_getu16(msg, &CIP);
|
||||
|
||||
cd->event = (int) msgid; /* XXX overload */
|
||||
cd->Q931state = (int) PLCI; /* XXX overload */
|
||||
|
||||
switch (CIP) {
|
||||
case 0x0010:
|
||||
case 0x0001: cd->bprot = BPROT_NONE; break;
|
||||
case 0x0002: cd->bprot = BPROT_RHDLC; break;
|
||||
default:
|
||||
NDBGL4(L4_CAPIDBG, "capi%d: unknown CIP = %d", sc->sc_unit, CIP);
|
||||
cd->bprot = BPROT_NONE;
|
||||
}
|
||||
|
||||
msg = capimsg_getu8(msg, &x); /* Called party struct len */
|
||||
if (x) {
|
||||
msg = capimsg_getu8(msg, &y); /* Numbering plan */
|
||||
z = x - 1;
|
||||
if (z >= TELNO_MAX) z = (TELNO_MAX-1);
|
||||
strncpy(cd->dst_telno, msg, z);
|
||||
msg += x;
|
||||
x = z;
|
||||
}
|
||||
cd->dst_telno[x] = '\0';
|
||||
|
||||
msg = capimsg_getu8(msg, &x); /* Calling party struct len */
|
||||
if (x) {
|
||||
msg = capimsg_getu8(msg, &y); /* Numbering plan */
|
||||
msg = capimsg_getu8(msg, &y); /* Screening/Presentation */
|
||||
if ((y & 0x80) == 0) { /* screening used */
|
||||
cd->scr_ind = (y & 3) + SCR_USR_NOSC;
|
||||
cd->prs_ind = ((y >> 5) & 3) + PRS_ALLOWED;
|
||||
}
|
||||
z = x - 2;
|
||||
if (z >= TELNO_MAX) z = (TELNO_MAX-1);
|
||||
strncpy(cd->src_telno, msg, z);
|
||||
msg += x;
|
||||
x = z;
|
||||
}
|
||||
cd->src_telno[x] = '\0';
|
||||
|
||||
i4b_l4_connect_ind(cd);
|
||||
}
|
||||
|
||||
void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct mbuf *m;
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
int dlen = strlen(cd->dst_telno);
|
||||
|
||||
m = i4b_Dgetmbuf(8 + 11 + dlen);
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msgid = (u_int16_t) cd->event;
|
||||
PLCI = (u_int32_t) cd->Q931state;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
switch (cd->response) {
|
||||
case SETUP_RESP_ACCEPT:
|
||||
sc->sc_bchan[cd->channelid].cdid = cd->cdid;
|
||||
sc->sc_bchan[cd->channelid].ncci = PLCI;
|
||||
sc->sc_bchan[cd->channelid].state = B_CONNECT_ACTIVE_IND;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_USED;
|
||||
msg = capimsg_setu16(msg, 0); /* Accept the call */
|
||||
break;
|
||||
|
||||
case SETUP_RESP_REJECT:
|
||||
sc->sc_bchan[cd->channelid].state = B_FREE;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
msg = capimsg_setu16(msg, 2); /* Reject, normal call clearing */
|
||||
break;
|
||||
|
||||
case SETUP_RESP_DNTCRE:
|
||||
sc->sc_bchan[cd->channelid].state = B_FREE;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
msg = capimsg_setu16(msg, 1); /* Ignore */
|
||||
break;
|
||||
|
||||
default:
|
||||
sc->sc_bchan[cd->channelid].state = B_FREE;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_CALLREJ));
|
||||
}
|
||||
|
||||
msg = capimsg_setu8(msg, 15); /* B protocol */
|
||||
if (cd->bprot == BPROT_NONE)
|
||||
msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
|
||||
else
|
||||
msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
|
||||
msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
|
||||
msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
|
||||
msg = capimsg_setu8(msg, 0); /* B1 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B2 parameters */
|
||||
msg = capimsg_setu8(msg, 0); /* B3 parameters */
|
||||
|
||||
msg = capimsg_setu8(msg, 1 + dlen);
|
||||
msg = capimsg_setu8(msg, 0x80); /* Numbering plan */
|
||||
strncpy(msg, cd->dst_telno, dlen);
|
||||
msg = capimsg_setu8(msg + dlen, 0); /* Connected subaddress */
|
||||
msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
|
||||
msg = capimsg_setu8(msg, 0); /* Additional Info */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 7);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECT_B3_IND) &&
|
||||
(sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
|
||||
break;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_CONNECT_B3_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
printf("capi%d: can't get cd for connect_b3_resp NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
msg = capimsg_setu16(msg, 8); /* Reject, destination OOO */
|
||||
|
||||
} else {
|
||||
sc->sc_bchan[bch].ncci = NCCI;
|
||||
sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
|
||||
msg = capimsg_setu16(msg, 0); /* Accept */
|
||||
}
|
||||
|
||||
msg = capimsg_setu8(msg, 0); /* NCPI */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
/*
|
||||
// Data transfer:
|
||||
// --------------
|
||||
*/
|
||||
|
||||
void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 14);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
|
||||
sc->sc_bchan[chan].busy = 1;
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_DATA_B3_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, sc->sc_bchan[chan].ncci);
|
||||
msg = capimsg_setu32(msg, (u_int32_t) m_b3->m_data); /* Pointer */
|
||||
msg = capimsg_setu16(msg, m_b3->m_len);
|
||||
msg = capimsg_setu16(msg, chan);
|
||||
msg = capimsg_setu16(msg, 0); /* Flags */
|
||||
|
||||
m->m_next = m_b3;
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int32_t NCCI;
|
||||
u_int16_t handle;
|
||||
u_int16_t Info;
|
||||
|
||||
msg = capimsg_getu32(msg + 8, &NCCI);
|
||||
msg = capimsg_getu16(msg, &handle);
|
||||
msg = capimsg_getu16(msg, &Info);
|
||||
|
||||
if (Info == 0) {
|
||||
sc->sc_bchan[handle].busy = 0;
|
||||
capi_start_tx(sc, handle);
|
||||
|
||||
} else {
|
||||
printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
|
||||
sc->sc_unit, NCCI, handle, Info);
|
||||
}
|
||||
}
|
||||
|
||||
void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 14);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
u_int16_t handle;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
msg = capimsg_getu16(msg + 6, &handle);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_CONNECTED) &&
|
||||
(sc->sc_bchan[bch].ncci == NCCI))
|
||||
break;
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
printf("capi%d: can't find channel for data_b3_ind NCCI %x\n",
|
||||
sc->sc_unit, NCCI);
|
||||
|
||||
} else {
|
||||
if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
|
||||
/* HDLC drivers use rx_mbuf */
|
||||
|
||||
sc->sc_bchan[bch].in_mbuf = m_in->m_next;
|
||||
sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
|
||||
m_in->m_next = NULL; /* driver frees */
|
||||
|
||||
(*sc->sc_bchan[bch].capi_drvr_linktab->bch_rx_data_ready)(
|
||||
sc->sc_bchan[bch].capi_drvr_linktab->unit);
|
||||
|
||||
} else {
|
||||
/* Telephony drivers use rx_queue */
|
||||
|
||||
if (!_IF_QFULL(&sc->sc_bchan[bch].rx_queue)) {
|
||||
_IF_ENQUEUE(&sc->sc_bchan[bch].rx_queue, m_in->m_next);
|
||||
sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
|
||||
m_in->m_next = NULL; /* driver frees */
|
||||
}
|
||||
|
||||
(*sc->sc_bchan[bch].capi_drvr_linktab->bch_rx_data_ready)(
|
||||
sc->sc_bchan[bch].capi_drvr_linktab->unit);
|
||||
}
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_DATA_B3_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
msg = capimsg_setu16(msg, handle);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
/*
|
||||
// Connection teardown:
|
||||
// --------------------
|
||||
*/
|
||||
|
||||
void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 5);
|
||||
u_int8_t *msg;
|
||||
u_int16_t msgid;
|
||||
u_int32_t PLCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_bchan[cd->channelid].state = B_DISCONNECT_CONF;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_RSVD;
|
||||
msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
|
||||
PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, I4BCAPI_APPLID);
|
||||
msg = capimsg_setu16(msg, CAPI_DISCONNECT_REQ);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
msg = capimsg_setu8(msg, 0); /* Additional Info */
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int32_t PLCI;
|
||||
int bch;
|
||||
|
||||
msg = capimsg_getu32(msg + 8, &PLCI);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state == B_DISCONNECT_CONF) &&
|
||||
((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
|
||||
break;
|
||||
|
||||
if (bch == sc->sc_nbch) {
|
||||
printf("capi%d: can't find channel for disconnect_conf PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
return;
|
||||
}
|
||||
|
||||
cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
|
||||
if (!cd) {
|
||||
printf("capi%d: can't find cd for disconnect_conf PLCI %x\n",
|
||||
sc->sc_unit, PLCI);
|
||||
} else {
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
}
|
||||
|
||||
sc->sc_bchan[bch].state = B_FREE;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
|
||||
}
|
||||
|
||||
void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t NCCI;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &NCCI);
|
||||
|
||||
/* XXX update bchan state? XXX */
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_DISCONNECT_B3_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, NCCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(8 + 4);
|
||||
u_int8_t *msg = mtod(m_in, u_int8_t*);
|
||||
call_desc_t *cd;
|
||||
u_int16_t applid, msgid;
|
||||
u_int32_t PLCI;
|
||||
u_int16_t Reason;
|
||||
int bch;
|
||||
|
||||
if (!m) {
|
||||
printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
|
||||
return;
|
||||
}
|
||||
|
||||
msg = capimsg_getu16(msg + 2, &applid);
|
||||
msg = capimsg_getu16(msg + 2, &msgid);
|
||||
msg = capimsg_getu32(msg, &PLCI);
|
||||
msg = capimsg_getu16(msg, &Reason);
|
||||
|
||||
for (bch = 0; bch < sc->sc_nbch; bch++)
|
||||
if ((sc->sc_bchan[bch].state != B_FREE) &&
|
||||
((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
|
||||
break;
|
||||
|
||||
if (bch < sc->sc_nbch) {
|
||||
/* We may not have a bchan assigned if call was ignored. */
|
||||
|
||||
cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
|
||||
sc->sc_bchan[bch].state = B_DISCONNECT_IND;
|
||||
} else cd = NULL;
|
||||
|
||||
if (cd) {
|
||||
if ((Reason & 0xff00) == 0x3400) {
|
||||
SET_CAUSE_TV(cd->cause_in, CAUSET_Q850, (Reason & 0x7f));
|
||||
} else {
|
||||
SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_NORMAL);
|
||||
}
|
||||
|
||||
i4b_l4_disconnect_ind(cd);
|
||||
freecd_by_cd(cd);
|
||||
|
||||
sc->sc_bchan[bch].state = B_FREE;
|
||||
ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
|
||||
}
|
||||
|
||||
msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
|
||||
msg = capimsg_setu16(msg, applid);
|
||||
msg = capimsg_setu16(msg, CAPI_DISCONNECT_RESP);
|
||||
msg = capimsg_setu16(msg, msgid);
|
||||
|
||||
msg = capimsg_setu32(msg, PLCI);
|
||||
|
||||
sc->send(sc, m);
|
||||
}
|
||||
|
||||
#endif /* NI4BCAPI > 0 */
|
380
sys/i4b/capi/capi_msgs.h
Normal file
380
sys/i4b/capi/capi_msgs.h
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/capi_msgs.h The CAPI i4b message and handler declarations.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _I4B_CAPI_MSGS_H_
|
||||
#define _I4B_CAPI_MSGS_H_
|
||||
|
||||
/* CAPI commands */
|
||||
|
||||
#define CAPI_ALERT 0x01
|
||||
#define CAPI_CONNECT 0x02
|
||||
#define CAPI_CONNECT_ACTIVE 0x03
|
||||
#define CAPI_CONNECT_B3 0x82
|
||||
#define CAPI_CONNECT_B3_ACTIVE 0x83
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE 0x88
|
||||
#define CAPI_DATA_B3 0x86
|
||||
#define CAPI_DISCONNECT_B3 0x84
|
||||
#define CAPI_DISCONNECT 0x04
|
||||
#define CAPI_FACILITY 0x80
|
||||
#define CAPI_INFO 0x08
|
||||
#define CAPI_LISTEN 0x05
|
||||
#define CAPI_MANUFACTURER 0xff
|
||||
#define CAPI_RESET_B3 0x87
|
||||
#define CAPI_SELECT_B_PROTOCOL 0x41
|
||||
|
||||
/* CAPI subcommands */
|
||||
|
||||
#define CAPI_REQ 0x80
|
||||
#define CAPI_CONF 0x81
|
||||
#define CAPI_IND 0x82
|
||||
#define CAPI_RESP 0x83
|
||||
|
||||
/* CAPI combined commands */
|
||||
|
||||
#define CAPICMD(cmd,subcmd) (((subcmd)<<8)|(cmd))
|
||||
|
||||
#define CAPI_DISCONNECT_REQ CAPICMD(CAPI_DISCONNECT,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_CONF CAPICMD(CAPI_DISCONNECT,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_IND CAPICMD(CAPI_DISCONNECT,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_RESP CAPICMD(CAPI_DISCONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_ALERT_REQ CAPICMD(CAPI_ALERT,CAPI_REQ)
|
||||
#define CAPI_ALERT_CONF CAPICMD(CAPI_ALERT,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_REQ CAPICMD(CAPI_CONNECT,CAPI_REQ)
|
||||
#define CAPI_CONNECT_CONF CAPICMD(CAPI_CONNECT,CAPI_CONF)
|
||||
#define CAPI_CONNECT_IND CAPICMD(CAPI_CONNECT,CAPI_IND)
|
||||
#define CAPI_CONNECT_RESP CAPICMD(CAPI_CONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_ACTIVE_REQ CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_ACTIVE_CONF CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_ACTIVE_IND CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_ACTIVE_RESP CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_SELECT_B_PROTOCOL_REQ CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_REQ)
|
||||
#define CAPI_SELECT_B_PROTOCOL_CONF CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_B3_REQ CAPICMD(CAPI_CONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_CONF CAPICMD(CAPI_CONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_IND CAPICMD(CAPI_CONNECT_B3,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_RESP CAPICMD(CAPI_CONNECT_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_B3_ACTIVE_REQ CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_CONF CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_DATA_B3_REQ CAPICMD(CAPI_DATA_B3,CAPI_REQ)
|
||||
#define CAPI_DATA_B3_CONF CAPICMD(CAPI_DATA_B3,CAPI_CONF)
|
||||
#define CAPI_DATA_B3_IND CAPICMD(CAPI_DATA_B3,CAPI_IND)
|
||||
#define CAPI_DATA_B3_RESP CAPICMD(CAPI_DATA_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_DISCONNECT_B3_REQ CAPICMD(CAPI_DISCONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_B3_CONF CAPICMD(CAPI_DISCONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_B3_IND CAPICMD(CAPI_DISCONNECT_B3,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_B3_RESP CAPICMD(CAPI_DISCONNECT_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_RESET_B3_REQ CAPICMD(CAPI_RESET_B3,CAPI_REQ)
|
||||
#define CAPI_RESET_B3_CONF CAPICMD(CAPI_RESET_B3,CAPI_CONF)
|
||||
#define CAPI_RESET_B3_IND CAPICMD(CAPI_RESET_B3,CAPI_IND)
|
||||
#define CAPI_RESET_B3_RESP CAPICMD(CAPI_RESET_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_LISTEN_REQ CAPICMD(CAPI_LISTEN,CAPI_REQ)
|
||||
#define CAPI_LISTEN_CONF CAPICMD(CAPI_LISTEN,CAPI_CONF)
|
||||
|
||||
#define CAPI_MANUFACTURER_REQ CAPICMD(CAPI_MANUFACTURER,CAPI_REQ)
|
||||
#define CAPI_MANUFACTURER_CONF CAPICMD(CAPI_MANUFACTURER,CAPI_CONF)
|
||||
#define CAPI_MANUFACTURER_IND CAPICMD(CAPI_MANUFACTURER,CAPI_IND)
|
||||
#define CAPI_MANUFACTURER_RESP CAPICMD(CAPI_MANUFACTURER,CAPI_RESP)
|
||||
|
||||
#define CAPI_FACILITY_REQ CAPICMD(CAPI_FACILITY,CAPI_REQ)
|
||||
#define CAPI_FACILITY_CONF CAPICMD(CAPI_FACILITY,CAPI_CONF)
|
||||
#define CAPI_FACILITY_IND CAPICMD(CAPI_FACILITY,CAPI_IND)
|
||||
#define CAPI_FACILITY_RESP CAPICMD(CAPI_FACILITY,CAPI_RESP)
|
||||
|
||||
#define CAPI_INFO_REQ CAPICMD(CAPI_INFO,CAPI_REQ)
|
||||
#define CAPI_INFO_CONF CAPICMD(CAPI_INFO,CAPI_CONF)
|
||||
#define CAPI_INFO_IND CAPICMD(CAPI_INFO,CAPI_IND)
|
||||
#define CAPI_INFO_RESP CAPICMD(CAPI_INFO,CAPI_RESP)
|
||||
|
||||
/* CAPI message access helpers */
|
||||
|
||||
/*
|
||||
* CAPI message header:
|
||||
* word Length
|
||||
* word ApplId
|
||||
* byte Command
|
||||
* byte Subcommand
|
||||
* word MsgId
|
||||
*
|
||||
* Note that in the following, Controller/PLCI/NCCI is coded as follows:
|
||||
* bits 0..6 = controller, bit 7 = ext/int, bits 8..15 = PLCI, and
|
||||
* bits 16..31 = NCCI value.
|
||||
*
|
||||
* ALERT_REQ, 01 80:
|
||||
* dword PLCI
|
||||
* struct Additional Info
|
||||
*
|
||||
* ALERT_CONF, 01 81:
|
||||
* dword PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* CONNECT_REQ, 02 80:
|
||||
* dword controller
|
||||
* word CIP
|
||||
* struct Called party number
|
||||
* struct Calling party number
|
||||
* struct Called party subaddress
|
||||
* struct Calling party subaddress
|
||||
* struct Bearer Capability
|
||||
* struct Low Layer Compatibility
|
||||
* struct High Layer Compatibility
|
||||
* struct Additional Info
|
||||
*
|
||||
* CONNECT_CONF, 02 81:
|
||||
* dword PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* CONNECT_IND, 02 82:
|
||||
* dword PLCI
|
||||
* word CIP
|
||||
* struct Called party number
|
||||
* struct Calling party number
|
||||
* struct Called party subaddress
|
||||
* struct Calling party subaddress
|
||||
* struct Bearer Capability
|
||||
* struct Low Layer Compatibility
|
||||
* struct High Layer Compatibility
|
||||
* struct Additional Info
|
||||
* struct Second Calling party number
|
||||
*
|
||||
* CONNECT_RESP, 02 83:
|
||||
* dword PLCI
|
||||
* word Reject (0 = accept, 1 = ignore, 2 = reject/normal clearing)
|
||||
* struct B protocol
|
||||
* struct Connected number
|
||||
* struct Connected subaddress
|
||||
* struct Low Layer Compatibility
|
||||
* struct Additional Info
|
||||
*
|
||||
* CONNECT_ACTIVE_IND, 03 82:
|
||||
* dword PLCI
|
||||
* struct Connected number
|
||||
* struct Connected subaddress
|
||||
* struct Low Layer Compatibility
|
||||
*
|
||||
* CONNECT_ACTIVE_RESP, 03 83:
|
||||
* dword PLCI
|
||||
*
|
||||
* CONNECT_B3_REQ, 82 80:
|
||||
* dword PLCI
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_CONF, 82 81:
|
||||
* dword NCCI
|
||||
* word Info (0 = connected, other = cause)
|
||||
*
|
||||
* CONNECT_B3_IND, 82 82:
|
||||
* dword NCCI
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_RESP, 82 83:
|
||||
* dword NCCI
|
||||
* word Reject (0 = accept, 2 = reject/normal clearing)
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_ACTIVE_IND, 83 82:
|
||||
* dword NCCI
|
||||
* struct NCPI
|
||||
*
|
||||
* CONNECT_B3_ACTIVE_RESP, 83 83:
|
||||
* dword NCCI
|
||||
*
|
||||
* DATA_B3_REQ, 86 80:
|
||||
* dword NCCI
|
||||
* dword Data pointer
|
||||
* word Data length
|
||||
* word Data handle (packet id)
|
||||
* word Flags (02 = more)
|
||||
*
|
||||
* DATA_B3_CONF, 86 81:
|
||||
* dword NCCI
|
||||
* word Data handle (packet id)
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* DATA_B3_IND, 86 82:
|
||||
* dword NCCI
|
||||
* dword Data pointer
|
||||
* word Data length
|
||||
* word Data handle (packet id)
|
||||
* word Flags (02 = more)
|
||||
*
|
||||
* DATA_B3_RESP, 86 83:
|
||||
* dword NCCI
|
||||
* word Data handle (packet id)
|
||||
*
|
||||
* DISCONNECT_B3_REQ, 84 80:
|
||||
* dword NCCI
|
||||
* struct NCPI
|
||||
*
|
||||
* DISCONNECT_B3_CONF, 84 81:
|
||||
* dword NCCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* DISCONNECT_B3_IND, 84 82:
|
||||
* dword NCCI
|
||||
* word Reason
|
||||
* struct NCPI
|
||||
*
|
||||
* DISCONNECT_B3_RESP, 84 83:
|
||||
* dword NCCI
|
||||
*
|
||||
* DISCONNECT_REQ, 04 80:
|
||||
* dword PLCI
|
||||
* struct Additional Info
|
||||
*
|
||||
* DISCONNECT_CONF, 04 81:
|
||||
* dword PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* DISCONNECT_IND, 04 82:
|
||||
* dword PLCI
|
||||
* word Reason
|
||||
*
|
||||
* DISCONNECT_RESP, 04 83:
|
||||
* dword PLCI
|
||||
*
|
||||
* LISTEN_REQ, 05 80:
|
||||
* dword Controller
|
||||
* dword Info mask (bits 0..9 used)
|
||||
* dword CIP Mask (bit 0 = any match)
|
||||
* dword CIP Mask 2 (bit 0 = any match)
|
||||
* struct Calling party number
|
||||
* struct Calling party subaddress
|
||||
*
|
||||
* LISTEN_CONF, 05 81:
|
||||
* dword Controller
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* INFO_REQ, 08 80:
|
||||
* dword Controller/PLCI
|
||||
* struct Called party number
|
||||
* struct Additional Info
|
||||
*
|
||||
* INFO_CONF, 08 81:
|
||||
* dword Controller/PLCI
|
||||
* word Info (0 = OK, other = cause)
|
||||
*
|
||||
* INFO_IND, 08 82:
|
||||
* dword Controller/PLCI
|
||||
* word Info number
|
||||
* struct Info element
|
||||
*
|
||||
* INFO_RESP, 08 83:
|
||||
* dword Controller/PLCI
|
||||
*/
|
||||
|
||||
#define CAPIMSG_LEN(msg) (msg[0]|(msg[1]<<8))
|
||||
#define CAPIMSG_DATALEN(msg) (msg[16]|(msg[17]<<8))
|
||||
|
||||
static __inline u_int8_t* capimsg_getu8(u_int8_t *msg, u_int8_t *val)
|
||||
{
|
||||
*val = *msg;
|
||||
return (msg + 1);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_getu16(u_int8_t *msg, u_int16_t *val)
|
||||
{
|
||||
*val = (msg[0]|(msg[1]<<8));
|
||||
return (msg + 2);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_getu32(u_int8_t *msg, u_int32_t *val)
|
||||
{
|
||||
*val = (msg[0]|(msg[1]<<8)|(msg[2]<<16)|(msg[3]<<24));
|
||||
return (msg + 4);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_setu8(u_int8_t *msg, u_int8_t val)
|
||||
{
|
||||
msg[0] = val;
|
||||
return (msg + 1);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_setu16(u_int8_t *msg, u_int16_t val)
|
||||
{
|
||||
msg[0] = (val & 0xff);
|
||||
msg[1] = (val >> 8) & 0xff;
|
||||
return (msg + 2);
|
||||
}
|
||||
|
||||
static __inline u_int8_t* capimsg_setu32(u_int8_t *msg, u_int32_t val)
|
||||
{
|
||||
msg[0] = (val & 0xff);
|
||||
msg[1] = (val >> 8) & 0xff;
|
||||
msg[2] = (val >> 16) & 0xff;
|
||||
msg[3] = (val >> 24) & 0xff;
|
||||
return (msg + 4);
|
||||
}
|
||||
|
||||
/*
|
||||
// CAPI message handlers called by higher layers
|
||||
*/
|
||||
|
||||
extern void capi_listen_req(capi_softc_t *sc, u_int32_t CIP);
|
||||
extern void capi_alert_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_connect_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd);
|
||||
extern void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m);
|
||||
extern void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd);
|
||||
|
||||
/*
|
||||
// CAPI message handlers called by the receive routine
|
||||
*/
|
||||
|
||||
extern void capi_listen_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_info_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_alert_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
extern void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m);
|
||||
|
||||
#endif /* _I4B_CAPI_MSGS_H_ */
|
586
sys/i4b/capi/iavc/iavc.h
Normal file
586
sys/i4b/capi/iavc/iavc.h
Normal file
@ -0,0 +1,586 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/iavc/iavc.h The AVM ISDN controllers' common declarations.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _CAPI_IAVC_H_
|
||||
#define _CAPI_IAVC_H_
|
||||
|
||||
/* max 4 units supported per machine */
|
||||
|
||||
#define IAVC_MAXUNIT 4
|
||||
|
||||
/*
|
||||
// iavc_softc_t
|
||||
// The software context of one AVM T1 controller.
|
||||
*/
|
||||
|
||||
#define IAVC_IO_BASES 1
|
||||
|
||||
typedef struct i4b_info {
|
||||
struct resource * io_base[IAVC_IO_BASES];
|
||||
int io_rid [IAVC_IO_BASES];
|
||||
struct resource * irq;
|
||||
int irq_rid;
|
||||
struct resource * mem;
|
||||
int mem_rid;
|
||||
} i4b_info_t;
|
||||
|
||||
typedef struct iavc_softc {
|
||||
capi_softc_t sc_capi;
|
||||
int sc_unit;
|
||||
int sc_cardtyp;
|
||||
|
||||
u_int32_t sc_membase;
|
||||
bus_space_handle_t sc_mem_bh;
|
||||
bus_space_tag_t sc_mem_bt;
|
||||
u_int32_t sc_iobase;
|
||||
bus_space_handle_t sc_io_bh;
|
||||
bus_space_tag_t sc_io_bt;
|
||||
|
||||
int sc_state;
|
||||
#define IAVC_DOWN 0
|
||||
#define IAVC_POLL 1
|
||||
#define IAVC_INIT 2
|
||||
#define IAVC_UP 3
|
||||
int sc_blocked;
|
||||
int sc_dma;
|
||||
int sc_t1;
|
||||
int sc_intr;
|
||||
|
||||
u_int32_t sc_csr;
|
||||
|
||||
char sc_sendbuf[128+2048];
|
||||
char sc_recvbuf[128+2048];
|
||||
int sc_recvlen;
|
||||
|
||||
struct ifqueue sc_txq;
|
||||
|
||||
i4b_info_t sc_resources;
|
||||
} iavc_softc_t;
|
||||
|
||||
extern iavc_softc_t iavc_sc[];
|
||||
|
||||
#define iavc_find_sc(unit) (&iavc_sc[(unit)])
|
||||
|
||||
/*
|
||||
// {b1,b1dma,t1}_{detect,reset}
|
||||
// Routines to detect and manage the specific type of card.
|
||||
*/
|
||||
|
||||
extern int b1_detect(iavc_softc_t *sc);
|
||||
extern void b1_disable_irq(iavc_softc_t *sc);
|
||||
extern void b1_reset(iavc_softc_t *sc);
|
||||
|
||||
extern int b1dma_detect(iavc_softc_t *sc);
|
||||
extern void b1dma_reset(iavc_softc_t *sc);
|
||||
|
||||
extern int t1_detect(iavc_softc_t *sc);
|
||||
extern void t1_disable_irq(iavc_softc_t *sc);
|
||||
extern void t1_reset(iavc_softc_t *sc);
|
||||
|
||||
/*
|
||||
// AMCC_{READ,WRITE}
|
||||
// Routines to access the memory mapped registers of the
|
||||
// S5933 DMA controller.
|
||||
*/
|
||||
|
||||
static __inline u_int32_t AMCC_READ(iavc_softc_t *sc, int off)
|
||||
{
|
||||
return bus_space_read_4(sc->sc_mem_bt, sc->sc_mem_bh, off);
|
||||
}
|
||||
|
||||
static __inline void AMCC_WRITE(iavc_softc_t *sc, int off, u_int32_t value)
|
||||
{
|
||||
bus_space_write_4(sc->sc_mem_bt, sc->sc_mem_bh, off, value);
|
||||
}
|
||||
|
||||
/*
|
||||
// amcc_{put,get}_{byte,word}
|
||||
// Routines to access the DMA buffers byte- or wordwise.
|
||||
*/
|
||||
|
||||
static __inline u_int8_t* amcc_put_byte(u_int8_t *buf, u_int8_t value)
|
||||
{
|
||||
*buf++ = value;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static __inline u_int8_t* amcc_get_byte(u_int8_t *buf, u_int8_t *value)
|
||||
{
|
||||
*value = *buf++;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static __inline u_int8_t* amcc_put_word(u_int8_t *buf, u_int32_t value)
|
||||
{
|
||||
*buf++ = (value & 0xff);
|
||||
*buf++ = (value >> 8) & 0xff;
|
||||
*buf++ = (value >> 16) & 0xff;
|
||||
*buf++ = (value >> 24) & 0xff;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static __inline u_int8_t* amcc_get_word(u_int8_t *buf, u_int32_t *value)
|
||||
{
|
||||
*value = *buf++;
|
||||
*value |= (*buf++ << 8);
|
||||
*value |= (*buf++ << 16);
|
||||
*value |= (*buf++ << 24);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
// Controller LLI message numbers.
|
||||
*/
|
||||
|
||||
#define SEND_POLL 0x72
|
||||
#define SEND_INIT 0x11
|
||||
#define SEND_REGISTER 0x12
|
||||
#define SEND_DATA_B3_REQ 0x13
|
||||
#define SEND_RELEASE 0x14
|
||||
#define SEND_MESSAGE 0x15
|
||||
#define SEND_CONFIG 0x71
|
||||
#define SEND_POLLACK 0x73
|
||||
|
||||
#define RECEIVE_POLL 0x32
|
||||
#define RECEIVE_INIT 0x27
|
||||
#define RECEIVE_MESSAGE 0x21
|
||||
#define RECEIVE_DATA_B3_IND 0x22
|
||||
#define RECEIVE_START 0x23
|
||||
#define RECEIVE_STOP 0x24
|
||||
#define RECEIVE_NEW_NCCI 0x25
|
||||
#define RECEIVE_FREE_NCCI 0x26
|
||||
#define RECEIVE_RELEASE 0x26
|
||||
#define RECEIVE_TASK_READY 0x31
|
||||
#define RECEIVE_DEBUGMSG 0x71
|
||||
#define RECEIVE_POLLDWORD 0x75
|
||||
|
||||
/* Operation constants */
|
||||
|
||||
#define WRITE_REGISTER 0x00
|
||||
#define READ_REGISTER 0x01
|
||||
|
||||
/* Port offsets in I/O space */
|
||||
|
||||
#define B1_READ 0x00
|
||||
#define B1_WRITE 0x01
|
||||
#define B1_INSTAT 0x02
|
||||
#define B1_OUTSTAT 0x03
|
||||
#define B1_ANALYSE 0x04
|
||||
#define B1_REVISION 0x05
|
||||
#define B1_RESET 0x10
|
||||
|
||||
#define T1_FASTLINK 0x00
|
||||
#define T1_SLOWLINK 0x08
|
||||
|
||||
#define T1_READ B1_READ
|
||||
#define T1_WRITE B1_WRITE
|
||||
#define T1_INSTAT B1_INSTAT
|
||||
#define T1_OUTSTAT B1_OUTSTAT
|
||||
#define T1_IRQENABLE 0x05
|
||||
#define T1_FIFOSTAT 0x06
|
||||
#define T1_RESETLINK 0x10
|
||||
#define T1_ANALYSE 0x11
|
||||
#define T1_IRQMASTER 0x12
|
||||
#define T1_IDENT 0x17
|
||||
#define T1_RESETBOARD 0x1f
|
||||
|
||||
#define T1F_IREADY 0x01
|
||||
#define T1F_IHALF 0x02
|
||||
#define T1F_IFULL 0x04
|
||||
#define T1F_IEMPTY 0x08
|
||||
#define T1F_IFLAGS 0xf0
|
||||
|
||||
#define T1F_OREADY 0x10
|
||||
#define T1F_OHALF 0x20
|
||||
#define T1F_OEMPTY 0x40
|
||||
#define T1F_OFULL 0x80
|
||||
#define T1F_OFLAGS 0xf0
|
||||
|
||||
#define FIFO_OUTBSIZE 256
|
||||
#define FIFO_INPBSIZE 512
|
||||
|
||||
#define HEMA_VERSION_ID 0
|
||||
#define HEMA_PAL_ID 0
|
||||
|
||||
/*
|
||||
// S5933 DMA controller register offsets in memory, and bitmasks.
|
||||
*/
|
||||
|
||||
#define AMCC_RXPTR 0x24
|
||||
#define AMCC_RXLEN 0x28
|
||||
#define AMCC_TXPTR 0x2c
|
||||
#define AMCC_TXLEN 0x30
|
||||
|
||||
#define AMCC_INTCSR 0x38
|
||||
#define EN_READ_TC_INT 0x00008000
|
||||
#define EN_WRITE_TC_INT 0x00004000
|
||||
#define EN_TX_TC_INT EN_READ_TC_INT
|
||||
#define EN_RX_TC_INT EN_WRITE_TC_INT
|
||||
#define AVM_FLAG 0x30000000
|
||||
|
||||
#define ANY_S5933_INT 0x00800000
|
||||
#define READ_TC_INT 0x00080000
|
||||
#define WRITE_TC_INT 0x00040000
|
||||
#define TX_TC_INT READ_TC_INT
|
||||
#define RX_TC_INT WRITE_TC_INT
|
||||
#define MASTER_ABORT_INT 0x00100000
|
||||
#define TARGET_ABORT_INT 0x00200000
|
||||
#define BUS_MASTER_INT 0x00200000
|
||||
#define ALL_INT 0x000c0000
|
||||
|
||||
#define AMCC_MCSR 0x3c
|
||||
#define A2P_HI_PRIORITY 0x00000100
|
||||
#define EN_A2P_TRANSFERS 0x00000400
|
||||
#define P2A_HI_PRIORITY 0x00001000
|
||||
#define EN_P2A_TRANSFERS 0x00004000
|
||||
#define RESET_A2P_FLAGS 0x04000000
|
||||
#define RESET_P2A_FLAGS 0x02000000
|
||||
|
||||
/*
|
||||
// (B1IO_WAIT_MAX * B1IO_WAIT_DLY) is the max wait in us for the card
|
||||
// to become ready after an I/O operation. The default is 1 ms.
|
||||
*/
|
||||
|
||||
#define B1IO_WAIT_MAX 1000
|
||||
#define B1IO_WAIT_DLY 1
|
||||
|
||||
/*
|
||||
// b1io_outp
|
||||
// Diagnostic output routine, returns the written value via
|
||||
// the device's analysis register.
|
||||
//
|
||||
// b1io_rx_full
|
||||
// Returns nonzero if data is readable from the card via the
|
||||
// I/O ports.
|
||||
//
|
||||
// b1io_tx_empty
|
||||
// Returns nonzero if data can be written to the card via the
|
||||
// I/O ports.
|
||||
*/
|
||||
|
||||
static __inline u_int8_t b1io_outp(iavc_softc_t *sc, int off, u_int8_t val)
|
||||
{
|
||||
bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, off, val);
|
||||
DELAY(1);
|
||||
return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_ANALYSE);
|
||||
}
|
||||
|
||||
static __inline int b1io_rx_full(iavc_softc_t *sc)
|
||||
{
|
||||
u_int8_t val = bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_INSTAT);
|
||||
return (val & 0x01);
|
||||
}
|
||||
|
||||
static __inline int b1io_tx_empty(iavc_softc_t *sc)
|
||||
{
|
||||
u_int8_t val = bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_OUTSTAT);
|
||||
return (val & 0x01);
|
||||
}
|
||||
|
||||
/*
|
||||
// b1io_{get,put}_{byte,word}
|
||||
// Routines to read and write the device I/O registers byte- or
|
||||
// wordwise.
|
||||
//
|
||||
// b1io_{get,put}_slice
|
||||
// Routines to read and write sequential bytes to the device
|
||||
// I/O registers.
|
||||
*/
|
||||
|
||||
static __inline u_int8_t b1io_get_byte(iavc_softc_t *sc)
|
||||
{
|
||||
int spin = 0;
|
||||
while (!b1io_rx_full(sc) && spin < B1IO_WAIT_MAX) {
|
||||
spin++; DELAY(B1IO_WAIT_DLY);
|
||||
}
|
||||
if (b1io_rx_full(sc))
|
||||
return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_READ);
|
||||
printf("iavc%d: rx not completed\n", sc->sc_unit);
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static __inline int b1io_put_byte(iavc_softc_t *sc, u_int8_t val)
|
||||
{
|
||||
int spin = 0;
|
||||
while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
|
||||
spin++; DELAY(B1IO_WAIT_DLY);
|
||||
}
|
||||
if (b1io_tx_empty(sc)) {
|
||||
bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, B1_WRITE, val);
|
||||
return 0;
|
||||
}
|
||||
printf("iavc%d: tx not emptied\n", sc->sc_unit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static __inline int b1io_save_put_byte(iavc_softc_t *sc, u_int8_t val)
|
||||
{
|
||||
int spin = 0;
|
||||
while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
|
||||
spin++; DELAY(B1IO_WAIT_DLY);
|
||||
}
|
||||
if (b1io_tx_empty(sc)) {
|
||||
b1io_outp(sc, B1_WRITE, val);
|
||||
return 0;
|
||||
}
|
||||
printf("iavc%d: tx not emptied\n", sc->sc_unit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static __inline u_int32_t b1io_get_word(iavc_softc_t *sc)
|
||||
{
|
||||
u_int32_t val = 0;
|
||||
val |= b1io_get_byte(sc);
|
||||
val |= (b1io_get_byte(sc) << 8);
|
||||
val |= (b1io_get_byte(sc) << 16);
|
||||
val |= (b1io_get_byte(sc) << 24);
|
||||
return val;
|
||||
}
|
||||
|
||||
static __inline void b1io_put_word(iavc_softc_t *sc, u_int32_t val)
|
||||
{
|
||||
b1io_put_byte(sc, (val & 0xff));
|
||||
b1io_put_byte(sc, (val >> 8) & 0xff);
|
||||
b1io_put_byte(sc, (val >> 16) & 0xff);
|
||||
b1io_put_byte(sc, (val >> 24) & 0xff);
|
||||
}
|
||||
|
||||
static __inline int b1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
|
||||
{
|
||||
int len, i;
|
||||
len = i = b1io_get_word(sc);
|
||||
while (i--) *dp++ = b1io_get_byte(sc);
|
||||
return len;
|
||||
}
|
||||
|
||||
static __inline void b1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
|
||||
{
|
||||
b1io_put_word(sc, len);
|
||||
while (len--) b1io_put_byte(sc, *dp++);
|
||||
}
|
||||
|
||||
/*
|
||||
// b1io_{read,write}_reg
|
||||
// Routines to read and write the device registers via the I/O
|
||||
// ports.
|
||||
*/
|
||||
|
||||
static __inline u_int32_t b1io_read_reg(iavc_softc_t *sc, int reg)
|
||||
{
|
||||
b1io_put_byte(sc, READ_REGISTER);
|
||||
b1io_put_word(sc, reg);
|
||||
return b1io_get_word(sc);
|
||||
}
|
||||
|
||||
static __inline u_int32_t b1io_write_reg(iavc_softc_t *sc, int reg, u_int32_t val)
|
||||
{
|
||||
b1io_put_byte(sc, WRITE_REGISTER);
|
||||
b1io_put_word(sc, reg);
|
||||
b1io_put_word(sc, val);
|
||||
return b1io_get_word(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
// t1io_outp
|
||||
// I/O port write operation for the T1, which does not seem
|
||||
// to have the analysis port.
|
||||
*/
|
||||
|
||||
static __inline void t1io_outp(iavc_softc_t *sc, int off, u_int8_t val)
|
||||
{
|
||||
bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, off, val);
|
||||
}
|
||||
|
||||
static __inline u_int8_t t1io_inp(iavc_softc_t *sc, int off)
|
||||
{
|
||||
return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, off);
|
||||
}
|
||||
|
||||
static __inline int t1io_isfastlink(iavc_softc_t *sc)
|
||||
{
|
||||
return ((bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, T1_IDENT) & ~0x82) == 1);
|
||||
}
|
||||
|
||||
static __inline u_int8_t t1io_fifostatus(iavc_softc_t *sc)
|
||||
{
|
||||
return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, T1_FIFOSTAT);
|
||||
}
|
||||
|
||||
static __inline int t1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
|
||||
{
|
||||
int len, i;
|
||||
len = i = b1io_get_word(sc);
|
||||
if (t1io_isfastlink(sc)) {
|
||||
int status;
|
||||
while (i) {
|
||||
status = t1io_fifostatus(sc) & (T1F_IREADY|T1F_IHALF);
|
||||
if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
|
||||
|
||||
switch (status) {
|
||||
case T1F_IREADY|T1F_IHALF|T1F_IFULL:
|
||||
bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
|
||||
T1_READ, dp, FIFO_INPBSIZE);
|
||||
dp += FIFO_INPBSIZE;
|
||||
i -= FIFO_INPBSIZE;
|
||||
break;
|
||||
|
||||
case T1F_IREADY|T1F_IHALF:
|
||||
bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
|
||||
T1_READ, dp, i);
|
||||
dp += i;
|
||||
i = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
*dp++ = b1io_get_byte(sc);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
} else { /* not fastlink */
|
||||
if (i--) *dp++ = b1io_get_byte(sc);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static __inline void t1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
|
||||
{
|
||||
int i = len;
|
||||
b1io_put_word(sc, i);
|
||||
if (t1io_isfastlink(sc)) {
|
||||
int status;
|
||||
while (i) {
|
||||
status = t1io_fifostatus(sc) & (T1F_OREADY|T1F_OHALF);
|
||||
if (i >= FIFO_OUTBSIZE) status |= T1F_OFULL;
|
||||
|
||||
switch (status) {
|
||||
case T1F_OREADY|T1F_OHALF|T1F_OFULL:
|
||||
bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
|
||||
T1_WRITE, dp, FIFO_OUTBSIZE);
|
||||
dp += FIFO_OUTBSIZE;
|
||||
i -= FIFO_OUTBSIZE;
|
||||
break;
|
||||
|
||||
case T1F_OREADY|T1F_OHALF:
|
||||
bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
|
||||
T1_WRITE, dp, i);
|
||||
dp += i;
|
||||
i = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
b1io_put_byte(sc, *dp++);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (i--) b1io_put_byte(sc, *dp++);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// An attempt to bring it all together:
|
||||
// ------------------------------------
|
||||
//
|
||||
// iavc_{read,write}_reg
|
||||
// Routines to access the device registers via the I/O port.
|
||||
//
|
||||
// iavc_{read,write}_port
|
||||
// Routines to access the device I/O ports.
|
||||
//
|
||||
// iavc_tx_empty, iavc_rx_full
|
||||
// Routines to check when the device has drained the last written
|
||||
// byte, or produced a full byte to read.
|
||||
//
|
||||
// iavc_{get,put}_byte
|
||||
// Routines to read/write byte values to the device via the I/O port.
|
||||
//
|
||||
// iavc_{get,put}_word
|
||||
// Routines to read/write 32-bit words to the device via the I/O port.
|
||||
//
|
||||
// iavc_{get,put}_slice
|
||||
// Routines to read/write {length, data} pairs to the device via the
|
||||
// ubiquituous I/O port. Uses the HEMA FIFO on a T1.
|
||||
*/
|
||||
|
||||
#define iavc_read_reg(sc, reg) b1io_read_reg(sc, reg)
|
||||
#define iavc_write_reg(sc, reg, val) b1io_write_reg(sc, reg, val)
|
||||
|
||||
#define iavc_read_port(sc, port) \
|
||||
bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, (port))
|
||||
#define iavc_write_port(sc, port, val) \
|
||||
bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, (port), (val))
|
||||
|
||||
#define iavc_tx_empty(sc) b1io_tx_empty(sc)
|
||||
#define iavc_rx_full(sc) b1io_rx_full(sc)
|
||||
|
||||
#define iavc_get_byte(sc) b1io_get_byte(sc)
|
||||
#define iavc_put_byte(sc, val) b1io_put_byte(sc, val)
|
||||
#define iavc_get_word(sc) b1io_get_word(sc)
|
||||
#define iavc_put_word(sc, val) b1io_put_word(sc, val)
|
||||
|
||||
static __inline u_int32_t iavc_get_slice(iavc_softc_t *sc, u_int8_t *dp)
|
||||
{
|
||||
if (sc->sc_t1) return t1io_get_slice(sc, dp);
|
||||
else return b1io_get_slice(sc, dp);
|
||||
}
|
||||
|
||||
static __inline void iavc_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
|
||||
{
|
||||
if (sc->sc_t1) t1io_put_slice(sc, dp, len);
|
||||
else b1io_put_slice(sc, dp, len);
|
||||
}
|
||||
|
||||
/*
|
||||
// iavc_handle_intr
|
||||
// Interrupt handler, called by the bus specific interrupt routine
|
||||
// in iavc_<bustype>.c module.
|
||||
//
|
||||
// iavc_load
|
||||
// CAPI callback. Resets device and loads firmware.
|
||||
//
|
||||
// iavc_register
|
||||
// CAPI callback. Registers an application id.
|
||||
//
|
||||
// iavc_release
|
||||
// CAPI callback. Releases an application id.
|
||||
//
|
||||
// iavc_send
|
||||
// CAPI callback. Sends a CAPI message. A B3_DATA_REQ message has
|
||||
// m_next point to a data mbuf.
|
||||
*/
|
||||
|
||||
extern void iavc_handle_intr(iavc_softc_t *);
|
||||
extern int iavc_load(capi_softc_t *, int, u_int8_t *);
|
||||
extern int iavc_register(capi_softc_t *, int, int);
|
||||
extern int iavc_release(capi_softc_t *, int);
|
||||
extern int iavc_send(capi_softc_t *, struct mbuf *);
|
||||
|
||||
extern void b1isa_setup_irq(struct iavc_softc *sc);
|
||||
|
||||
#endif /* _CAPI_IAVC_H_ */
|
292
sys/i4b/capi/iavc/iavc_card.c
Normal file
292
sys/i4b/capi/iavc/iavc_card.c
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/iavc/iavc_card.c
|
||||
* The AVM ISDN controllers' card specific support routines.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "iavc.h"
|
||||
#include "i4bcapi.h"
|
||||
#include "pci.h"
|
||||
|
||||
#if (NIAVC > 0) && (NI4BCAPI > 0)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/i4b_debug.h>
|
||||
#include <machine/i4b_ioctl.h>
|
||||
#include <machine/i4b_trace.h>
|
||||
|
||||
#include <i4b/include/i4b_global.h>
|
||||
#include <i4b/include/i4b_l3l4.h>
|
||||
#include <i4b/include/i4b_mbuf.h>
|
||||
|
||||
#include <i4b/capi/capi.h>
|
||||
|
||||
#include <i4b/capi/iavc/iavc.h>
|
||||
|
||||
/*
|
||||
// AVM B1 (active BRI, PIO mode)
|
||||
*/
|
||||
|
||||
int b1_detect(iavc_softc_t *sc)
|
||||
{
|
||||
if ((iavc_read_port(sc, B1_INSTAT) & 0xfc) ||
|
||||
(iavc_read_port(sc, B1_OUTSTAT) & 0xfc))
|
||||
return (1);
|
||||
|
||||
b1io_outp(sc, B1_INSTAT, 0x02);
|
||||
b1io_outp(sc, B1_OUTSTAT, 0x02);
|
||||
if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) != 2 ||
|
||||
(iavc_read_port(sc, B1_OUTSTAT) & 0xfe) != 2)
|
||||
return (2);
|
||||
|
||||
b1io_outp(sc, B1_INSTAT, 0x00);
|
||||
b1io_outp(sc, B1_OUTSTAT, 0x00);
|
||||
if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) ||
|
||||
(iavc_read_port(sc, B1_OUTSTAT) & 0xfe))
|
||||
return (3);
|
||||
|
||||
return (0); /* found */
|
||||
}
|
||||
|
||||
void b1_disable_irq(iavc_softc_t *sc)
|
||||
{
|
||||
b1io_outp(sc, B1_INSTAT, 0x00);
|
||||
}
|
||||
|
||||
void b1_reset(iavc_softc_t *sc)
|
||||
{
|
||||
b1io_outp(sc, B1_RESET, 0);
|
||||
DELAY(55*2*1000);
|
||||
|
||||
b1io_outp(sc, B1_RESET, 1);
|
||||
DELAY(55*2*1000);
|
||||
|
||||
b1io_outp(sc, B1_RESET, 0);
|
||||
DELAY(55*2*1000);
|
||||
}
|
||||
|
||||
/*
|
||||
// Newer PCI-based B1's, and T1's, supports DMA
|
||||
*/
|
||||
|
||||
int b1dma_detect(iavc_softc_t *sc)
|
||||
{
|
||||
AMCC_WRITE(sc, AMCC_MCSR, 0);
|
||||
DELAY(10*1000);
|
||||
AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
|
||||
DELAY(10*1000);
|
||||
AMCC_WRITE(sc, AMCC_MCSR, 0);
|
||||
DELAY(42*1000);
|
||||
|
||||
AMCC_WRITE(sc, AMCC_RXLEN, 0);
|
||||
AMCC_WRITE(sc, AMCC_TXLEN, 0);
|
||||
sc->sc_csr = 0;
|
||||
AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
|
||||
|
||||
if (AMCC_READ(sc, AMCC_INTCSR) != 0)
|
||||
return 1;
|
||||
|
||||
AMCC_WRITE(sc, AMCC_RXPTR, 0xffffffff);
|
||||
AMCC_WRITE(sc, AMCC_TXPTR, 0xffffffff);
|
||||
if ((AMCC_READ(sc, AMCC_RXPTR) != 0xfffffffc) ||
|
||||
(AMCC_READ(sc, AMCC_TXPTR) != 0xfffffffc))
|
||||
return 2;
|
||||
|
||||
AMCC_WRITE(sc, AMCC_RXPTR, 0);
|
||||
AMCC_WRITE(sc, AMCC_TXPTR, 0);
|
||||
if ((AMCC_READ(sc, AMCC_RXPTR) != 0) ||
|
||||
(AMCC_READ(sc, AMCC_TXPTR) != 0))
|
||||
return 3;
|
||||
|
||||
iavc_write_port(sc, 0x10, 0x00);
|
||||
iavc_write_port(sc, 0x07, 0x00);
|
||||
|
||||
iavc_write_port(sc, 0x02, 0x02);
|
||||
iavc_write_port(sc, 0x03, 0x02);
|
||||
|
||||
if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x02) ||
|
||||
(iavc_read_port(sc, 0x03) != 0x03))
|
||||
return 4;
|
||||
|
||||
iavc_write_port(sc, 0x02, 0x00);
|
||||
iavc_write_port(sc, 0x03, 0x00);
|
||||
|
||||
if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x00) ||
|
||||
(iavc_read_port(sc, 0x03) != 0x01))
|
||||
return 5;
|
||||
|
||||
return (0); /* found */
|
||||
}
|
||||
|
||||
void b1dma_reset(iavc_softc_t *sc)
|
||||
{
|
||||
int s = SPLI4B();
|
||||
|
||||
sc->sc_csr = 0;
|
||||
AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
|
||||
AMCC_WRITE(sc, AMCC_MCSR, 0);
|
||||
AMCC_WRITE(sc, AMCC_RXLEN, 0);
|
||||
AMCC_WRITE(sc, AMCC_TXLEN, 0);
|
||||
|
||||
iavc_write_port(sc, 0x10, 0x00); /* XXX magic numbers from */
|
||||
iavc_write_port(sc, 0x07, 0x00); /* XXX the linux driver */
|
||||
|
||||
splx(s);
|
||||
|
||||
AMCC_WRITE(sc, AMCC_MCSR, 0);
|
||||
DELAY(10 * 1000);
|
||||
AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
|
||||
DELAY(10 * 1000);
|
||||
AMCC_WRITE(sc, AMCC_MCSR, 0);
|
||||
DELAY(42 * 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
// AVM T1 (active PRI)
|
||||
*/
|
||||
|
||||
/* XXX how do these differ from b1io_{read,write}_reg()? XXX */
|
||||
|
||||
static int b1dma_tx_empty(int iobase)
|
||||
{ return inb(iobase + 3) & 1; }
|
||||
|
||||
static int b1dma_rx_full(int iobase)
|
||||
{ return inb(iobase + 2) & 1; }
|
||||
|
||||
static int b1dma_tolink(iavc_softc_t *sc, void *buf, int len)
|
||||
{
|
||||
volatile int spin;
|
||||
char *s = (char*) buf;
|
||||
while (len--) {
|
||||
spin = 0;
|
||||
while (!b1dma_tx_empty(sc->sc_iobase) && spin < 100000)
|
||||
spin++;
|
||||
if (!b1dma_tx_empty(sc->sc_iobase))
|
||||
return -1;
|
||||
t1io_outp(sc, 1, *s++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b1dma_fromlink(iavc_softc_t *sc, void *buf, int len)
|
||||
{
|
||||
volatile int spin;
|
||||
char *s = (char*) buf;
|
||||
while (len--) {
|
||||
spin = 0;
|
||||
while (!b1dma_rx_full(sc->sc_iobase) && spin < 100000)
|
||||
spin++;
|
||||
if (!b1dma_rx_full(sc->sc_iobase))
|
||||
return -1;
|
||||
*s++ = t1io_inp(sc, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int WriteReg(iavc_softc_t *sc, u_int32_t reg, u_int8_t val)
|
||||
{
|
||||
u_int8_t cmd = 0;
|
||||
if (b1dma_tolink(sc, &cmd, 1) == 0 &&
|
||||
b1dma_tolink(sc, ®, 4) == 0) {
|
||||
u_int32_t tmp = val;
|
||||
return b1dma_tolink(sc, &tmp, 4);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static u_int8_t ReadReg(iavc_softc_t *sc, u_int32_t reg)
|
||||
{
|
||||
u_int8_t cmd = 1;
|
||||
if (b1dma_tolink(sc, &cmd, 1) == 0 &&
|
||||
b1dma_tolink(sc, ®, 4) == 0) {
|
||||
u_int32_t tmp;
|
||||
if (b1dma_fromlink(sc, &tmp, 4) == 0)
|
||||
return (u_int8_t) tmp;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
int t1_detect(iavc_softc_t *sc)
|
||||
{
|
||||
int ret = b1dma_detect(sc);
|
||||
if (ret) return ret;
|
||||
|
||||
if ((WriteReg(sc, 0x80001000, 0x11) != 0) ||
|
||||
(WriteReg(sc, 0x80101000, 0x22) != 0) ||
|
||||
(WriteReg(sc, 0x80201000, 0x33) != 0) ||
|
||||
(WriteReg(sc, 0x80301000, 0x44) != 0))
|
||||
return 6;
|
||||
|
||||
if ((ReadReg(sc, 0x80001000) != 0x11) ||
|
||||
(ReadReg(sc, 0x80101000) != 0x22) ||
|
||||
(ReadReg(sc, 0x80201000) != 0x33) ||
|
||||
(ReadReg(sc, 0x80301000) != 0x44))
|
||||
return 7;
|
||||
|
||||
if ((WriteReg(sc, 0x80001000, 0x55) != 0) ||
|
||||
(WriteReg(sc, 0x80101000, 0x66) != 0) ||
|
||||
(WriteReg(sc, 0x80201000, 0x77) != 0) ||
|
||||
(WriteReg(sc, 0x80301000, 0x88) != 0))
|
||||
return 8;
|
||||
|
||||
if ((ReadReg(sc, 0x80001000) != 0x55) ||
|
||||
(ReadReg(sc, 0x80101000) != 0x66) ||
|
||||
(ReadReg(sc, 0x80201000) != 0x77) ||
|
||||
(ReadReg(sc, 0x80301000) != 0x88))
|
||||
return 9;
|
||||
|
||||
return 0; /* found */
|
||||
}
|
||||
|
||||
void t1_disable_irq(iavc_softc_t *sc)
|
||||
{
|
||||
iavc_write_port(sc, T1_IRQMASTER, 0x00);
|
||||
}
|
||||
|
||||
void t1_reset(iavc_softc_t *sc)
|
||||
{
|
||||
b1_reset(sc);
|
||||
iavc_write_port(sc, B1_INSTAT, 0x00);
|
||||
iavc_write_port(sc, B1_OUTSTAT, 0x00);
|
||||
iavc_write_port(sc, T1_IRQMASTER, 0x00);
|
||||
iavc_write_port(sc, T1_RESETBOARD, 0x0f);
|
||||
}
|
||||
|
||||
#endif
|
297
sys/i4b/capi/iavc/iavc_isa.c
Normal file
297
sys/i4b/capi/iavc/iavc_isa.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Hellmuth Michaelis. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "iavc.h"
|
||||
#include "i4bcapi.h"
|
||||
|
||||
#if (NIAVC > 0) && (NI4BCAPI > 0)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#include <machine/i4b_debug.h>
|
||||
#include <machine/i4b_ioctl.h>
|
||||
#include <machine/i4b_trace.h>
|
||||
|
||||
#include <i4b/include/i4b_global.h>
|
||||
#include <i4b/include/i4b_l3l4.h>
|
||||
#include <i4b/include/i4b_mbuf.h>
|
||||
|
||||
#include <i4b/capi/capi.h>
|
||||
|
||||
#include <i4b/capi/iavc/iavc.h>
|
||||
|
||||
/* ISA driver linkage */
|
||||
|
||||
static void iavc_isa_intr(iavc_softc_t *sc);
|
||||
static int iavc_isa_probe(device_t dev);
|
||||
static int iavc_isa_attach(device_t dev);
|
||||
|
||||
static device_method_t iavc_isa_methods[] =
|
||||
{
|
||||
DEVMETHOD(device_probe, iavc_isa_probe),
|
||||
DEVMETHOD(device_attach, iavc_isa_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t iavc_isa_driver =
|
||||
{
|
||||
"iavc",
|
||||
iavc_isa_methods,
|
||||
0
|
||||
};
|
||||
|
||||
static devclass_t iavc_isa_devclass;
|
||||
|
||||
DRIVER_MODULE(iavc, isa, iavc_isa_driver, iavc_isa_devclass, 0, 0);
|
||||
|
||||
#define B1_IOLENGTH 0x20
|
||||
|
||||
static int b1_irq_table[] =
|
||||
{0, 0, 0, 192, 32, 160, 96, 224, 0, 64, 80, 208, 48, 0, 0, 112};
|
||||
/* 3 4 5 6 7 9 10 11 12 15 */
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* device probe
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
iavc_isa_probe(device_t dev)
|
||||
{
|
||||
struct iavc_softc *sc;
|
||||
int ret = ENXIO;
|
||||
int unit = device_get_unit(dev);
|
||||
|
||||
if(isa_get_vendorid(dev)) /* no PnP probes here */
|
||||
return ENXIO;
|
||||
|
||||
/* check max unit range */
|
||||
|
||||
if (unit >= IAVC_MAXUNIT)
|
||||
{
|
||||
printf("iavc%d: too many units\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
sc = iavc_find_sc(unit); /* get softc */
|
||||
|
||||
sc->sc_unit = unit;
|
||||
|
||||
if (!(sc->sc_resources.io_base[0] =
|
||||
bus_alloc_resource(dev, SYS_RES_IOPORT,
|
||||
&sc->sc_resources.io_rid[0],
|
||||
0UL, ~0UL, B1_IOLENGTH, RF_ACTIVE)))
|
||||
{
|
||||
printf("iavc%d: can't allocate io region\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
sc->sc_iobase = rman_get_start(sc->sc_resources.io_base[0]);
|
||||
|
||||
switch(sc->sc_iobase)
|
||||
{
|
||||
case 0x150:
|
||||
case 0x250:
|
||||
case 0x300:
|
||||
case 0x340:
|
||||
break;
|
||||
default:
|
||||
printf("iavc%d: ERROR, invalid i/o base addr 0x%x configured!\n", sc->sc_unit, sc->sc_iobase);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||
sc->sc_resources.io_rid[0],
|
||||
sc->sc_resources.io_base[0]);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
sc->sc_io_bt = rman_get_bustag(sc->sc_resources.io_base[0]);
|
||||
sc->sc_io_bh = rman_get_bushandle(sc->sc_resources.io_base[0]);
|
||||
|
||||
/* setup characteristics */
|
||||
|
||||
sc->sc_t1 = FALSE;
|
||||
sc->sc_dma = FALSE;
|
||||
|
||||
sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_ISA;
|
||||
sc->sc_capi.sc_nbch = 2;
|
||||
|
||||
b1_reset(sc);
|
||||
DELAY(100);
|
||||
|
||||
ret = b1_detect(sc);
|
||||
|
||||
if(ret)
|
||||
{
|
||||
printf("iavc%d: no card ? b1_detect returns 0x02x\n", sc->sc_unit, ret);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
DELAY(100);
|
||||
|
||||
b1_reset(sc);
|
||||
|
||||
DELAY(100);
|
||||
|
||||
if(bootverbose)
|
||||
{
|
||||
printf("iavc%d: class = 0x%02x, rev = 0x%02x\n", sc->sc_unit,
|
||||
iavc_read_port(sc, B1_ANALYSE),
|
||||
iavc_read_port(sc, B1_REVISION));
|
||||
}
|
||||
|
||||
device_set_desc(dev, "AVM B1 ISA");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* attach
|
||||
*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
iavc_isa_attach(device_t dev)
|
||||
{
|
||||
struct iavc_softc *sc;
|
||||
void *ih = 0;
|
||||
int unit = device_get_unit(dev);
|
||||
int irq;
|
||||
|
||||
sc = iavc_find_sc(unit); /* get softc */
|
||||
|
||||
sc->sc_resources.irq_rid = 0;
|
||||
|
||||
if(!(sc->sc_resources.irq =
|
||||
bus_alloc_resource(dev, SYS_RES_IRQ,
|
||||
&sc->sc_resources.irq_rid,
|
||||
0UL, ~0UL, 1, RF_ACTIVE)))
|
||||
{
|
||||
printf("iavc%d: can't allocate irq\n",unit);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||
sc->sc_resources.io_rid[0],
|
||||
sc->sc_resources.io_base[0]);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
irq = rman_get_start(sc->sc_resources.irq);
|
||||
|
||||
if(b1_irq_table[irq] == 0)
|
||||
{
|
||||
printf("iavc%d: ERROR, illegal irq %d configured!\n",unit, irq);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||
sc->sc_resources.io_rid[0],
|
||||
sc->sc_resources.io_base[0]);
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->sc_resources.irq_rid,
|
||||
sc->sc_resources.irq);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
memset(&sc->sc_txq, 0, sizeof(struct ifqueue));
|
||||
sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4;
|
||||
|
||||
#if defined (__FreeBSD__) && __FreeBSD__ > 4
|
||||
mtx_init(&sc->sc_txq.ifq_mtx, "i4b_ivac_isa", MTX_DEF);
|
||||
#endif
|
||||
|
||||
sc->sc_intr = FALSE;
|
||||
sc->sc_state = IAVC_DOWN;
|
||||
sc->sc_blocked = FALSE;
|
||||
|
||||
/* setup capi link */
|
||||
|
||||
sc->sc_capi.load = iavc_load;
|
||||
sc->sc_capi.reg_appl = iavc_register;
|
||||
sc->sc_capi.rel_appl = iavc_release;
|
||||
sc->sc_capi.send = iavc_send;
|
||||
sc->sc_capi.ctx = (void*) sc;
|
||||
|
||||
if (capi_ll_attach(&sc->sc_capi))
|
||||
{
|
||||
printf("iavc%d: capi attach failed\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
/* setup the interrupt */
|
||||
|
||||
if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
|
||||
(void(*)(void*))iavc_isa_intr,
|
||||
sc, &ih))
|
||||
{
|
||||
printf("iavc%d: irq setup failed\n", unit);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT,
|
||||
sc->sc_resources.io_rid[0],
|
||||
sc->sc_resources.io_base[0]);
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->sc_resources.irq_rid,
|
||||
sc->sc_resources.irq);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
/* the board is now ready to be loaded */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* setup interrupt
|
||||
*---------------------------------------------------------------------------*/
|
||||
void
|
||||
b1isa_setup_irq(struct iavc_softc *sc)
|
||||
{
|
||||
int irq = rman_get_start(sc->sc_resources.irq);
|
||||
|
||||
if(bootverbose)
|
||||
printf("iavc%d: using irq %d\n", sc->sc_unit, irq);
|
||||
|
||||
/* enable the interrupt */
|
||||
|
||||
b1io_outp(sc, B1_INSTAT, 0x00);
|
||||
b1io_outp(sc, B1_RESET, b1_irq_table[irq]);
|
||||
b1io_outp(sc, B1_INSTAT, 0x02);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* IRQ handler
|
||||
*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
iavc_isa_intr(struct iavc_softc *sc)
|
||||
{
|
||||
iavc_handle_intr(sc);
|
||||
}
|
||||
|
||||
#endif
|
834
sys/i4b/capi/iavc/iavc_lli.c
Normal file
834
sys/i4b/capi/iavc/iavc_lli.c
Normal file
@ -0,0 +1,834 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/iavc/iavc_lli.c
|
||||
* The AVM ISDN controllers' Low Level Interface.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "iavc.h"
|
||||
#include "i4bcapi.h"
|
||||
#include "pci.h"
|
||||
|
||||
#if (NIAVC > 0) && (NI4BCAPI > 0)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <machine/i4b_debug.h>
|
||||
#include <machine/i4b_ioctl.h>
|
||||
#include <machine/i4b_trace.h>
|
||||
|
||||
#include <i4b/include/i4b_global.h>
|
||||
#include <i4b/include/i4b_l3l4.h>
|
||||
#include <i4b/include/i4b_mbuf.h>
|
||||
|
||||
#include <i4b/capi/capi.h>
|
||||
#include <i4b/capi/capi_msgs.h>
|
||||
|
||||
#include <i4b/capi/iavc/iavc.h>
|
||||
|
||||
/* Forward declarations of local subroutines... */
|
||||
|
||||
static int iavc_send_init(iavc_softc_t *);
|
||||
|
||||
static void iavc_handle_rx(iavc_softc_t *);
|
||||
static void iavc_start_tx(iavc_softc_t *);
|
||||
|
||||
/*
|
||||
// Callbacks from the upper (capi) layer:
|
||||
// --------------------------------------
|
||||
//
|
||||
// iavc_load
|
||||
// Resets the board and loads the firmware, then initiates
|
||||
// board startup.
|
||||
//
|
||||
// iavc_register
|
||||
// Registers a CAPI application id.
|
||||
//
|
||||
// iavc_release
|
||||
// Releases a CAPI application id.
|
||||
//
|
||||
// iavc_send
|
||||
// Sends a capi message.
|
||||
*/
|
||||
|
||||
int iavc_load(capi_softc_t *capi_sc, int len, u_int8_t *cp)
|
||||
{
|
||||
iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
|
||||
u_int8_t val;
|
||||
|
||||
if(bootverbose)
|
||||
printf("iavc%d: reset card ....\n", sc->sc_unit);
|
||||
|
||||
if (sc->sc_dma)
|
||||
b1dma_reset(sc); /* PCI cards */
|
||||
else if (sc->sc_t1)
|
||||
t1_reset(sc); /* ISA attachment T1 */
|
||||
else
|
||||
b1_reset(sc); /* ISA attachment B1 */
|
||||
|
||||
DELAY(1000);
|
||||
|
||||
if(bootverbose)
|
||||
printf("iavc%d: start loading %d bytes firmware ....\n", sc->sc_unit, len);
|
||||
|
||||
while (len && b1io_save_put_byte(sc, *cp++) == 0)
|
||||
len--;
|
||||
|
||||
if (len) {
|
||||
printf("iavc%d: loading failed, can't write to card, len = %d\n",
|
||||
sc->sc_unit, len);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
if(bootverbose)
|
||||
printf("iavc%d: firmware loaded, wait for ACK ....\n", sc->sc_unit);
|
||||
|
||||
if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
|
||||
iavc_put_byte(sc, SEND_POLL);
|
||||
else
|
||||
iavc_put_byte(sc, SEND_POLLACK);
|
||||
|
||||
for (len = 0; len < 1000 && !iavc_rx_full(sc); len++)
|
||||
DELAY(100);
|
||||
|
||||
if (!iavc_rx_full(sc)) {
|
||||
printf("iavc%d: loading failed, no ack\n", sc->sc_unit);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
val = iavc_get_byte(sc);
|
||||
|
||||
if ((sc->sc_dma && val != RECEIVE_POLLDWORD) ||
|
||||
(!sc->sc_dma && val != RECEIVE_POLL)) {
|
||||
printf("iavc%d: loading failed, bad ack = %02x\n", sc->sc_unit, val);
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
if(bootverbose)
|
||||
printf("iavc%d: got ACK = 0x%02x\n", sc->sc_unit, val);
|
||||
|
||||
if (sc->sc_dma) {
|
||||
/* Start the DMA engine */
|
||||
|
||||
int s = SPLI4B();
|
||||
|
||||
sc->sc_csr = AVM_FLAG;
|
||||
AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
|
||||
AMCC_WRITE(sc, AMCC_MCSR, (EN_A2P_TRANSFERS|EN_P2A_TRANSFERS|
|
||||
A2P_HI_PRIORITY|P2A_HI_PRIORITY|
|
||||
RESET_A2P_FLAGS|RESET_P2A_FLAGS));
|
||||
|
||||
iavc_write_port(sc, 0x07, 0x30); /* XXX magic numbers from */
|
||||
iavc_write_port(sc, 0x10, 0xf0); /* XXX the linux driver */
|
||||
|
||||
sc->sc_recvlen = 0;
|
||||
AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[0]));
|
||||
AMCC_WRITE(sc, AMCC_RXLEN, 4);
|
||||
sc->sc_csr |= EN_RX_TC_INT|EN_TX_TC_INT;
|
||||
AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
|
||||
b1isa_setup_irq(sc);
|
||||
|
||||
iavc_send_init(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iavc_register(capi_softc_t *capi_sc, int applid, int nchan)
|
||||
{
|
||||
iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
|
||||
struct mbuf *m = i4b_Dgetmbuf(23);
|
||||
u_int8_t *p;
|
||||
|
||||
if (!m) {
|
||||
printf("iavc%d: can't get memory\n", sc->sc_unit);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* byte 0x12 = SEND_REGISTER
|
||||
* dword ApplId
|
||||
* dword NumMessages
|
||||
* dword NumB3Connections 0..nbch
|
||||
* dword NumB3Blocks
|
||||
* dword B3Size
|
||||
*/
|
||||
|
||||
p = amcc_put_byte(mtod(m, u_int8_t*), 0);
|
||||
p = amcc_put_byte(p, 0);
|
||||
p = amcc_put_byte(p, SEND_REGISTER);
|
||||
p = amcc_put_word(p, applid);
|
||||
#if 0
|
||||
p = amcc_put_word(p, 1024 + (nchan + 1));
|
||||
#else
|
||||
p = amcc_put_word(p, 1024 * (nchan + 1));
|
||||
#endif
|
||||
p = amcc_put_word(p, nchan);
|
||||
p = amcc_put_word(p, 8);
|
||||
p = amcc_put_word(p, 2048);
|
||||
|
||||
_IF_ENQUEUE(&sc->sc_txq, m);
|
||||
|
||||
iavc_start_tx(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iavc_release(capi_softc_t *capi_sc, int applid)
|
||||
{
|
||||
iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
|
||||
struct mbuf *m = i4b_Dgetmbuf(7);
|
||||
u_int8_t *p;
|
||||
|
||||
if (!m) {
|
||||
printf("iavc%d: can't get memory\n", sc->sc_unit);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* byte 0x14 = SEND_RELEASE
|
||||
* dword ApplId
|
||||
*/
|
||||
|
||||
p = amcc_put_byte(mtod(m, u_int8_t*), 0);
|
||||
p = amcc_put_byte(p, 0);
|
||||
p = amcc_put_byte(p, SEND_RELEASE);
|
||||
p = amcc_put_word(p, applid);
|
||||
|
||||
_IF_ENQUEUE(&sc->sc_txq, m);
|
||||
|
||||
iavc_start_tx(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iavc_send(capi_softc_t *capi_sc, struct mbuf *m)
|
||||
{
|
||||
iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
|
||||
|
||||
if (sc->sc_state != IAVC_UP) {
|
||||
printf("iavc%d: attempt to send before device up\n", sc->sc_unit);
|
||||
|
||||
if (m->m_next) i4b_Bfreembuf(m->m_next);
|
||||
i4b_Dfreembuf(m);
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (_IF_QFULL(&sc->sc_txq)) {
|
||||
_IF_DROP(&sc->sc_txq);
|
||||
|
||||
printf("iavc%d: tx overflow, message dropped\n", sc->sc_unit);
|
||||
|
||||
if (m->m_next) i4b_Bfreembuf(m->m_next);
|
||||
i4b_Dfreembuf(m);
|
||||
|
||||
} else {
|
||||
_IF_ENQUEUE(&sc->sc_txq, m);
|
||||
|
||||
iavc_start_tx(sc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// Functions called by ourself during the initialization sequence:
|
||||
// ---------------------------------------------------------------
|
||||
//
|
||||
// iavc_send_init
|
||||
// Sends the system initialization message to a newly loaded
|
||||
// board, and sets state to INIT.
|
||||
*/
|
||||
|
||||
static int iavc_send_init(iavc_softc_t *sc)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(15);
|
||||
u_int8_t *p;
|
||||
int s;
|
||||
|
||||
if (!m) {
|
||||
printf("iavc%d: can't get memory\n", sc->sc_unit);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* byte 0x11 = SEND_INIT
|
||||
* dword NumApplications
|
||||
* dword NumNCCIs
|
||||
* dword BoardNumber
|
||||
*/
|
||||
|
||||
p = amcc_put_byte(mtod(m, u_int8_t*), 0);
|
||||
p = amcc_put_byte(p, 0);
|
||||
p = amcc_put_byte(p, SEND_INIT);
|
||||
p = amcc_put_word(p, 1); /* XXX MaxAppl XXX */
|
||||
p = amcc_put_word(p, sc->sc_capi.sc_nbch);
|
||||
p = amcc_put_word(p, sc->sc_unit);
|
||||
|
||||
s = SPLI4B();
|
||||
_IF_ENQUEUE(&sc->sc_txq, m);
|
||||
|
||||
iavc_start_tx(sc);
|
||||
|
||||
sc->sc_state = IAVC_INIT;
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// Functions called during normal operation:
|
||||
// -----------------------------------------
|
||||
//
|
||||
// iavc_receive_init
|
||||
// Reads the initialization reply and calls capi_ll_control().
|
||||
//
|
||||
// iavc_receive_new_ncci
|
||||
// Reads a new NCCI notification and calls capi_ll_control().
|
||||
//
|
||||
// iavc_receive_free_ncci
|
||||
// Reads a freed NCCI notification and calls capi_ll_control().
|
||||
//
|
||||
// iavc_receive_task_ready
|
||||
// Reads a task ready message -- which should not occur XXX.
|
||||
//
|
||||
// iavc_receive_debugmsg
|
||||
// Reads a debug message -- which should not occur XXX.
|
||||
//
|
||||
// iavc_receive_start
|
||||
// Reads a START TRANSMIT message and unblocks device.
|
||||
//
|
||||
// iavc_receive_stop
|
||||
// Reads a STOP TRANSMIT message and blocks device.
|
||||
//
|
||||
// iavc_receive
|
||||
// Reads an incoming message and calls capi_ll_receive().
|
||||
*/
|
||||
|
||||
static int iavc_receive_init(iavc_softc_t *sc, u_int8_t *dmabuf)
|
||||
{
|
||||
u_int32_t Length;
|
||||
u_int8_t *p;
|
||||
u_int8_t *cardtype, *serial, *profile, *version, *caps, *prot;
|
||||
|
||||
if (sc->sc_dma) {
|
||||
p = amcc_get_word(dmabuf, &Length);
|
||||
} else {
|
||||
Length = iavc_get_slice(sc, sc->sc_recvbuf);
|
||||
p = sc->sc_recvbuf;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
int len = 0;
|
||||
printf("iavc%d: rx_init: ", sc->sc_unit);
|
||||
while (len < Length) {
|
||||
printf(" %02x", p[len]);
|
||||
if (len && (len % 16) == 0) printf("\n");
|
||||
len++;
|
||||
}
|
||||
if (len % 16) printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
version = (p + 1);
|
||||
p += (*p + 1); /* driver version */
|
||||
cardtype = (p + 1);
|
||||
p += (*p + 1); /* card type */
|
||||
p += (*p + 1); /* hardware ID */
|
||||
serial = (p + 1);
|
||||
p += (*p + 1); /* serial number */
|
||||
caps = (p + 1);
|
||||
p += (*p + 1); /* supported options */
|
||||
prot = (p + 1);
|
||||
p += (*p + 1); /* supported protocols */
|
||||
profile = (p + 1);
|
||||
|
||||
if (cardtype && serial && profile) {
|
||||
int nbch = ((profile[3]<<8) | profile[2]);
|
||||
|
||||
printf("iavc%d: AVM %s, s/n %s, %d chans, f/w rev %s, prot %s\n",
|
||||
sc->sc_unit, cardtype, serial, nbch, version, prot);
|
||||
|
||||
if(bootverbose)
|
||||
printf("iavc%d: %s\n", sc->sc_unit, caps);
|
||||
|
||||
capi_ll_control(&sc->sc_capi, CAPI_CTRL_PROFILE, (int) profile);
|
||||
|
||||
} else {
|
||||
printf("iavc%d: no profile data in info response?\n", sc->sc_unit);
|
||||
}
|
||||
|
||||
sc->sc_blocked = TRUE; /* controller will send START when ready */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iavc_receive_start(iavc_softc_t *sc, u_int8_t *dmabuf)
|
||||
{
|
||||
struct mbuf *m = i4b_Dgetmbuf(3);
|
||||
u_int8_t *p;
|
||||
|
||||
if (sc->sc_blocked && sc->sc_state == IAVC_UP)
|
||||
printf("iavc%d: receive_start\n", sc->sc_unit);
|
||||
|
||||
if (!m) {
|
||||
printf("iavc%d: can't get memory\n", sc->sc_unit);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* byte 0x73 = SEND_POLLACK
|
||||
*/
|
||||
|
||||
p = amcc_put_byte(mtod(m, u_int8_t*), 0);
|
||||
p = amcc_put_byte(p, 0);
|
||||
p = amcc_put_byte(p, SEND_POLLACK);
|
||||
|
||||
_IF_PREPEND(&sc->sc_txq, m);
|
||||
|
||||
NDBGL4(L4_IAVCDBG, "iavc%d: blocked = %d, state = %d",
|
||||
sc->sc_unit, sc->sc_blocked, sc->sc_state);
|
||||
|
||||
sc->sc_blocked = FALSE;
|
||||
iavc_start_tx(sc);
|
||||
|
||||
/* If this was our first START, register our readiness */
|
||||
|
||||
if (sc->sc_state != IAVC_UP) {
|
||||
sc->sc_state = IAVC_UP;
|
||||
capi_ll_control(&sc->sc_capi, CAPI_CTRL_READY, TRUE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iavc_receive_stop(iavc_softc_t *sc, u_int8_t *dmabuf)
|
||||
{
|
||||
printf("iavc%d: receive_stop\n", sc->sc_unit);
|
||||
sc->sc_blocked = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iavc_receive_new_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
|
||||
{
|
||||
u_int32_t ApplId, NCCI, WindowSize;
|
||||
|
||||
if (sc->sc_dma) {
|
||||
dmabuf = amcc_get_word(dmabuf, &ApplId);
|
||||
dmabuf = amcc_get_word(dmabuf, &NCCI);
|
||||
dmabuf = amcc_get_word(dmabuf, &WindowSize);
|
||||
} else {
|
||||
ApplId = iavc_get_word(sc);
|
||||
NCCI = iavc_get_word(sc);
|
||||
WindowSize = iavc_get_word(sc);
|
||||
}
|
||||
|
||||
capi_ll_control(&sc->sc_capi, CAPI_CTRL_NEW_NCCI, NCCI);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iavc_receive_free_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
|
||||
{
|
||||
u_int32_t ApplId, NCCI;
|
||||
|
||||
if (sc->sc_dma) {
|
||||
dmabuf = amcc_get_word(dmabuf, &ApplId);
|
||||
dmabuf = amcc_get_word(dmabuf, &NCCI);
|
||||
} else {
|
||||
ApplId = iavc_get_word(sc);
|
||||
NCCI = iavc_get_word(sc);
|
||||
}
|
||||
|
||||
capi_ll_control(&sc->sc_capi, CAPI_CTRL_FREE_NCCI, NCCI);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iavc_receive_task_ready(iavc_softc_t *sc, u_int8_t *dmabuf)
|
||||
{
|
||||
u_int32_t TaskId, Length;
|
||||
u_int8_t *p;
|
||||
printf("iavc%d: receive_task_ready\n", sc->sc_unit);
|
||||
|
||||
if (sc->sc_dma) {
|
||||
p = amcc_get_word(dmabuf, &TaskId);
|
||||
p = amcc_get_word(p, &Length);
|
||||
} else {
|
||||
TaskId = iavc_get_word(sc);
|
||||
Length = iavc_get_slice(sc, sc->sc_recvbuf);
|
||||
p = sc->sc_recvbuf;
|
||||
}
|
||||
|
||||
/* XXX could show the message if trace enabled? XXX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iavc_receive_debugmsg(iavc_softc_t *sc, u_int8_t *dmabuf)
|
||||
{
|
||||
u_int32_t Length;
|
||||
u_int8_t *p;
|
||||
printf("iavc%d: receive_debugmsg\n", sc->sc_unit);
|
||||
|
||||
if (sc->sc_dma) {
|
||||
p = amcc_get_word(dmabuf, &Length);
|
||||
} else {
|
||||
Length = iavc_get_slice(sc, sc->sc_recvbuf);
|
||||
p = sc->sc_recvbuf;
|
||||
}
|
||||
|
||||
/* XXX could show the message if trace enabled? XXX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iavc_receive(iavc_softc_t *sc, u_int8_t *dmabuf, int b3data)
|
||||
{
|
||||
struct mbuf *m;
|
||||
u_int32_t ApplId, Length;
|
||||
|
||||
/*
|
||||
* byte 0x21 = RECEIVE_MESSAGE
|
||||
* dword ApplId
|
||||
* dword length
|
||||
* ... CAPI msg
|
||||
*
|
||||
* --or--
|
||||
*
|
||||
* byte 0x22 = RECEIVE_DATA_B3_IND
|
||||
* dword ApplId
|
||||
* dword length
|
||||
* ... CAPI msg
|
||||
* dword datalen
|
||||
* ... B3 data
|
||||
*/
|
||||
|
||||
if (sc->sc_dma) {
|
||||
dmabuf = amcc_get_word(dmabuf, &ApplId);
|
||||
dmabuf = amcc_get_word(dmabuf, &Length);
|
||||
} else {
|
||||
ApplId = iavc_get_word(sc);
|
||||
Length = iavc_get_slice(sc, sc->sc_recvbuf);
|
||||
dmabuf = sc->sc_recvbuf;
|
||||
}
|
||||
|
||||
m = i4b_Dgetmbuf(Length);
|
||||
if (!m) {
|
||||
printf("iavc%d: can't get memory for receive\n", sc->sc_unit);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
bcopy(dmabuf, mtod(m, u_int8_t*), Length);
|
||||
|
||||
#if 0
|
||||
{
|
||||
u_int8_t *p = mtod(m, u_int8_t*);
|
||||
int len = 0;
|
||||
printf("iavc%d: applid=%d, len=%d\n", sc->sc_unit, ApplId, Length);
|
||||
while (len < m->m_len) {
|
||||
printf(" %02x", p[len]);
|
||||
if (len && (len % 16) == 0) printf("\n");
|
||||
len++;
|
||||
}
|
||||
if (len % 16) printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (b3data) {
|
||||
if (sc->sc_dma) {
|
||||
dmabuf = amcc_get_word(dmabuf + Length, &Length);
|
||||
} else {
|
||||
Length = iavc_get_slice(sc, sc->sc_recvbuf);
|
||||
dmabuf = sc->sc_recvbuf;
|
||||
}
|
||||
|
||||
m->m_next = i4b_Bgetmbuf(Length);
|
||||
if (!m->m_next) {
|
||||
printf("iavc%d: can't get memory for receive\n", sc->sc_unit);
|
||||
i4b_Dfreembuf(m);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
bcopy(dmabuf, mtod(m->m_next, u_int8_t*), Length);
|
||||
}
|
||||
|
||||
capi_ll_receive(&sc->sc_capi, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// iavc_handle_intr
|
||||
// Checks device interrupt status and calls iavc_handle_{rx,tx}()
|
||||
// as necessary.
|
||||
//
|
||||
// iavc_handle_rx
|
||||
// Reads in the command byte and calls the subroutines above.
|
||||
//
|
||||
// iavc_start_tx
|
||||
// Initiates DMA on the next queued message if possible.
|
||||
*/
|
||||
|
||||
void iavc_handle_intr(iavc_softc_t *sc)
|
||||
{
|
||||
u_int32_t status;
|
||||
u_int32_t newcsr;
|
||||
|
||||
if (!sc->sc_dma) {
|
||||
while (iavc_rx_full(sc))
|
||||
iavc_handle_rx(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
status = AMCC_READ(sc, AMCC_INTCSR);
|
||||
if ((status & ANY_S5933_INT) == 0)
|
||||
return;
|
||||
|
||||
newcsr = sc->sc_csr | (status & ALL_INT);
|
||||
if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
|
||||
if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
|
||||
AMCC_WRITE(sc, AMCC_INTCSR, newcsr);
|
||||
sc->sc_intr = TRUE;
|
||||
|
||||
if (status & RX_TC_INT) {
|
||||
u_int32_t rxlen;
|
||||
|
||||
if (sc->sc_recvlen == 0) {
|
||||
sc->sc_recvlen = *((u_int32_t*)(&sc->sc_recvbuf[0]));
|
||||
rxlen = (sc->sc_recvlen + 3) & ~3;
|
||||
AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[4]));
|
||||
AMCC_WRITE(sc, AMCC_RXLEN, rxlen);
|
||||
} else {
|
||||
iavc_handle_rx(sc);
|
||||
sc->sc_recvlen = 0;
|
||||
AMCC_WRITE(sc, AMCC_RXPTR, vtophys(&sc->sc_recvbuf[0]));
|
||||
AMCC_WRITE(sc, AMCC_RXLEN, 4);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & TX_TC_INT) {
|
||||
sc->sc_csr &= ~EN_TX_TC_INT;
|
||||
iavc_start_tx(sc);
|
||||
}
|
||||
|
||||
AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
|
||||
sc->sc_intr = FALSE;
|
||||
}
|
||||
|
||||
static void iavc_handle_rx(iavc_softc_t *sc)
|
||||
{
|
||||
u_int8_t *dmabuf = 0, cmd;
|
||||
|
||||
if (sc->sc_dma) {
|
||||
dmabuf = amcc_get_byte(&sc->sc_recvbuf[4], &cmd);
|
||||
} else {
|
||||
cmd = iavc_get_byte(sc);
|
||||
}
|
||||
|
||||
NDBGL4(L4_IAVCDBG, "iavc%d: command = 0x%02x", sc->sc_unit, cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case RECEIVE_DATA_B3_IND:
|
||||
iavc_receive(sc, dmabuf, TRUE);
|
||||
break;
|
||||
|
||||
case RECEIVE_MESSAGE:
|
||||
iavc_receive(sc, dmabuf, FALSE);
|
||||
break;
|
||||
|
||||
case RECEIVE_NEW_NCCI:
|
||||
iavc_receive_new_ncci(sc, dmabuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_FREE_NCCI:
|
||||
iavc_receive_free_ncci(sc, dmabuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_START:
|
||||
iavc_receive_start(sc, dmabuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_STOP:
|
||||
iavc_receive_stop(sc, dmabuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_INIT:
|
||||
iavc_receive_init(sc, dmabuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_TASK_READY:
|
||||
iavc_receive_task_ready(sc, dmabuf);
|
||||
break;
|
||||
|
||||
case RECEIVE_DEBUGMSG:
|
||||
iavc_receive_debugmsg(sc, dmabuf);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("iavc%d: unknown msg %02x\n", sc->sc_unit, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void iavc_start_tx(iavc_softc_t *sc)
|
||||
{
|
||||
struct mbuf *m;
|
||||
u_int8_t *dmabuf;
|
||||
u_int32_t txlen = 0;
|
||||
|
||||
/* If device has put us on hold, punt. */
|
||||
|
||||
if (sc->sc_blocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If using DMA and transmitter busy, punt. */
|
||||
|
||||
if (sc->sc_dma && (sc->sc_csr & EN_TX_TC_INT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Else, see if we have messages to send. */
|
||||
|
||||
_IF_DEQUEUE(&sc->sc_txq, m);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Have message, will send. */
|
||||
|
||||
if (CAPIMSG_LEN(m->m_data)) {
|
||||
/* A proper CAPI message, possibly with B3 data */
|
||||
|
||||
if (sc->sc_dma) {
|
||||
/* Copy message to DMA buffer. */
|
||||
|
||||
if (m->m_next) {
|
||||
dmabuf = amcc_put_byte(&sc->sc_sendbuf[0], SEND_DATA_B3_REQ);
|
||||
} else {
|
||||
dmabuf = amcc_put_byte(&sc->sc_sendbuf[0], SEND_MESSAGE);
|
||||
}
|
||||
|
||||
dmabuf = amcc_put_word(dmabuf, m->m_len);
|
||||
bcopy(m->m_data, dmabuf, m->m_len);
|
||||
dmabuf += m->m_len;
|
||||
txlen = 5 + m->m_len;
|
||||
|
||||
if (m->m_next) {
|
||||
dmabuf = amcc_put_word(dmabuf, m->m_next->m_len);
|
||||
bcopy(m->m_next->m_data, dmabuf, m->m_next->m_len);
|
||||
txlen += 4 + m->m_next->m_len;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Use PIO. */
|
||||
|
||||
if (m->m_next) {
|
||||
iavc_put_byte(sc, SEND_DATA_B3_REQ);
|
||||
NDBGL4(L4_IAVCDBG, "iavc%d: tx SDB3R msg, len = %d", sc->sc_unit, m->m_len);
|
||||
} else {
|
||||
iavc_put_byte(sc, SEND_MESSAGE);
|
||||
NDBGL4(L4_IAVCDBG, "iavc%d: tx SM msg, len = %d", sc->sc_unit, m->m_len);
|
||||
}
|
||||
#if 0
|
||||
{
|
||||
u_int8_t *p = mtod(m, u_int8_t*);
|
||||
int len;
|
||||
for (len = 0; len < m->m_len; len++) {
|
||||
printf(" %02x", *p++);
|
||||
if (len && (len % 16) == 0) printf("\n");
|
||||
}
|
||||
if (len % 16) printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
iavc_put_slice(sc, m->m_data, m->m_len);
|
||||
|
||||
if (m->m_next) {
|
||||
iavc_put_slice(sc, m->m_next->m_data, m->m_next->m_len);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* A board control message to be sent as is */
|
||||
|
||||
if (sc->sc_dma) {
|
||||
bcopy(m->m_data + 2, &sc->sc_sendbuf[0], m->m_len - 2);
|
||||
txlen = m->m_len - 2;
|
||||
|
||||
} else {
|
||||
#if 0
|
||||
{
|
||||
u_int8_t *p = mtod(m, u_int8_t*) + 2;
|
||||
int len;
|
||||
printf("iavc%d: tx BDC msg, len = %d, msg =", sc->sc_unit, m->m_len-2);
|
||||
for (len = 0; len < m->m_len-2; len++) {
|
||||
printf(" %02x", *p++);
|
||||
if (len && (len % 16) == 0) printf("\n");
|
||||
}
|
||||
if (len % 16) printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
txlen = m->m_len - 2;
|
||||
dmabuf = mtod(m, char*) + 2;
|
||||
while(txlen--)
|
||||
b1io_put_byte(sc, *dmabuf++);
|
||||
}
|
||||
}
|
||||
|
||||
if (m->m_next) {
|
||||
i4b_Bfreembuf(m->m_next);
|
||||
m->m_next = NULL;
|
||||
}
|
||||
i4b_Dfreembuf(m);
|
||||
|
||||
if (sc->sc_dma) {
|
||||
/* Start transmitter */
|
||||
|
||||
txlen = (txlen + 3) & ~3;
|
||||
AMCC_WRITE(sc, AMCC_TXPTR, vtophys(&sc->sc_sendbuf[0]));
|
||||
AMCC_WRITE(sc, AMCC_TXLEN, txlen);
|
||||
sc->sc_csr |= EN_TX_TC_INT;
|
||||
|
||||
if (!sc->sc_intr)
|
||||
AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
283
sys/i4b/capi/iavc/iavc_pci.c
Normal file
283
sys/i4b/capi/iavc/iavc_pci.c
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* capi/iavc/iavc_pci.c
|
||||
* The AVM ISDN controllers' PCI bus attachment handling.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "iavc.h"
|
||||
#include "i4bcapi.h"
|
||||
#include "pci.h"
|
||||
|
||||
#if (NIAVC > 0) && (NI4BCAPI > 0) && (NPCI > 0)
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <pci/pcireg.h>
|
||||
#include <pci/pcivar.h>
|
||||
|
||||
#include <machine/i4b_debug.h>
|
||||
#include <machine/i4b_ioctl.h>
|
||||
#include <machine/i4b_trace.h>
|
||||
|
||||
#include <i4b/include/i4b_global.h>
|
||||
#include <i4b/include/i4b_l3l4.h>
|
||||
#include <i4b/include/i4b_mbuf.h>
|
||||
|
||||
#include <i4b/capi/capi.h>
|
||||
|
||||
#include <i4b/capi/iavc/iavc.h>
|
||||
|
||||
/* PCI device ids */
|
||||
|
||||
#define PCI_AVM_VID 0x1244
|
||||
#define PCI_AVMT1_DID 0x1200
|
||||
#define PCI_AVMB1_DID 0x0700
|
||||
|
||||
/* PCI driver linkage */
|
||||
|
||||
static void iavc_pci_intr(iavc_softc_t *sc);
|
||||
static int iavc_pci_probe(device_t dev);
|
||||
static int iavc_pci_attach(device_t dev);
|
||||
|
||||
static device_method_t iavc_pci_methods[] =
|
||||
{
|
||||
DEVMETHOD(device_probe, iavc_pci_probe),
|
||||
DEVMETHOD(device_attach, iavc_pci_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t iavc_pci_driver =
|
||||
{
|
||||
"iavc",
|
||||
iavc_pci_methods,
|
||||
0
|
||||
};
|
||||
|
||||
static devclass_t iavc_pci_devclass;
|
||||
|
||||
DRIVER_MODULE(iavc, pci, iavc_pci_driver, iavc_pci_devclass, 0, 0);
|
||||
|
||||
/* Driver soft contexts */
|
||||
|
||||
iavc_softc_t iavc_sc[IAVC_MAXUNIT];
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
iavc_pci_probe(device_t dev)
|
||||
{
|
||||
u_int16_t did = pci_get_device(dev);
|
||||
u_int16_t vid = pci_get_vendor(dev);
|
||||
|
||||
if ((vid == PCI_AVM_VID) && (did == PCI_AVMT1_DID)) {
|
||||
device_set_desc(dev, "AVM T1 PCI");
|
||||
} else if ((vid == PCI_AVM_VID) && (did == PCI_AVMB1_DID)) {
|
||||
device_set_desc(dev, "AVM B1 PCI");
|
||||
} else {
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
iavc_pci_attach(device_t dev)
|
||||
{
|
||||
struct iavc_softc *sc;
|
||||
void *ih = 0;
|
||||
u_int16_t did = pci_get_device(dev);
|
||||
int unit = device_get_unit(dev), ret;
|
||||
|
||||
/* check max unit range */
|
||||
|
||||
if (unit >= IAVC_MAXUNIT) {
|
||||
printf("iavc%d: too many units\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
sc = iavc_find_sc(unit); /* get softc */
|
||||
|
||||
sc->sc_unit = unit;
|
||||
|
||||
/* use the i/o mapped base address */
|
||||
|
||||
sc->sc_resources.io_rid[0] = 0x14;
|
||||
|
||||
if (!(sc->sc_resources.io_base[0] =
|
||||
bus_alloc_resource(dev, SYS_RES_IOPORT,
|
||||
&sc->sc_resources.io_rid[0],
|
||||
0UL, ~0UL, 1, RF_ACTIVE))) {
|
||||
printf("iavc%d: can't allocate io region\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
sc->sc_iobase = rman_get_start(sc->sc_resources.io_base[0]);
|
||||
sc->sc_io_bt = rman_get_bustag(sc->sc_resources.io_base[0]);
|
||||
sc->sc_io_bh = rman_get_bushandle(sc->sc_resources.io_base[0]);
|
||||
|
||||
/* use the memory mapped DMA controller */
|
||||
|
||||
sc->sc_resources.mem_rid = 0x10;
|
||||
|
||||
if (!(sc->sc_resources.mem =
|
||||
bus_alloc_resource(dev, SYS_RES_MEMORY,
|
||||
&sc->sc_resources.mem_rid,
|
||||
0UL, ~0UL, 1, RF_ACTIVE))) {
|
||||
printf("iavc%d: can't allocate memory region\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
sc->sc_membase = rman_get_start(sc->sc_resources.mem);
|
||||
sc->sc_mem_bt = rman_get_bustag(sc->sc_resources.mem);
|
||||
sc->sc_mem_bh = rman_get_bushandle(sc->sc_resources.mem);
|
||||
|
||||
/* do some detection */
|
||||
|
||||
sc->sc_t1 = FALSE;
|
||||
sc->sc_dma = FALSE;
|
||||
b1dma_reset(sc);
|
||||
|
||||
if (did == PCI_AVMT1_DID) {
|
||||
sc->sc_capi.card_type = CARD_TYPEC_AVM_T1_PCI;
|
||||
sc->sc_capi.sc_nbch = 30;
|
||||
ret = t1_detect(sc);
|
||||
if (ret) {
|
||||
if (ret < 6) {
|
||||
printf("iavc%d: no card detected?\n", sc->sc_unit);
|
||||
} else {
|
||||
printf("iavc%d: black box not on\n", sc->sc_unit);
|
||||
}
|
||||
return(ENXIO);
|
||||
} else {
|
||||
sc->sc_dma = TRUE;
|
||||
sc->sc_t1 = TRUE;
|
||||
}
|
||||
|
||||
} else if (did == PCI_AVMB1_DID) {
|
||||
sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_PCI;
|
||||
sc->sc_capi.sc_nbch = 2;
|
||||
ret = b1dma_detect(sc);
|
||||
if (ret) {
|
||||
ret = b1_detect(sc);
|
||||
if (ret) {
|
||||
printf("iavc%d: no card detected?\n", sc->sc_unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
} else {
|
||||
sc->sc_dma = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->sc_dma) b1dma_reset(sc);
|
||||
#if 0
|
||||
if (sc->sc_t1) t1_reset(sc);
|
||||
else b1_reset(sc);
|
||||
#endif
|
||||
|
||||
/* of course we need an interrupt */
|
||||
|
||||
sc->sc_resources.irq_rid = 0x00;
|
||||
|
||||
if(!(sc->sc_resources.irq =
|
||||
bus_alloc_resource(dev, SYS_RES_IRQ,
|
||||
&sc->sc_resources.irq_rid,
|
||||
0UL, ~0UL, 1, RF_SHAREABLE|RF_ACTIVE))) {
|
||||
printf("iavc%d: can't allocate irq\n",unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
/* finalize our own context */
|
||||
|
||||
memset(&sc->sc_txq, 0, sizeof(struct ifqueue));
|
||||
sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4;
|
||||
|
||||
#if defined (__FreeBSD__) && __FreeBSD__ > 4
|
||||
mtx_init(&sc->sc_txq.ifq_mtx, "i4b_ivac_pci", MTX_DEF);
|
||||
#endif
|
||||
|
||||
sc->sc_intr = FALSE;
|
||||
sc->sc_state = IAVC_DOWN;
|
||||
sc->sc_blocked = FALSE;
|
||||
|
||||
/* setup capi link */
|
||||
|
||||
sc->sc_capi.load = iavc_load;
|
||||
sc->sc_capi.reg_appl = iavc_register;
|
||||
sc->sc_capi.rel_appl = iavc_release;
|
||||
sc->sc_capi.send = iavc_send;
|
||||
sc->sc_capi.ctx = (void*) sc;
|
||||
|
||||
if (capi_ll_attach(&sc->sc_capi)) {
|
||||
printf("iavc%d: capi attach failed\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
/* setup the interrupt */
|
||||
|
||||
if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
|
||||
(void(*)(void*))iavc_pci_intr,
|
||||
sc, &ih)) {
|
||||
printf("iavc%d: irq setup failed\n", unit);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
/* the board is now ready to be loaded */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* IRQ handler
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
iavc_pci_intr(struct iavc_softc *sc)
|
||||
{
|
||||
iavc_handle_intr(sc);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
|
||||
* Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -27,11 +27,9 @@
|
||||
* i4b_debug.h - i4b debug header file
|
||||
* -----------------------------------
|
||||
*
|
||||
* $Id: i4b_debug.h,v 1.32 2000/07/24 12:22:08 hm Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Wed Oct 18 09:48:16 2000]
|
||||
* last edit-date: [Mon May 21 10:05:34 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -169,13 +167,12 @@ extern unsigned int i4b_l4_debug;
|
||||
#define L4_RBCHDBG 0x0020 /* rbch driver debug messages */
|
||||
#define L4_ISPDBG 0x0040 /* isp driver debug messages */
|
||||
#define L4_TELDBG 0x0080 /* tel driver debug messages */
|
||||
#define L4_TINADBG 0x0100 /* tina driver debug messages */
|
||||
#define L4_TINAMSG 0x0200 /* tina driver messages */
|
||||
#define L4_TINAERR 0x0400 /* tina driver error messages */
|
||||
#define L4_INGDBG 0x0800 /* ing driver debug messages */
|
||||
#define L4_INGDBG 0x0100 /* ing driver debug messages */
|
||||
#define L4_IAVCDBG 0x0200 /* AVM B1 driver debug messages */
|
||||
#define L4_CAPIDBG 0x0400 /* CAPI driver debug messages */
|
||||
|
||||
#define L4_DEBUG_MAX 0x0fff /* all messages on */
|
||||
#define L4_DEBUG_ERR (L4_ERR | L4_TINADBG | L4_TINAMSG | L4_TINAERR)
|
||||
#define L4_DEBUG_ERR L4_ERR
|
||||
|
||||
#ifndef L4_DEBUG_DEFAULT
|
||||
#ifdef DO_I4B_MAXDEBUG
|
||||
|
@ -29,7 +29,7 @@
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Fri Jan 26 13:46:50 2001]
|
||||
* last edit-date: [Fri May 25 10:04:37 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -45,9 +45,9 @@
|
||||
/*---------------------------------------------------------------------------*
|
||||
* version and release number for isdn4bsd package
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define VERSION 0 /* version number */
|
||||
#define REL 96 /* release number */
|
||||
#define STEP 3 /* release step */
|
||||
#define VERSION 1 /* version number */
|
||||
#define REL 0 /* release number */
|
||||
#define STEP 0 /* release step */
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* date/time format in i4b log messages
|
||||
@ -82,7 +82,8 @@
|
||||
#define CTRL_DAIC 2 /* Diehl active controller cards*/
|
||||
#define CTRL_TINADD 3 /* Stollmann Tina-dd active card*/
|
||||
#define CTRL_AVMB1 4 /* AVM B1 active card */
|
||||
#define CTRL_NUMTYPES 5 /* number of controller types */
|
||||
#define CTRL_CAPI 5 /* cards seen via the CAPI layer*/
|
||||
#define CTRL_NUMTYPES 6 /* number of controller types */
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* CTRL_PASSIVE: driver types
|
||||
@ -155,6 +156,14 @@
|
||||
#define CARD_TYPEA_DAIC_SCOM 3
|
||||
#define CARD_TYPEA_DAIC_QUAD 4
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* card types for CTRL_CAPI
|
||||
*---------------------------------------------------------------------------*/
|
||||
#define CARD_TYPEC_CAPI_UNK 0
|
||||
#define CARD_TYPEC_AVM_T1_PCI 1
|
||||
#define CARD_TYPEC_AVM_B1_PCI 2
|
||||
#define CARD_TYPEC_AVM_B1_ISA 3
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* max length of some strings
|
||||
*---------------------------------------------------------------------------*/
|
||||
@ -592,6 +601,7 @@ typedef struct {
|
||||
int ctrl_type; /* controller type passive/active */
|
||||
int card_type; /* brand / version */
|
||||
int tei; /* tei controller probably has */
|
||||
int nbch; /* number of b channels provided */
|
||||
} msg_ctrl_info_req_t;
|
||||
|
||||
#define I4B_CTRL_INFO_REQ _IOWR('4', 4, msg_ctrl_info_req_t)
|
||||
|
@ -46,7 +46,8 @@
|
||||
#define T313VAL (hz*4) /* 4 seconds timeout */
|
||||
#define T400DEF (hz*10) /* 10 seconds timeout */
|
||||
|
||||
#define N_CALL_DESC (MAX_CONTROLLERS*2) /* no of call descriptors */
|
||||
#define MAX_BCHAN 30
|
||||
#define N_CALL_DESC (MAX_CONTROLLERS*MAX_BCHAN) /* no of call descriptors */
|
||||
|
||||
extern int nctrl; /* number of controllers detected in system */
|
||||
|
||||
@ -263,7 +264,8 @@ typedef struct
|
||||
#define DL_DOWN 0
|
||||
#define DL_UP 1
|
||||
|
||||
int bch_state[2]; /* states of the b channels */
|
||||
int nbch; /* number of b channels */
|
||||
int bch_state[MAX_BCHAN]; /* states of the b channels */
|
||||
#define BCH_ST_FREE 0 /* free to be used, idle */
|
||||
#define BCH_ST_RSVD 1 /* reserved, may become free or used */
|
||||
#define BCH_ST_USED 2 /* in use for data transfer */
|
||||
|
@ -218,7 +218,7 @@ struct l3state_tab {
|
||||
/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */
|
||||
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/*EV_DLESTIN*/ {{F_ILL, ST_ILL}, {F_DLEI, ST_U1}, {F_DLEI, ST_U3}, {F_DLEI, ST_U4}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
|
||||
/*EV_DLRELIN*/ {{F_NCNA, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRIA,ST_U10}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
|
||||
/*EV_DLRELIN*/ {{F_NCNA, ST_U0}, {F_DLRIA, ST_OW}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRIA,ST_U10}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
|
||||
/*EV_DLESTCF*/ {{F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF2,ST_U8}, {F_DECF3,ST_U0}, {F_DECF1,ST_U1}, {F_DECF4,ST_U7}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
|
||||
/*EV_DLRELCF*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}},
|
||||
/*EV_ILL */ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}
|
||||
@ -280,21 +280,25 @@ char *print_l3state(call_desc_t *cd)
|
||||
*---------------------------------------------------------------------------*/
|
||||
static void F_00A(call_desc_t *cd)
|
||||
{
|
||||
int s;
|
||||
NDBGL3(L3_F_MSG, "FSM function F_00A executing");
|
||||
|
||||
cd->T303_first_to = 1;
|
||||
T303_start(cd);
|
||||
|
||||
s = SPLI4B();
|
||||
if(i4b_get_dl_stat(cd) == DL_DOWN)
|
||||
{
|
||||
splx(s);
|
||||
DL_Est_Req(ctrl_desc[cd->controller].unit);
|
||||
cd->Q931state = ST_OW;
|
||||
}
|
||||
else
|
||||
{
|
||||
i4b_l3_tx_setup(cd);
|
||||
cd->Q931state = ST_U1;
|
||||
splx(s);
|
||||
i4b_l3_tx_setup(cd);
|
||||
}
|
||||
|
||||
cd->T303_first_to = 1;
|
||||
T303_start(cd);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
|
@ -113,8 +113,10 @@ i4b_mdl_status_ind(int unit, int status, int parm)
|
||||
/* state fields */
|
||||
|
||||
ctrl_desc[nctrl].dl_est = DL_DOWN;
|
||||
ctrl_desc[nctrl].bch_state[CHAN_B1] = BCH_ST_FREE;
|
||||
ctrl_desc[nctrl].bch_state[CHAN_B2] = BCH_ST_FREE;
|
||||
ctrl_desc[nctrl].nbch = 2; /* XXX extra param? */
|
||||
for (i = 0; i < ctrl_desc[nctrl].nbch; i++)
|
||||
ctrl_desc[nctrl].bch_state[i] = BCH_ST_FREE;
|
||||
|
||||
ctrl_desc[nctrl].tei = -1;
|
||||
|
||||
/* init unit to controller table */
|
||||
@ -160,8 +162,8 @@ i4b_mdl_status_ind(int unit, int status, int parm)
|
||||
}
|
||||
|
||||
ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
|
||||
for (i = 0; i < ctrl_desc[utoc_tab[unit]].nbch; i++)
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[i] = BCH_ST_FREE;
|
||||
ctrl_desc[utoc_tab[unit]].tei = -1;
|
||||
|
||||
if(sendup)
|
||||
@ -189,8 +191,8 @@ i4b_mdl_status_ind(int unit, int status, int parm)
|
||||
}
|
||||
|
||||
ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
|
||||
for (i = 0; i < ctrl_desc[utoc_tab[unit]].nbch; i++)
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[i] = BCH_ST_FREE;
|
||||
ctrl_desc[utoc_tab[unit]].tei = -1;
|
||||
break;
|
||||
|
||||
@ -224,8 +226,8 @@ n_mgmt_command(int unit, int cmd, void *parm)
|
||||
}
|
||||
|
||||
ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN;
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE;
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE;
|
||||
for (i = 0; i < ctrl_desc[utoc_tab[unit]].nbch; i++)
|
||||
ctrl_desc[utoc_tab[unit]].bch_state[i] = BCH_ST_FREE;
|
||||
ctrl_desc[utoc_tab[unit]].tei = -1;
|
||||
break;
|
||||
|
||||
@ -299,7 +301,7 @@ n_connect_response(u_int cdid, int response, int cause)
|
||||
break;
|
||||
}
|
||||
|
||||
if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
|
||||
if((cd->channelid >= 0) && (cd->channelid < ctrl_desc[cd->controller].nbch))
|
||||
{
|
||||
ctrl_desc[cd->controller].bch_state[cd->channelid] = chstate;
|
||||
}
|
||||
|
@ -453,9 +453,16 @@ i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
|
||||
break;
|
||||
|
||||
case CHAN_ANY:
|
||||
if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) &&
|
||||
(ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE))
|
||||
{
|
||||
int i;
|
||||
for (i = 0;
|
||||
i < ctrl_desc[mcr->controller].nbch &&
|
||||
ctrl_desc[mcr->controller].bch_state[i] != BCH_ST_FREE;
|
||||
i++);
|
||||
if (i == ctrl_desc[mcr->controller].nbch)
|
||||
SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
|
||||
/* else mcr->channel = i; XXX */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -560,6 +567,8 @@ i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
|
||||
ctrl_desc[mcir->controller].ctrl_type;
|
||||
mcir->card_type =
|
||||
ctrl_desc[mcir->controller].card_type;
|
||||
mcir->nbch =
|
||||
ctrl_desc[mcir->controller].nbch;
|
||||
|
||||
if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
|
||||
mcir->tei = ctrl_desc[mcir->controller].tei;
|
||||
|
@ -131,7 +131,7 @@ i4b_l4_pdeact(int controller, int numactive)
|
||||
i4b_unlink_bchandrvr(cd);
|
||||
}
|
||||
|
||||
if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
|
||||
if((cd->channelid >= 0) & (cd->channelid < ctrl_desc[cd->controller].nbch))
|
||||
{
|
||||
ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
}
|
||||
@ -438,14 +438,14 @@ i4b_l4_disconnect_ind(call_desc_t *cd)
|
||||
i4b_unlink_bchandrvr(cd);
|
||||
}
|
||||
|
||||
if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
|
||||
if((cd->channelid >= 0) && (cd->channelid < ctrl_desc[cd->controller].nbch))
|
||||
{
|
||||
ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no error, might be hunting call for callback */
|
||||
NDBGL4(L4_MSG, "channel free not B1/B2 but %d!", cd->channelid);
|
||||
NDBGL4(L4_MSG, "channel free not valid but %d!", cd->channelid);
|
||||
}
|
||||
|
||||
if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
|
||||
* Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -27,11 +27,9 @@
|
||||
* i4b daemon - compile time configuration header file
|
||||
* ---------------------------------------------------
|
||||
*
|
||||
* $Id: config.h,v 1.8 1999/12/13 21:25:24 hm Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Mon Dec 13 21:45:27 1999]
|
||||
* last edit-date: [Mon May 21 11:21:15 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -41,7 +39,7 @@
|
||||
/* general values */
|
||||
|
||||
#define UMASK 022 /* file creation perm mask */
|
||||
#define CFG_ENTRY_MAX 32 /* max no of config entries */
|
||||
#define CFG_ENTRY_MAX 60 /* max no of config entries */
|
||||
#define ISDN_CTRL_MAX 4 /* max no of controllers */
|
||||
#define MAX_RE 8 /* max regular expression entries */
|
||||
|
||||
|
@ -29,14 +29,17 @@
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Fri Jan 26 14:00:10 2001]
|
||||
* last edit-date: [Sun May 20 10:03:53 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "isdnd.h"
|
||||
|
||||
static int
|
||||
init_controller_state(int controller, int ctrl_type, int card_type, int tei);
|
||||
init_controller_state(int controller, int ctrl_type, int card_type, int tei, int nbch);
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* get name of a controller
|
||||
@ -84,6 +87,12 @@ name_of_controller(int ctrl_type, int card_type)
|
||||
"EICON.Diehl QUADRO",
|
||||
};
|
||||
|
||||
static char *capi_card[] = {
|
||||
"AVM T1 PCI",
|
||||
"AVM B1 PCI",
|
||||
"AVM B1 ISA",
|
||||
};
|
||||
|
||||
if(ctrl_type == CTRL_PASSIVE)
|
||||
{
|
||||
int index = card_type - CARD_TYPEP_8;
|
||||
@ -100,6 +109,12 @@ name_of_controller(int ctrl_type, int card_type)
|
||||
{
|
||||
return "Stollmann tina-dd";
|
||||
}
|
||||
else if(ctrl_type == CTRL_CAPI)
|
||||
{
|
||||
int index = card_type - CARD_TYPEC_AVM_T1_PCI;
|
||||
if (index >= 0 && index < (sizeof capi_card / sizeof capi_card[0] ))
|
||||
return capi_card[index];
|
||||
}
|
||||
|
||||
return "unknown card type";
|
||||
}
|
||||
@ -138,7 +153,7 @@ init_controller(void)
|
||||
|
||||
/* init controller tab */
|
||||
|
||||
if((init_controller_state(i, mcir.ctrl_type, mcir.card_type, mcir.tei)) == ERROR)
|
||||
if((init_controller_state(i, mcir.ctrl_type, mcir.card_type, mcir.tei, mcir.nbch)) == ERROR)
|
||||
{
|
||||
log(LL_ERR, "init_controller: init_controller_state for controller %d failed", i);
|
||||
do_exit(1);
|
||||
@ -151,8 +166,11 @@ init_controller(void)
|
||||
* init controller state table entry
|
||||
*--------------------------------------------------------------------------*/
|
||||
static int
|
||||
init_controller_state(int controller, int ctrl_type, int card_type, int tei)
|
||||
init_controller_state(int controller, int ctrl_type, int card_type, int tei,
|
||||
int nbch)
|
||||
{
|
||||
int i;
|
||||
|
||||
if((controller < 0) || (controller >= ncontroller))
|
||||
{
|
||||
log(LL_ERR, "init_controller_state: invalid controller number [%d]!", controller);
|
||||
@ -161,57 +179,49 @@ init_controller_state(int controller, int ctrl_type, int card_type, int tei)
|
||||
|
||||
/* init controller tab */
|
||||
|
||||
if(ctrl_type == CTRL_PASSIVE)
|
||||
{
|
||||
switch (ctrl_type) {
|
||||
case CTRL_PASSIVE:
|
||||
if((card_type > CARD_TYPEP_UNK) &&
|
||||
(card_type <= CARD_TYPEP_MAX))
|
||||
{
|
||||
isdn_ctrl_tab[controller].ctrl_type = ctrl_type;
|
||||
isdn_ctrl_tab[controller].card_type = card_type;
|
||||
isdn_ctrl_tab[controller].state = CTRL_UP;
|
||||
isdn_ctrl_tab[controller].stateb1 = CHAN_IDLE;
|
||||
isdn_ctrl_tab[controller].stateb2 = CHAN_IDLE;
|
||||
isdn_ctrl_tab[controller].freechans = MAX_CHANCTRL;
|
||||
isdn_ctrl_tab[controller].tei = tei;
|
||||
isdn_ctrl_tab[controller].l1stat = LAYER_IDLE;
|
||||
isdn_ctrl_tab[controller].l2stat = LAYER_IDLE;
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "init_controller_state: controller %d is %s",
|
||||
controller,
|
||||
name_of_controller(isdn_ctrl_tab[controller].ctrl_type,
|
||||
isdn_ctrl_tab[controller].card_type))));
|
||||
}
|
||||
else
|
||||
{
|
||||
log(LL_ERR, "init_controller_state: unknown card type %d", card_type);
|
||||
return(ERROR);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
else if(ctrl_type == CTRL_DAIC)
|
||||
{
|
||||
case CTRL_DAIC:
|
||||
isdn_ctrl_tab[controller].ctrl_type = ctrl_type;
|
||||
isdn_ctrl_tab[controller].card_type = card_type;
|
||||
isdn_ctrl_tab[controller].state = CTRL_DOWN;
|
||||
isdn_ctrl_tab[controller].stateb1 = CHAN_IDLE;
|
||||
isdn_ctrl_tab[controller].stateb2 = CHAN_IDLE;
|
||||
isdn_ctrl_tab[controller].freechans = MAX_CHANCTRL;
|
||||
isdn_ctrl_tab[controller].tei = tei;
|
||||
isdn_ctrl_tab[controller].l1stat = LAYER_IDLE;
|
||||
isdn_ctrl_tab[controller].l2stat = LAYER_IDLE;
|
||||
break;
|
||||
|
||||
log(LL_DMN, "init_controller_state: controller %d is %s",
|
||||
controller,
|
||||
name_of_controller(isdn_ctrl_tab[controller].ctrl_type,
|
||||
isdn_ctrl_tab[controller].card_type));
|
||||
}
|
||||
else if(ctrl_type == CTRL_TINADD)
|
||||
{
|
||||
case CTRL_TINADD:
|
||||
isdn_ctrl_tab[controller].ctrl_type = ctrl_type;
|
||||
isdn_ctrl_tab[controller].card_type = 0;
|
||||
isdn_ctrl_tab[controller].state = CTRL_DOWN;
|
||||
isdn_ctrl_tab[controller].stateb1 = CHAN_IDLE;
|
||||
isdn_ctrl_tab[controller].stateb2 = CHAN_IDLE;
|
||||
isdn_ctrl_tab[controller].freechans = MAX_CHANCTRL;
|
||||
break;
|
||||
|
||||
case CTRL_CAPI:
|
||||
isdn_ctrl_tab[controller].ctrl_type = ctrl_type;
|
||||
isdn_ctrl_tab[controller].card_type = card_type;
|
||||
isdn_ctrl_tab[controller].state = CTRL_UP;
|
||||
break;
|
||||
|
||||
default:
|
||||
log(LL_ERR, "init_controller_state: unknown controller type %d", ctrl_type);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
isdn_ctrl_tab[controller].nbch = nbch;
|
||||
isdn_ctrl_tab[controller].freechans = nbch;
|
||||
for (i = 0; i < nbch; i++)
|
||||
isdn_ctrl_tab[controller].stateb[i] = CHAN_IDLE;
|
||||
isdn_ctrl_tab[controller].tei = tei;
|
||||
isdn_ctrl_tab[controller].l1stat = LAYER_IDLE;
|
||||
isdn_ctrl_tab[controller].l2stat = LAYER_IDLE;
|
||||
@ -221,17 +231,11 @@ init_controller_state(int controller, int ctrl_type, int card_type, int tei)
|
||||
name_of_controller(isdn_ctrl_tab[controller].ctrl_type,
|
||||
isdn_ctrl_tab[controller].card_type));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
log(LL_ERR, "init_controller_state: unknown controller type %d", ctrl_type);
|
||||
return(ERROR);
|
||||
}
|
||||
return(GOOD);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* init active controller
|
||||
* init active or capi controller
|
||||
*--------------------------------------------------------------------------*/
|
||||
void
|
||||
init_active_controller(void)
|
||||
@ -255,6 +259,54 @@ init_active_controller(void)
|
||||
do_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic microcode loading. If a controller has
|
||||
* defined a microcode file, load it using the
|
||||
* I4B_CTRL_DOWNLOAD ioctl.
|
||||
*/
|
||||
|
||||
if(isdn_ctrl_tab[controller].firmware != NULL)
|
||||
{
|
||||
int fd, ret;
|
||||
struct isdn_dr_prot idp;
|
||||
struct isdn_download_request idr;
|
||||
|
||||
fd = open(isdn_ctrl_tab[controller].firmware, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
log(LL_ERR, "init_active_controller %d: open %s: %s!",
|
||||
controller, isdn_ctrl_tab[controller].firmware,
|
||||
strerror(errno));
|
||||
do_exit(1);
|
||||
}
|
||||
|
||||
idp.bytecount = lseek(fd, 0, SEEK_END);
|
||||
idp.microcode = mmap(0, idp.bytecount, PROT_READ,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (idp.microcode == MAP_FAILED) {
|
||||
log(LL_ERR, "init_active_controller %d: mmap %s: %s!",
|
||||
controller, isdn_ctrl_tab[controller].firmware,
|
||||
strerror(errno));
|
||||
do_exit(1);
|
||||
}
|
||||
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "init_active_controller %d: loading firmware from [%s]", controller, isdn_ctrl_tab[controller].firmware)));
|
||||
|
||||
idr.controller = controller;
|
||||
idr.numprotos = 1;
|
||||
idr.protocols = &idp;
|
||||
|
||||
ret = ioctl(isdnfd, I4B_CTRL_DOWNLOAD, &idr, sizeof(idr));
|
||||
if (ret) {
|
||||
log(LL_ERR, "init_active_controller %d: load %s: %s!",
|
||||
controller, isdn_ctrl_tab[controller].firmware,
|
||||
strerror(errno));
|
||||
do_exit(1);
|
||||
}
|
||||
|
||||
munmap(idp.microcode, idp.bytecount);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,7 +411,7 @@ incr_free_channels(int controller)
|
||||
log(LL_ERR, "incr_free_channels: invalid controller number [%d]!", controller);
|
||||
return(ERROR);
|
||||
}
|
||||
if(isdn_ctrl_tab[controller].freechans < MAX_CHANCTRL)
|
||||
if(isdn_ctrl_tab[controller].freechans < isdn_ctrl_tab[controller].nbch)
|
||||
{
|
||||
(isdn_ctrl_tab[controller].freechans)++;
|
||||
DBGL(DL_CNST, (log(LL_DBG, "incr_free_channels: ctrl %d, now %d chan free", controller, isdn_ctrl_tab[controller].freechans)));
|
||||
@ -367,7 +419,7 @@ incr_free_channels(int controller)
|
||||
}
|
||||
else
|
||||
{
|
||||
log(LL_ERR, "incr_free_channels: controller [%d] already 2 free chans!", controller);
|
||||
log(LL_ERR, "incr_free_channels: controller [%d] already %d free chans!", controller, isdn_ctrl_tab[controller].nbch);
|
||||
return(ERROR);
|
||||
}
|
||||
}
|
||||
@ -399,36 +451,20 @@ set_channel_busy(int controller, int channel)
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
switch(channel)
|
||||
{
|
||||
case CHAN_B1:
|
||||
if(isdn_ctrl_tab[controller].stateb1 == CHAN_RUN)
|
||||
if ((channel < 0) || (channel >= isdn_ctrl_tab[controller].nbch))
|
||||
{
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B1 already busy!", controller)));
|
||||
log(LL_ERR, "set_channel_busy: controller [%d] invalid channel [%d]!", controller, channel);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if(isdn_ctrl_tab[controller].stateb[channel] == CHAN_RUN)
|
||||
{
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B%d already busy!", controller, channel+1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
isdn_ctrl_tab[controller].stateb1 = CHAN_RUN;
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B1 set to BUSY!", controller)));
|
||||
}
|
||||
break;
|
||||
|
||||
case CHAN_B2:
|
||||
if(isdn_ctrl_tab[controller].stateb2 == CHAN_RUN)
|
||||
{
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B2 already busy!", controller)));
|
||||
}
|
||||
else
|
||||
{
|
||||
isdn_ctrl_tab[controller].stateb2 = CHAN_RUN;
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B2 set to BUSY!", controller)));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log(LL_ERR, "set_channel_busy: controller [%d], invalid channel [%d]!", controller, channel);
|
||||
return(ERROR);
|
||||
break;
|
||||
isdn_ctrl_tab[controller].stateb[channel] = CHAN_RUN;
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B%d set to BUSY!", controller, channel+1)));
|
||||
}
|
||||
return(GOOD);
|
||||
}
|
||||
@ -445,36 +481,20 @@ set_channel_idle(int controller, int channel)
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
switch(channel)
|
||||
{
|
||||
case CHAN_B1:
|
||||
if(isdn_ctrl_tab[controller].stateb1 == CHAN_IDLE)
|
||||
if ((channel < 0) || (channel >= isdn_ctrl_tab[controller].nbch))
|
||||
{
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B1 already idle!", controller)));
|
||||
log(LL_ERR, "set_channel_busy: controller [%d] invalid channel [%d]!", controller, channel);
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
if (isdn_ctrl_tab[controller].stateb[channel] == CHAN_IDLE)
|
||||
{
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B%d already idle!", controller, channel+1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
isdn_ctrl_tab[controller].stateb1 = CHAN_IDLE;
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B1 set to IDLE!", controller)));
|
||||
}
|
||||
break;
|
||||
|
||||
case CHAN_B2:
|
||||
if(isdn_ctrl_tab[controller].stateb2 == CHAN_IDLE)
|
||||
{
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B2 already idle!", controller)));
|
||||
}
|
||||
else
|
||||
{
|
||||
isdn_ctrl_tab[controller].stateb2 = CHAN_IDLE;
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B2 set to IDLE!", controller)));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d], invalid channel [%d]!", controller, channel)));
|
||||
return(ERROR);
|
||||
break;
|
||||
isdn_ctrl_tab[controller].stateb[channel] = CHAN_IDLE;
|
||||
DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B%d set to IDLE!", controller, channel+1)));
|
||||
}
|
||||
return(GOOD);
|
||||
}
|
||||
@ -491,22 +511,13 @@ ret_channel_state(int controller, int channel)
|
||||
return(ERROR);
|
||||
}
|
||||
|
||||
switch(channel)
|
||||
if ((channel < 0) || (channel >= isdn_ctrl_tab[controller].nbch))
|
||||
{
|
||||
case CHAN_B1:
|
||||
return(isdn_ctrl_tab[controller].stateb1);
|
||||
break;
|
||||
|
||||
case CHAN_B2:
|
||||
return(isdn_ctrl_tab[controller].stateb2);
|
||||
break;
|
||||
|
||||
default:
|
||||
log(LL_ERR, "ret_channel_state: controller [%d], invalid channel [%d]!", controller, channel);
|
||||
log(LL_ERR, "set_channel_busy: controller [%d] invalid channel [%d]!", controller, channel);
|
||||
return(ERROR);
|
||||
break;
|
||||
}
|
||||
return(ERROR);
|
||||
|
||||
return(isdn_ctrl_tab[controller].stateb[channel]);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
@ -502,21 +502,23 @@ typedef struct cfg_entry {
|
||||
} cfg_entry_t;
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* this struct describes state of controller with 2 b channels
|
||||
* this struct describes state of controller with MAX_BCHAN b channels
|
||||
*---------------------------------------------------------------------------*/
|
||||
typedef struct isdn_ctrl_state {
|
||||
int ctrl_type; /* type: active/passive */
|
||||
int card_type; /* manufacturer (CARD_XXXX) */
|
||||
int protocol; /* ISDN D-channel protocol */
|
||||
char* firmware; /* loadable fimrware file name */
|
||||
|
||||
int state; /* controller state */
|
||||
#define CTRL_DOWN 0 /* controller inoparable */
|
||||
#define CTRL_UP 1 /* controller may be used */
|
||||
int stateb1; /* B-channel 1 */
|
||||
int stateb2; /* B-channel 2 */
|
||||
#define MAX_BCHAN 30
|
||||
int stateb[MAX_BCHAN]; /* b channel state */
|
||||
#define CHAN_IDLE 0 /* channel is free for usage */
|
||||
#define CHAN_RUN 1 /* channel is occupied */
|
||||
int nbch; /* number of b channels */
|
||||
int freechans; /* number of unused channels */
|
||||
#define MAX_CHANCTRL 2 /* free channels per controller */
|
||||
int tei; /* tei or -1 if invalid */
|
||||
int l1stat; /* layer 1 state */
|
||||
int l2stat; /* layer 2 state */
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
|
||||
.\" Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
@ -22,13 +22,11 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id: isdnd.rc.5,v 1.51 2000/10/09 11:17:07 hm Exp $
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" last edit-date: [Mon Oct 9 13:12:29 2000]
|
||||
.\" last edit-date: [Mon May 21 11:20:26 2001]
|
||||
.\"
|
||||
.Dd October 9, 2000
|
||||
.Dd May 21, 2001
|
||||
.Dt ISDND.RC 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -295,6 +293,16 @@ ITU Recommendations Q.921 and Q.931.
|
||||
.It Ar d64s
|
||||
An ISDN leased line with a single B-channel (called D64S in Germany).
|
||||
.El
|
||||
.It Li firmware
|
||||
This is keyword ist used like firmware=/path/to/file to download the
|
||||
firmware to active controllers supported by the
|
||||
.Em iavc
|
||||
driver (AVM B1, T1). This keyword is supported for all controller types,
|
||||
and causes I4B_CTRL_DOWNLOAD ioctl to be invoked with the specified file
|
||||
as an argument. In systems equipped with both active and passive adapters,
|
||||
and the passive cards being detected first, dummy 'controller' entries
|
||||
are required for the passive cards to get the correct firmwares to
|
||||
correct adapters.
|
||||
.El
|
||||
.It Li entry
|
||||
This keyword starts one configuration entry.
|
||||
@ -380,6 +388,11 @@ and calling back the remote site.
|
||||
The time in seconds to wait for a remote site calling back the local site
|
||||
after a call from the local site to the remote site has been made.
|
||||
(optional)
|
||||
.It Li clone
|
||||
This causes the contents of the specified entry to be copied from the
|
||||
existing named entry to the current one.
|
||||
When using this feature at least a new entry specific 'name' and
|
||||
'usrdeviceunit' value should be specified for the current entry.
|
||||
.It Li connectprog
|
||||
specifies a program run every time after a connection is established and
|
||||
address negotiation is complete (i.e.: the connection is usable).
|
||||
@ -982,7 +995,7 @@ ISDN daemon.
|
||||
The
|
||||
.Xr isdnd 8
|
||||
daemon and this manual page were written by
|
||||
.An Hellmuth Michaelis Aq hm@kts.org .
|
||||
.An Hellmuth Michaelis Aq hm@freebsd.org .
|
||||
.Pp
|
||||
Additions to this manual page by
|
||||
.An Barry Scott Aq barry@scottb.demon.co.uk .
|
||||
|
@ -941,24 +941,21 @@ static void
|
||||
hangup_channel(int controller, int channel, const char *source)
|
||||
{
|
||||
cfg_entry_t * cep = NULL;
|
||||
int i;
|
||||
|
||||
if(controller < ncontroller)
|
||||
{
|
||||
if(isdn_ctrl_tab[controller].state != CTRL_UP)
|
||||
return;
|
||||
if(isdn_ctrl_tab[controller].stateb1 != CHAN_IDLE)
|
||||
for (i = 0; i < isdn_ctrl_tab[controller].nbch; i++)
|
||||
{
|
||||
cep = get_cep_by_cc(controller, 0);
|
||||
if (cep != NULL && cep->isdnchannelused == channel &&
|
||||
cep->isdncontrollerused == controller)
|
||||
goto found;
|
||||
}
|
||||
if(isdn_ctrl_tab[controller].stateb2 != CHAN_IDLE)
|
||||
{
|
||||
cep = get_cep_by_cc(controller, 1);
|
||||
if(isdn_ctrl_tab[controller].stateb[i] != CHAN_IDLE)
|
||||
{
|
||||
cep = get_cep_by_cc(controller, i);
|
||||
if (cep != NULL && cep->isdnchannelused == channel &&
|
||||
cep->isdncontrollerused == controller)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* not found */
|
||||
|
@ -170,6 +170,7 @@ set_config_defaults(void)
|
||||
for(i=0; i < ncontroller; i++)
|
||||
{
|
||||
isdn_ctrl_tab[i].protocol = PROTOCOL_DSS1;
|
||||
isdn_ctrl_tab[i].firmware = NULL;
|
||||
}
|
||||
|
||||
/* entry section cleanup */
|
||||
@ -568,6 +569,42 @@ cfg_setval(int keyword)
|
||||
cfg_entry_tab[entrycount].calledbackwait = yylval.num;
|
||||
break;
|
||||
|
||||
case CLONE:
|
||||
/*
|
||||
* clone = <entryname>
|
||||
* Loads the entry from the named, existing one.
|
||||
* Fields such as name and usrdeviceunit should
|
||||
* always be specified after clone as they must be
|
||||
* unique.
|
||||
*
|
||||
* NOTE: all malloc()'d fields must be dup()'d here,
|
||||
* we can't have multiple references to same storage.
|
||||
*/
|
||||
for (i = 0; i < entrycount; i++)
|
||||
if (!strcmp(cfg_entry_tab[i].name, yylval.str))
|
||||
break;
|
||||
if (i == entrycount) {
|
||||
log(LL_ERR, "entry %d: clone, unknown entry %s!", entrycount, yylval.str);
|
||||
do_exit(1);
|
||||
}
|
||||
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "entry %d: clone = %s", entrycount, yylval.str)));
|
||||
|
||||
memcpy(&cfg_entry_tab[entrycount], &cfg_entry_tab[i],
|
||||
sizeof(cfg_entry_tab[0]));
|
||||
|
||||
if (cfg_entry_tab[entrycount].answerprog)
|
||||
cfg_entry_tab[entrycount].answerprog = strdup(cfg_entry_tab[entrycount].answerprog);
|
||||
if (cfg_entry_tab[entrycount].budget_callbacks_file)
|
||||
cfg_entry_tab[entrycount].budget_callbacks_file = strdup(cfg_entry_tab[entrycount].budget_callbacks_file);
|
||||
if (cfg_entry_tab[entrycount].budget_callouts_file)
|
||||
cfg_entry_tab[entrycount].budget_callouts_file = strdup(cfg_entry_tab[entrycount].budget_callouts_file);
|
||||
if (cfg_entry_tab[entrycount].connectprog)
|
||||
cfg_entry_tab[entrycount].connectprog = strdup(cfg_entry_tab[entrycount].connectprog);
|
||||
if (cfg_entry_tab[entrycount].disconnectprog)
|
||||
cfg_entry_tab[entrycount].disconnectprog = strdup(cfg_entry_tab[entrycount].disconnectprog);
|
||||
break;
|
||||
|
||||
case CONNECTPROG:
|
||||
if((cfg_entry_tab[entrycount].connectprog = malloc(strlen(yylval.str)+1)) == NULL)
|
||||
{
|
||||
@ -657,6 +694,11 @@ cfg_setval(int keyword)
|
||||
extcallattr = yylval.booln;
|
||||
break;
|
||||
|
||||
case FIRMWARE:
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "controller %d: firmware = %s", controllercount, yylval.str)));
|
||||
isdn_ctrl_tab[controllercount].firmware = strdup(yylval.str);
|
||||
break;
|
||||
|
||||
case HOLIDAYFILE:
|
||||
strcpy(holidayfile, yylval.str);
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "system: holidayfile = %s", yylval.str)));
|
||||
@ -696,25 +738,20 @@ cfg_setval(int keyword)
|
||||
break;
|
||||
|
||||
case ISDNCHANNEL:
|
||||
switch(yylval.num)
|
||||
if (yylval.num == 0 || yylval.num == -1)
|
||||
{
|
||||
case 0:
|
||||
case -1:
|
||||
cfg_entry_tab[entrycount].isdnchannel = CHAN_ANY;
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "entry %d: isdnchannel = any", entrycount)));
|
||||
break;
|
||||
case 1:
|
||||
cfg_entry_tab[entrycount].isdnchannel = CHAN_B1;
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "entry %d: isdnchannel = one", entrycount)));
|
||||
break;
|
||||
case 2:
|
||||
cfg_entry_tab[entrycount].isdnchannel = CHAN_B2;
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "entry %d: isdnchannel = two", entrycount)));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
else if (yylval.num > MAX_BCHAN)
|
||||
{
|
||||
log(LL_DBG, "entry %d: isdnchannel value out of range", entrycount);
|
||||
config_error_flag++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg_entry_tab[entrycount].isdnchannel = yylval.num-1;
|
||||
DBGL(DL_RCCF, (log(LL_DBG, "entry %d: isdnchannel = B%d", entrycount, yylval.num)));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1523,11 +1560,8 @@ print_config(void)
|
||||
case CHAN_ANY:
|
||||
fprintf(PFILE, "-1\t\t# any ISDN B-channel may be used\n");
|
||||
break;
|
||||
case CHAN_B1:
|
||||
fprintf(PFILE, "1\t\t# only ISDN B-channel 1 may be used\n");
|
||||
break;
|
||||
case CHAN_B2:
|
||||
fprintf(PFILE, "2\t\t# only ISDN B-channel 2 ay be used\n");
|
||||
default:
|
||||
fprintf(PFILE, "%d\t\t# only ISDN B-channel %d may be used\n", cep->isdnchannel+1, cep->isdnchannel+1);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 1997 Joerg Wunsch. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
|
||||
* Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -30,11 +30,9 @@
|
||||
* i4b daemon - runtime configuration parser
|
||||
* -----------------------------------------
|
||||
*
|
||||
* $Id: rc_parse.y,v 1.30 2000/10/09 11:17:07 hm Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Mon Oct 2 22:51:23 2000]
|
||||
* last edit-date: [Mon May 21 11:22:21 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -94,6 +92,7 @@ int controllercount = -1;
|
||||
%token CALLIN
|
||||
%token CALLOUT
|
||||
%token CHANNELSTATE
|
||||
%token CLONE
|
||||
%token CONNECTPROG
|
||||
%token CONTROLLER
|
||||
%token DIALOUTTYPE
|
||||
@ -106,6 +105,7 @@ int controllercount = -1;
|
||||
%token EARLYHANGUP
|
||||
%token ENTRY
|
||||
%token EXTCALLATTR
|
||||
%token FIRMWARE
|
||||
%token FULLCMD
|
||||
%token HOLIDAYFILE
|
||||
%token IDLETIME_IN
|
||||
@ -170,7 +170,7 @@ int controllercount = -1;
|
||||
|
||||
%type <num> sysfilekeyword sysnumkeyword sysstrkeyword sysboolkeyword
|
||||
%type <num> filekeyword numkeyword strkeyword boolkeyword monrights monright
|
||||
%type <num> cstrkeyword
|
||||
%type <num> cstrkeyword cfilekeyword
|
||||
%type <str> filename
|
||||
|
||||
%union {
|
||||
@ -441,6 +441,7 @@ strkeyword: ANSWERPROG { $$ = ANSWERPROG; }
|
||||
| UNITLENGTHSRC { $$ = UNITLENGTHSRC; }
|
||||
| USRDEVICENAME { $$ = USRDEVICENAME; }
|
||||
| VALID { $$ = VALID; }
|
||||
| CLONE { $$ = CLONE; }
|
||||
;
|
||||
|
||||
numkeyword: ALERT { $$ = ALERT; }
|
||||
@ -502,10 +503,17 @@ strcontroller: cstrkeyword '=' STRING '\n'
|
||||
{
|
||||
cfg_setval($1);
|
||||
}
|
||||
| cfilekeyword '=' filename '\n'
|
||||
{
|
||||
cfg_setval($1);
|
||||
}
|
||||
;
|
||||
|
||||
cstrkeyword: PROTOCOL { $$ = PROTOCOL; }
|
||||
;
|
||||
|
||||
cfilekeyword: FIRMWARE { $$ = FIRMWARE; }
|
||||
;
|
||||
|
||||
|
||||
%%
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 1997 Joerg Wunsch. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
|
||||
* Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -30,11 +30,9 @@
|
||||
* i4b daemon - runtime configuration lexical analyzer
|
||||
* ---------------------------------------------------
|
||||
*
|
||||
* $Id: rc_scan.l,v 1.33 2000/10/09 11:17:07 hm Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Wed Jan 10 10:37:11 2001]
|
||||
* last edit-date: [Mon May 21 11:22:38 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -105,6 +103,7 @@ budget-calloutsfile { return BUDGETCALLOUTSFILE; }
|
||||
budget-calloutsfile-rotate { return BUDGETCALLOUTSFILEROTATE; }
|
||||
callbackwait { return CALLBACKWAIT; }
|
||||
calledbackwait { return CALLEDBACKWAIT; }
|
||||
clone { return CLONE; }
|
||||
connectprog { return CONNECTPROG; }
|
||||
controller { return CONTROLLER; }
|
||||
dialin-reaction { return REACTION; }
|
||||
@ -118,6 +117,7 @@ downtime { return DOWNTIME; }
|
||||
earlyhangup { return EARLYHANGUP; }
|
||||
entry { return ENTRY; }
|
||||
extcallattr { return EXTCALLATTR; }
|
||||
firmware { return FIRMWARE; }
|
||||
holidayfile { return HOLIDAYFILE; }
|
||||
idletime-incoming { return IDLETIME_IN; }
|
||||
idletime-outgoing { return IDLETIME_OUT; }
|
||||
|
@ -230,6 +230,8 @@ find_by_device_for_dialoutnumber(int drivertype, int driverunit, int cmdlen, cha
|
||||
int
|
||||
setup_dialout(cfg_entry_t *cep)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* check controller operational */
|
||||
|
||||
if((get_controller_state(cep->isdncontroller)) != CTRL_UP)
|
||||
@ -244,19 +246,14 @@ setup_dialout(cfg_entry_t *cep)
|
||||
|
||||
switch(cep->isdnchannel)
|
||||
{
|
||||
case CHAN_B1:
|
||||
case CHAN_B2:
|
||||
if((ret_channel_state(cep->isdncontroller, cep->isdnchannel)) != CHAN_IDLE)
|
||||
{
|
||||
DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel not free", cep->name)));
|
||||
return(ERROR);
|
||||
}
|
||||
cep->isdnchannelused = cep->isdnchannel;
|
||||
break;
|
||||
|
||||
case CHAN_ANY:
|
||||
if(((ret_channel_state(cep->isdncontroller, CHAN_B1)) != CHAN_IDLE) &&
|
||||
((ret_channel_state(cep->isdncontroller, CHAN_B2)) != CHAN_IDLE))
|
||||
for (i = 0; i < isdn_ctrl_tab[cep->isdncontroller].nbch; i++)
|
||||
{
|
||||
if(ret_channel_state(cep->isdncontroller, i) == CHAN_IDLE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == isdn_ctrl_tab[cep->isdncontroller].nbch)
|
||||
{
|
||||
DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, no channel free", cep->name)));
|
||||
return(ERROR);
|
||||
@ -265,8 +262,12 @@ setup_dialout(cfg_entry_t *cep)
|
||||
break;
|
||||
|
||||
default:
|
||||
DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel undefined", cep->name)));
|
||||
if((ret_channel_state(cep->isdncontroller, cep->isdnchannel)) != CHAN_IDLE)
|
||||
{
|
||||
DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel not free", cep->name)));
|
||||
return(ERROR);
|
||||
}
|
||||
cep->isdnchannelused = cep->isdnchannel;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -460,19 +461,14 @@ find_matching_entry_incoming(msg_connect_ind_t *mp)
|
||||
|
||||
switch(mp->channel)
|
||||
{
|
||||
case CHAN_B1:
|
||||
case CHAN_B2:
|
||||
if((ret_channel_state(mp->controller, mp->channel)) != CHAN_IDLE)
|
||||
{
|
||||
log(LL_CHD, "%05d %s incoming call, channel %s not free!",
|
||||
mp->header.cdid, cep->name, mp->channel == CHAN_B1 ? "B1" : "B2");
|
||||
return(NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case CHAN_ANY:
|
||||
if(((ret_channel_state(mp->controller, CHAN_B1)) != CHAN_IDLE) &&
|
||||
((ret_channel_state(mp->controller, CHAN_B2)) != CHAN_IDLE))
|
||||
for (i = 0; i < isdn_ctrl_tab[mp->controller].nbch; i++)
|
||||
{
|
||||
if(ret_channel_state(mp->controller, i) == CHAN_IDLE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == isdn_ctrl_tab[mp->controller].nbch)
|
||||
{
|
||||
log(LL_CHD, "%05d %s incoming call, no channel free!",
|
||||
mp->header.cdid, cep->name);
|
||||
@ -487,9 +483,12 @@ find_matching_entry_incoming(msg_connect_ind_t *mp)
|
||||
break;
|
||||
|
||||
default:
|
||||
log(LL_CHD, "%05d %s incoming call, ERROR, channel undefined!",
|
||||
mp->header.cdid, cep->name);
|
||||
if((ret_channel_state(mp->controller, mp->channel)) != CHAN_IDLE)
|
||||
{
|
||||
log(LL_CHD, "%05d %s incoming call, channel B%d not free!",
|
||||
mp->header.cdid, cep->name, mp->channel+1);
|
||||
return(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -569,7 +568,7 @@ get_cep_by_cc(int ctrlr, int chan)
|
||||
{
|
||||
int i;
|
||||
|
||||
if((chan != CHAN_B1) && (chan != CHAN_B2))
|
||||
if((chan < 0) || (chan >= isdn_ctrl_tab[ctrlr].nbch))
|
||||
return(NULL);
|
||||
|
||||
for(i=0; i < nentries; i++)
|
||||
@ -724,7 +723,7 @@ unitlen_chkupd(cfg_entry_t *cep)
|
||||
void
|
||||
close_allactive(void)
|
||||
{
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
cfg_entry_t *cep = NULL;
|
||||
|
||||
j = 0;
|
||||
@ -734,25 +733,11 @@ close_allactive(void)
|
||||
if((get_controller_state(i)) != CTRL_UP)
|
||||
continue;
|
||||
|
||||
if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN)
|
||||
for (k = 0; k < isdn_ctrl_tab[i].nbch; k++)
|
||||
{
|
||||
if((cep = get_cep_by_cc(i, CHAN_B1)) != NULL)
|
||||
if((ret_channel_state(i, k)) == CHAN_RUN)
|
||||
{
|
||||
#ifdef USE_CURSES
|
||||
if(do_fullscreen)
|
||||
display_disconnect(cep);
|
||||
#endif
|
||||
#ifdef I4B_EXTERNAL_MONITOR
|
||||
monitor_evnt_disconnect(cep);
|
||||
#endif
|
||||
next_state(cep, EV_DRQ);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN)
|
||||
{
|
||||
if((cep = get_cep_by_cc(i, CHAN_B2)) != NULL)
|
||||
if((cep = get_cep_by_cc(i, k)) != NULL)
|
||||
{
|
||||
#ifdef USE_CURSES
|
||||
if(do_fullscreen)
|
||||
@ -764,6 +749,7 @@ close_allactive(void)
|
||||
next_state(cep, EV_DRQ);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
|
||||
* Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -27,11 +27,9 @@
|
||||
* main.c - i4b set debug options
|
||||
* ------------------------------
|
||||
*
|
||||
* $Id: main.c,v 1.27 2000/07/24 12:22:08 hm Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
* last edit-date: [Thu Oct 26 08:50:30 2000]
|
||||
* last edit-date: [Mon May 21 10:09:23 2001]
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -617,19 +615,18 @@ void
|
||||
printl4(unsigned long val)
|
||||
{
|
||||
printf("\nLayer 4: %s = 0x%lX\n", bin_str(val, 32), val);
|
||||
printf(" |||| |||| ||||\n"),
|
||||
printf(" |||| |||| |||+- general error messages\n");
|
||||
printf(" |||| |||| ||+-- general messages\n");
|
||||
printf(" |||| |||| |+--- B-ch timeout messages\n");
|
||||
printf(" |||| |||| +---- network driver dial state\n");
|
||||
printf(" |||| |||+------ ipr driver debug messages\n");
|
||||
printf(" |||| ||+------- rbch driver debug messages\n");
|
||||
printf(" |||| |+-------- isp driver debug messages\n");
|
||||
printf(" |||| +--------- tel driver debug messages\n");
|
||||
printf(" |||+----------- tina driver debug messages\n");
|
||||
printf(" ||+------------ tina driver messages\n");
|
||||
printf(" |+------------- tina driver error messages\n");
|
||||
printf(" +-------------- ing driver debug messages\n");
|
||||
printf(" ||| |||| ||||\n"),
|
||||
printf(" ||| |||| |||+- general error messages\n");
|
||||
printf(" ||| |||| ||+-- general messages\n");
|
||||
printf(" ||| |||| |+--- B-ch timeout messages\n");
|
||||
printf(" ||| |||| +---- network driver dial state\n");
|
||||
printf(" ||| |||+------ ipr driver debug messages\n");
|
||||
printf(" ||| ||+------- rbch driver debug messages\n");
|
||||
printf(" ||| |+-------- isp driver debug messages\n");
|
||||
printf(" ||| +--------- tel driver debug messages\n");
|
||||
printf(" ||+----------- ing driver debug messages\n");
|
||||
printf(" |+------------ iavc driver debug messages\n");
|
||||
printf(" +------------- capi driver debug messages\n");
|
||||
printf(" ++++-++++-++++-++++-++++---------------- unassigned\n");
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
# $FreeBSD$
|
||||
MAN = i4b.4 i4bctl.4 i4bipr.4 i4bq921.4 i4bq931.4 i4brbch.4 i4btel.4 \
|
||||
i4btrc.4 isic.4 i4bisppp.4 iwic.4 ifpi.4 ifpnp.4 ihfc.4 itjc.4
|
||||
i4btrc.4 isic.4 i4bisppp.4 iwic.4 ifpi.4 ifpnp.4 ihfc.4 itjc.4 \
|
||||
i4bcapi.4 iavc.4
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
|
55
usr.sbin/i4b/man/i4bcapi.4
Normal file
55
usr.sbin/i4b/man/i4bcapi.4
Normal file
@ -0,0 +1,55 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Hellmuth Michaelis. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" last edit-date: [Fri May 25 09:38:45 2001]
|
||||
.\"
|
||||
.Dd May 21, 2001
|
||||
.Dt I4BCAPI 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm i4bcapi
|
||||
.Nd CAPI driver for the isdn4bsd kernel part
|
||||
.Sh SYNOPSIS
|
||||
.Cd device \&"i4bcapi\&"
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a CAPI driver for the
|
||||
.Em isdn4bsd
|
||||
package. It sits between layer 4 of isdn4bsd and a driver for an active
|
||||
ISDN card; currently only the
|
||||
.Xr iavc 4
|
||||
driver for the AVM B1 and T1 family of active cards is supported.
|
||||
.Sh STANDARDS
|
||||
CAPI 2.0 (http://www.capi.org/)
|
||||
.Sh SEE ALSO
|
||||
.Xr iavc 4
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver was written by
|
||||
.An Juha-Matti Liukkonen (Cubical Solutions Ltd, Finnland) Aq jml@cubical.fi .
|
||||
This manpage was written by
|
||||
.An Hellmuth Michaelis Aq hm@freebsd.org .
|
67
usr.sbin/i4b/man/iavc.4
Normal file
67
usr.sbin/i4b/man/iavc.4
Normal file
@ -0,0 +1,67 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Hellmuth Michaelis. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" last edit-date: [Fri May 25 09:45:35 2001]
|
||||
.\"
|
||||
.Dd May 22, 2001
|
||||
.Dt IAVC 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm iavc
|
||||
.Nd isdn4bsd AVM B1/T1 driver
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device iavc"
|
||||
.Pp
|
||||
NOTE:
|
||||
For the B1 ISA card
|
||||
.Pp
|
||||
.Dl hint.iavc.0.at="isa"
|
||||
.Dl hint.iavc.0.port="0x150"
|
||||
.Dl hint.iavc.0.irq="5"
|
||||
.Pp
|
||||
must be added to
|
||||
.Pa /boot/device.hints
|
||||
.Pp
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver is used to access the AVM family of active cards to the
|
||||
.Xr i4bcapi 4
|
||||
driver and the
|
||||
.Em isdn4bsd
|
||||
package. Currently the AVM B1 PCI, the AVM B1 ISA and the AVM T1 PCI
|
||||
cards are supported.
|
||||
.Sh STANDARDS
|
||||
CAPI 2.0 (http://www.capi.org/)
|
||||
.Sh SEE ALSO
|
||||
.Xr i4bcapi 4
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
device driver was written by
|
||||
.An Juha-Matti Liukkonen (Cubical Solutions Ltd, Finnland) Aq jml@cubical.fi .
|
||||
This manpage was written by
|
||||
.An Hellmuth Michaelis Aq hm@freebsd.org .
|
Loading…
Reference in New Issue
Block a user