HARP driver for the IDT77201/211 NICStAR ATM Adapter (Including Fore LE155).
Obtained from: Richard Hodges <rh@matriplex.com>
This commit is contained in:
parent
940f2da74e
commit
0e0e9411f2
3307
sys/dev/idt/idt.c
Normal file
3307
sys/dev/idt/idt.c
Normal file
File diff suppressed because it is too large
Load Diff
764
sys/dev/idt/idt_harp.c
Normal file
764
sys/dev/idt/idt_harp.c
Normal file
@ -0,0 +1,764 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Matriplex, inc.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This driver is derived from the Nicstar driver by Mark Tinguely, and
|
||||
* some of the original driver still exists here. Those portions are...
|
||||
* Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
|
||||
* All rights reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <sys/module.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/netisr.h>
|
||||
#include <net/if_var.h>
|
||||
|
||||
#include <netatm/port.h>
|
||||
#include <netatm/queue.h>
|
||||
#include <netatm/atm.h>
|
||||
#include <netatm/atm_sys.h>
|
||||
#include <netatm/atm_sap.h>
|
||||
#include <netatm/atm_cm.h>
|
||||
#include <netatm/atm_if.h>
|
||||
#include <netatm/atm_stack.h>
|
||||
#include <netatm/atm_pcb.h>
|
||||
#include <netatm/atm_var.h>
|
||||
#include <netatm/atm_vc.h>
|
||||
|
||||
#include <dev/idt/idtreg.h>
|
||||
#include <dev/idt/idtvar.h>
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* HARP-specific definitions
|
||||
*
|
||||
*/
|
||||
|
||||
#define IDT_DEV_NAME "idt"
|
||||
|
||||
#define IDT_IFF_MTU 9188
|
||||
#define IDT_MAX_VCI 1023 /* 0 - 1023 */
|
||||
#define IDT_MAX_VPI 0
|
||||
|
||||
#define iv_next iv_cmn.cv_next
|
||||
#define iv_toku iv_cmn.cv_toku
|
||||
#define iv_upper iv_cmn.cv_upper
|
||||
#define iv_vccb iv_cmn.cv_connvc /* HARP 3.0 */
|
||||
#define iv_state iv_cmn.cv_state
|
||||
#define iu_pif iu_cmn.cu_pif
|
||||
#define iu_unit iu_cmn.cu_unit
|
||||
#define iu_flags iu_cmn.cu_flags
|
||||
#define iu_mtu iu_cmn.cu_mtu
|
||||
#define iu_open_vcc iu_cmn.cu_open_vcc
|
||||
#define iu_instvcc iu_cmn.cu_instvcc /* HARP 3.0 */
|
||||
#define iu_vcc iu_cmn.cu_vcc
|
||||
#define iu_vcc_zone iu_cmn.cu_vcc_zone
|
||||
#define iu_nif_zone iu_cmn.cu_nif_zone
|
||||
#define iu_ioctl iu_cmn.cu_ioctl
|
||||
#define iu_openvcc iu_cmn.cu_openvcc
|
||||
#define iu_closevcc iu_cmn.cu_closevcc
|
||||
#define iu_output iu_cmn.cu_output
|
||||
#define iu_config iu_cmn.cu_config
|
||||
|
||||
/*
|
||||
* ATM Interface services
|
||||
*/
|
||||
static struct stack_defn idt_svaal5 = {
|
||||
NULL,
|
||||
SAP_CPCS_AAL5,
|
||||
SDF_TERM,
|
||||
atm_dev_inst,
|
||||
atm_dev_lower,
|
||||
NULL,
|
||||
0,
|
||||
};
|
||||
static struct stack_defn idt_svaal4 = {
|
||||
&idt_svaal5,
|
||||
SAP_CPCS_AAL3_4,
|
||||
SDF_TERM,
|
||||
atm_dev_inst,
|
||||
atm_dev_lower,
|
||||
NULL,
|
||||
0,
|
||||
};
|
||||
static struct stack_defn idt_svaal0 = {
|
||||
&idt_svaal4,
|
||||
SAP_ATM,
|
||||
SDF_TERM,
|
||||
atm_dev_inst,
|
||||
atm_dev_lower,
|
||||
NULL,
|
||||
0,
|
||||
};
|
||||
struct stack_defn *idt_services = &idt_svaal0;
|
||||
|
||||
extern uma_zone_t idt_nif_zone;
|
||||
extern uma_zone_t idt_vcc_zone;
|
||||
|
||||
static int idt_atm_bearerclass(struct attr_bearer *);
|
||||
static CONNECTION *idt_atm_harpconn(Cmn_unit *, Cmn_vcc *);
|
||||
static int idt_atm_ioctl(int, caddr_t, caddr_t);
|
||||
|
||||
static void idt_output(Cmn_unit *, Cmn_vcc *, KBuffer *);
|
||||
static int idt_openvcc(Cmn_unit *, Cmn_vcc *);
|
||||
static int idt_closevcc(Cmn_unit *, Cmn_vcc *);
|
||||
static int idt_instvcc(Cmn_unit *, Cmn_vcc *);
|
||||
|
||||
static void idt_recv_stack(void *, KBuffer *);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* HARP GLUE SECTION
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* Handle netatm core service interface ioctl requests
|
||||
*
|
||||
* Called at splnet.
|
||||
*
|
||||
* Arguments:
|
||||
* code ioctl function (sub)code
|
||||
* data data to/from ioctl
|
||||
* arg optional code-specific argument
|
||||
*
|
||||
* Returns:
|
||||
* 0 request processed successfully
|
||||
* error request failed - reason code
|
||||
*
|
||||
*/
|
||||
static int
|
||||
idt_atm_ioctl(int code, caddr_t addr, caddr_t arg)
|
||||
{
|
||||
#ifdef T_ATM_BUFQUEUE
|
||||
CONNECTION *connection;
|
||||
TX_QUEUE *txq;
|
||||
struct mbuf *m;
|
||||
Cmn_unit *cup;
|
||||
Cmn_vcc *cvp;
|
||||
int retval;
|
||||
#endif
|
||||
|
||||
switch (code) {
|
||||
|
||||
#ifdef T_ATM_BUFQUEUE
|
||||
case T_ATM_BUFQUEUE:
|
||||
cup = (Cmn_unit *) addr;
|
||||
cvp = (Cmn_vcc *) arg;
|
||||
connection = idt_atm_harpconn(cup, cvp);
|
||||
if (connection == NULL)
|
||||
return (-1);
|
||||
retval = 0;
|
||||
txq = connection->queue;
|
||||
if (txq == NULL)
|
||||
return (-1);
|
||||
for (m = txq->mget; m != NULL; m = m->m_nextpkt)
|
||||
retval += m->m_pkthdr.len;
|
||||
return (retval);
|
||||
#endif
|
||||
}
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Get connection pointer from Cmn_unit and Cmn_vcc
|
||||
*
|
||||
* in: Cmn_unit and Cmn_vcc
|
||||
* out: connection (NULL=error)
|
||||
*
|
||||
* Date first: 05/31/2001 last: 05/31/2001
|
||||
*/
|
||||
|
||||
static CONNECTION *
|
||||
idt_atm_harpconn(Cmn_unit * cup, Cmn_vcc * cvp)
|
||||
{
|
||||
struct vccb *vccinf; /* from HARP struct */
|
||||
IDT *idt;
|
||||
int vpi;
|
||||
int vci;
|
||||
|
||||
idt = (IDT *) cup;
|
||||
if (idt == NULL || cvp == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (cvp->cv_connvc == NULL)
|
||||
return (NULL);
|
||||
|
||||
vccinf = cvp->cv_connvc->cvc_vcc;
|
||||
|
||||
if (vccinf == NULL)
|
||||
return (NULL);
|
||||
|
||||
vpi = vccinf->vc_vpi;
|
||||
vci = vccinf->vc_vci;
|
||||
|
||||
return (idt_connect_find(idt, vpi, vci));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Get CBR/VBR/UBR class from bearer attribute
|
||||
*
|
||||
* in:
|
||||
* out: NICCBR/NICVBR/NICABR/NICUBR
|
||||
*
|
||||
* Date first: 06/12/2001 last: 06/13/2001
|
||||
*/
|
||||
|
||||
static int
|
||||
idt_atm_bearerclass(struct attr_bearer * bearer)
|
||||
{
|
||||
switch (bearer->v.bearer_class) {
|
||||
case T_ATM_CLASS_A:return (NICCBR);
|
||||
case T_ATM_CLASS_C:
|
||||
if (idt_sysctl_vbriscbr)
|
||||
return (NICCBR); /* use CBR slots for VBR VC's */
|
||||
else
|
||||
return (NICVBR);
|
||||
case T_ATM_CLASS_X:
|
||||
if (bearer->v.traffic_type == T_ATM_CBR)
|
||||
return (NICCBR);
|
||||
if (bearer->v.traffic_type == T_ATM_VBR)
|
||||
return (NICVBR);
|
||||
return (NICUBR);
|
||||
}
|
||||
return (NICUBR);
|
||||
}
|
||||
|
||||
/* The flag idt_sysctl_vbriscbr allows us to set up a CBR VC as if it were
|
||||
* VBR. This is primarily to avoid cell loss at a switch that cannot seem
|
||||
* to buffer one or two cells of jitter. This jitter is created when many
|
||||
* CBR slots have been taken, and a new CBR VC cannot use the optimally
|
||||
* spaced slots, and has to use nearby slots instead.
|
||||
*
|
||||
* In this case, we want to use the VC SCR as the CBR value. The PCR and MBS
|
||||
* is only of interest to the switch.
|
||||
*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Initialize HARP service
|
||||
* called from device attach
|
||||
*/
|
||||
|
||||
int
|
||||
idt_harp_init(nicstar_reg_t *idt)
|
||||
{
|
||||
long long tsc_val;
|
||||
u_char idt_mac[6];
|
||||
int i;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
|
||||
/*
|
||||
* Start initializing it
|
||||
*/
|
||||
idt->iu_unit = device_get_unit(idt->dev);
|
||||
idt->iu_mtu = IDT_IFF_MTU;
|
||||
idt->iu_ioctl = idt_atm_ioctl;
|
||||
idt->iu_openvcc = idt_openvcc;
|
||||
idt->iu_instvcc = idt_instvcc;
|
||||
idt->iu_closevcc = idt_closevcc;
|
||||
idt->iu_output = idt_output;
|
||||
idt->iu_vcc_zone = idt_vcc_zone;
|
||||
idt->iu_nif_zone = idt_nif_zone;
|
||||
|
||||
/*
|
||||
* Copy serial number into config space
|
||||
*/
|
||||
idt->iu_config.ac_serial = 0;
|
||||
|
||||
idt->iu_config.ac_vendor = VENDOR_IDT;
|
||||
idt->iu_config.ac_vendapi = VENDAPI_IDT_1;
|
||||
idt->iu_config.ac_device = DEV_IDT_155;
|
||||
idt->iu_config.ac_media = MEDIA_UNKNOWN;
|
||||
idt->iu_config.ac_bustype = BUS_PCI;
|
||||
|
||||
idt->iu_pif.pif_pcr = idt->cellrate_rmax; /* ATM_PCR_OC3C; */
|
||||
idt->iu_pif.pif_maxvpi = idt->conn_maxvpi;
|
||||
idt->iu_pif.pif_maxvci = idt->conn_maxvci;
|
||||
|
||||
snprintf(idt->iu_config.ac_hard_vers,
|
||||
sizeof(idt->iu_config.ac_hard_vers),
|
||||
idt->hardware);
|
||||
snprintf(idt->iu_config.ac_firm_vers,
|
||||
sizeof(idt->iu_config.ac_firm_vers),
|
||||
IDT_VERSION);
|
||||
/*
|
||||
* Save device ram info for user-level programs NOTE: This really
|
||||
* points to start of EEPROM and includes all the device registers
|
||||
* in the lower 2 Megabytes.
|
||||
*/
|
||||
idt->iu_config.ac_ram = NULL;
|
||||
idt->iu_config.ac_ramsize = 0;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
idt_mac[i] = nicstar_eeprom_rd(idt, (0x6c + i));
|
||||
}
|
||||
|
||||
/* looks like bad MAC */
|
||||
if ((idt_mac[3] | idt_mac[4] | idt_mac[5]) == 0) {
|
||||
GET_RDTSC(tsc_val); /* 24 bits on 500mhz CPU is about
|
||||
* 30msec */
|
||||
idt_mac[0] = 0x00;
|
||||
idt_mac[1] = 0x20;
|
||||
idt_mac[2] = 0x48; /* use Fore prefix */
|
||||
idt_mac[3] = (tsc_val >> 16) & 0xff;
|
||||
idt_mac[4] = (tsc_val >> 8) & 0xff;
|
||||
idt_mac[5] = (tsc_val) & 0xff;
|
||||
device_printf(idt->dev,
|
||||
"Cannot read MAC address from EEPROM, generating it.\n");
|
||||
}
|
||||
bcopy(&idt_mac, &idt->iu_pif.pif_macaddr.ma_data, sizeof(idt_mac));
|
||||
|
||||
device_printf(idt->dev, "MAC address %6D, HWrev=%d\n",
|
||||
(u_int8_t *)&idt->iu_pif.pif_macaddr.ma_data, ":",
|
||||
idt->pci_rev);
|
||||
|
||||
idt->iu_config.ac_macaddr = idt->iu_pif.pif_macaddr;
|
||||
|
||||
/*
|
||||
* Register this interface with ATM core services
|
||||
*/
|
||||
error = atm_physif_register(&idt->iu_cmn, IDT_DEV_NAME, idt_services);
|
||||
if (error != 0) {
|
||||
/*
|
||||
* Registration failed - back everything out
|
||||
*/
|
||||
|
||||
log(LOG_ERR, "%s(): atm_physif_register failed\n", __func__);
|
||||
return (error);
|
||||
}
|
||||
idt->iu_flags |= CUF_INITED;
|
||||
|
||||
#if BSD >= 199506
|
||||
/*
|
||||
* Add hook to out shutdown function at_shutdown (
|
||||
* (bootlist_fn)idt_pci_shutdown, idt, SHUTDOWN_POST_SYNC );
|
||||
*/
|
||||
#endif
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Output data
|
||||
*/
|
||||
|
||||
static void
|
||||
idt_output(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc, KBuffer * m)
|
||||
{
|
||||
struct vccb *vccinf; /* from HARP struct */
|
||||
IDT *idt;
|
||||
int vpi;
|
||||
int vci;
|
||||
int flags;
|
||||
|
||||
idt = (IDT *) cmnunit;
|
||||
flags = 0;
|
||||
|
||||
if (cmnvcc == NULL) {
|
||||
device_printf(idt->dev, "idt_output arg error #1\n");
|
||||
goto bad;
|
||||
}
|
||||
if (cmnvcc->cv_connvc == NULL) {
|
||||
device_printf(idt->dev, "idt_output arg error #2\n");
|
||||
goto bad;
|
||||
}
|
||||
vccinf = cmnvcc->cv_connvc->cvc_vcc;
|
||||
if (vccinf == NULL) {
|
||||
device_printf(idt->dev, "idt_output arg error #3\n");
|
||||
goto bad;
|
||||
}
|
||||
vpi = vccinf->vc_vpi;
|
||||
vci = vccinf->vc_vci;
|
||||
|
||||
#ifdef CVF_MPEG2TS /* option to split bufs into small TS bufs */
|
||||
if (cmnvcc->cv_flags & CVF_MPEG2TS)
|
||||
flags = 1;
|
||||
#endif
|
||||
|
||||
idt_transmit(idt, m, vpi, vci, flags);
|
||||
|
||||
return;
|
||||
bad:
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Open VCC
|
||||
*/
|
||||
|
||||
static int
|
||||
idt_openvcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
|
||||
{
|
||||
Atm_attributes *attrib; /* from HARP struct */
|
||||
struct vccb *vccinf; /* from HARP struct */
|
||||
CONNECTION *connection;
|
||||
IDT *idt;
|
||||
int vpi;
|
||||
int vci;
|
||||
int class; /* NICCBR, NICVBR, or NICUBR */
|
||||
|
||||
idt = (IDT *) cmnunit;
|
||||
|
||||
if (cmnvcc == NULL || cmnvcc->cv_connvc == NULL) {
|
||||
printf("idt_openvcc: bad request #1.\n");
|
||||
return (1);
|
||||
}
|
||||
attrib = &cmnvcc->cv_connvc->cvc_attr;
|
||||
vccinf = cmnvcc->cv_connvc->cvc_vcc;
|
||||
|
||||
if (attrib == NULL || vccinf == NULL) {
|
||||
printf("idt_openvcc: bad request #2.\n");
|
||||
return (1);
|
||||
}
|
||||
vpi = vccinf->vc_vpi;
|
||||
vci = vccinf->vc_vci;
|
||||
|
||||
connection = idt_connect_find(idt, vpi, vci);
|
||||
if (connection == NULL) {
|
||||
printf("idt_openvcc: vpi/vci invalid: %d/%d\n", vpi, vci);
|
||||
return (1);
|
||||
}
|
||||
if (connection->status) {
|
||||
printf("idt_openvcc: connection already open %d/%d\n", vpi, vci);
|
||||
return (1);
|
||||
}
|
||||
connection->status = 1;
|
||||
connection->recv = NULL;
|
||||
connection->rlen = 0;
|
||||
connection->maxpdu = 20000;
|
||||
connection->aal = IDTAAL5;
|
||||
connection->traf_pcr = attrib->traffic.v.forward.PCR_all_traffic;
|
||||
connection->traf_scr = attrib->traffic.v.forward.SCR_all_traffic;
|
||||
connection->vccinf = vccinf; /* 12/15/2000 */
|
||||
|
||||
if (connection->traf_pcr <= 0)
|
||||
connection->traf_pcr = connection->traf_scr;
|
||||
if (connection->traf_scr <= 0)
|
||||
connection->traf_scr = connection->traf_pcr;
|
||||
|
||||
class = idt_atm_bearerclass(&attrib->bearer);
|
||||
if (vpi == 0 && vci == 5)
|
||||
class = NICABR; /* higher priority than UBR */
|
||||
if (vpi == 0 && vci == 16)
|
||||
class = NICABR;
|
||||
|
||||
if (connection->traf_pcr < 0) { /* neither PCR nor SCR given */
|
||||
connection->traf_pcr = 1;
|
||||
connection->traf_scr = 1;
|
||||
class = NICUBR; /* so give it lowest priority */
|
||||
}
|
||||
connection->class = class;
|
||||
|
||||
if (idt_connect_txopen(idt, connection)) {
|
||||
device_printf(idt->dev, "cannot open connection for %d/%d\n",
|
||||
vpi, vci);
|
||||
return (1);
|
||||
}
|
||||
if (idt_sysctl_logvcs)
|
||||
printf("idt_openvcc: %d/%d, PCR=%d, SCR=%d\n", vpi, vci,
|
||||
connection->traf_pcr, connection->traf_scr);
|
||||
idt_connect_opencls(idt, connection, 1); /* open entry in rcv
|
||||
* connect table */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* We really don't handle ABR, but use it as a higher priority UBR. The
|
||||
* idea is that a UBR connection that gives a PCR (like 0/16) should
|
||||
* be given preference over a UBR connection that wants "everything else".
|
||||
*
|
||||
* Note that CLASS_X is typically UBR, but the traffic type information
|
||||
* element may still specify CBR or VBR.
|
||||
*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Close VCC
|
||||
*/
|
||||
|
||||
static int
|
||||
idt_closevcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
|
||||
{
|
||||
CONNECTION *connection;
|
||||
nicstar_reg_t *idt = (nicstar_reg_t *) cmnunit;
|
||||
int vpi;
|
||||
int vci;
|
||||
|
||||
if (cmnvcc && cmnvcc->cv_connvc && cmnvcc->cv_connvc->cvc_vcc) {
|
||||
vpi = cmnvcc->cv_connvc->cvc_vcc->vc_vpi;
|
||||
vci = cmnvcc->cv_connvc->cvc_vcc->vc_vci;
|
||||
} else {
|
||||
printf("idt_closevcc: bad vcivpi\n");
|
||||
return (0);
|
||||
}
|
||||
connection = idt_connect_find(idt, vpi, vci);
|
||||
|
||||
if (connection == NULL) {
|
||||
printf("idt_closevcc: vpi/vci invalid: %d/%d\n", vpi, vci);
|
||||
return (0);
|
||||
}
|
||||
idt_connect_opencls(idt, connection, 0); /* close entry in rcv
|
||||
* connect table */
|
||||
|
||||
if (connection->status == 0)
|
||||
printf("idt_closevcc: close on empty connection %d/%d\n", vpi, vci);
|
||||
if (connection->recv != NULL)
|
||||
m_freem(connection->recv); /* recycle mbuf of partial PDU */
|
||||
idt_connect_txclose(idt, connection);
|
||||
connection->status = 0;
|
||||
connection->recv = NULL;
|
||||
connection->rlen = 0;
|
||||
connection->maxpdu = 0;
|
||||
connection->aal = 0;
|
||||
connection->traf_pcr = 0;
|
||||
connection->traf_scr = 0;
|
||||
|
||||
if (idt_sysctl_logvcs)
|
||||
printf("idt_closevcc: vpi=%d vci=%d\n", vpi, vci);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* VCC Stack Instantiation
|
||||
*
|
||||
* This function is called via the common driver code during a device VCC
|
||||
* stack instantiation. The common code has already validated some of
|
||||
* the request so we just need to check a few more IDT-specific details.
|
||||
*
|
||||
* Called at splnet.
|
||||
*
|
||||
* Arguments:
|
||||
* cup pointer to device common unit
|
||||
* cvp pointer to common VCC entry
|
||||
*
|
||||
* Returns:
|
||||
* 0 instantiation successful
|
||||
* err instantiation failed - reason indicated
|
||||
*
|
||||
*/
|
||||
static int
|
||||
idt_instvcc(Cmn_unit * cmnunit, Cmn_vcc * cmnvcc)
|
||||
{
|
||||
Atm_attributes *attrib; /* from HARP struct */
|
||||
IDT *idt;
|
||||
int class, pcr, scr;
|
||||
int slots_vc, slots_cur, slots_max;
|
||||
|
||||
if (cmnvcc == NULL)
|
||||
return (EINVAL);
|
||||
if (cmnvcc->cv_connvc == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
idt = (IDT *) cmnunit;
|
||||
if (idt == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
attrib = &cmnvcc->cv_connvc->cvc_attr;
|
||||
|
||||
if (attrib == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
pcr = attrib->traffic.v.forward.PCR_all_traffic;
|
||||
scr = attrib->traffic.v.forward.SCR_all_traffic;
|
||||
|
||||
if (pcr <= 0)
|
||||
pcr = scr; /* if PCR missing, default to SCR */
|
||||
if (pcr <= 0)
|
||||
pcr = 1;
|
||||
if (scr <= 0)
|
||||
scr = pcr;
|
||||
|
||||
class = idt_atm_bearerclass(&attrib->bearer);
|
||||
if (class == NICCBR) {
|
||||
slots_max = idt->txslots_max;
|
||||
slots_cur = idt->txslots_cur;
|
||||
slots_vc = idt_slots_cbr(idt, scr); /* 06/13/2001: now using
|
||||
* SCR */
|
||||
if (slots_vc + slots_cur > slots_max) {
|
||||
if (idt_sysctl_logvcs)
|
||||
device_printf(idt->dev,
|
||||
"Insufficient bandwidth (vc=%d cur=%d max=%d)\n",
|
||||
slots_vc, slots_cur, slots_max);
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
/* This part was take from /sys/dev/hfa/fore_vcm.c */
|
||||
|
||||
switch (attrib->aal.type) {
|
||||
case ATM_AAL0:
|
||||
break;
|
||||
case ATM_AAL3_4:
|
||||
if ((attrib->aal.v.aal4.forward_max_SDU_size > IDT_IFF_MTU) ||
|
||||
(attrib->aal.v.aal4.backward_max_SDU_size > IDT_IFF_MTU))
|
||||
return (EINVAL);
|
||||
break;
|
||||
case ATM_AAL5:
|
||||
if ((attrib->aal.v.aal5.forward_max_SDU_size > IDT_IFF_MTU) ||
|
||||
(attrib->aal.v.aal5.backward_max_SDU_size > IDT_IFF_MTU))
|
||||
return (EINVAL);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass Incoming PDU up Stack
|
||||
*
|
||||
* This function is called via the core ATM interrupt queue callback
|
||||
* set in fore_recv_drain(). It will pass the supplied incoming
|
||||
* PDU up the incoming VCC's stack.
|
||||
*
|
||||
* Called at splnet.
|
||||
*
|
||||
* Arguments:
|
||||
* tok token to identify stack instantiation
|
||||
* m pointer to incoming PDU buffer chain
|
||||
*
|
||||
* Returns:
|
||||
* none
|
||||
*/
|
||||
static void
|
||||
idt_recv_stack(void *tok, KBuffer * m)
|
||||
{
|
||||
Idt_vcc *ivp = (Idt_vcc *) tok;
|
||||
int err;
|
||||
|
||||
if ((m->m_flags & M_PKTHDR) == 0) {
|
||||
printf("idt_recv_stack: Warning - mbuf chain has no header.\n");
|
||||
KB_FREEALL(m);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Send the data up the stack
|
||||
*/
|
||||
STACK_CALL(CPCS_UNITDATA_SIG, ivp->iv_upper,
|
||||
ivp->iv_toku, ivp->iv_vccb, (int)m, 0, err);
|
||||
if (err)
|
||||
KB_FREEALL(m);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Enqueue received PDU for HARP to handle
|
||||
*
|
||||
* in: IDT device, mbuf, vpi, vci
|
||||
*
|
||||
* Date last: 12/14/2000
|
||||
*/
|
||||
|
||||
void
|
||||
idt_receive(nicstar_reg_t * idt, struct mbuf * m, int vpi, int vci)
|
||||
{
|
||||
caddr_t cp;
|
||||
Cmn_vcc *vcc;
|
||||
int space;
|
||||
|
||||
/*
|
||||
* The STACK_CALL needs to happen at splnet() in order for the stack
|
||||
* sequence processing to work. Schedule an interrupt queue
|
||||
* callback at splnet() since we are currently at device level.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Prepend callback function pointer and token value to buffer. We
|
||||
* have already guaranteed that the space is available in the first
|
||||
* buffer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* vcc = atm_dev_vcc_find(&idt->iu_cmn, (vpivci>> 16), vpivci &
|
||||
* 0xffff, VCC_IN);
|
||||
*/
|
||||
|
||||
vcc = atm_dev_vcc_find(&idt->iu_cmn, vpi, vci, VCC_IN);
|
||||
|
||||
if (vcc == NULL) { /* harp stack not ready or no vcc */
|
||||
printf("idt_receive: no VCC %d/%d\n", vpi, vci);
|
||||
KB_FREEALL(m);
|
||||
return;
|
||||
}
|
||||
space = m->m_data - idt_mbuf_base(m);
|
||||
if (space < sizeof(atm_intr_func_t) + sizeof(int)) {
|
||||
printf("idt_receive: NOT enough buffer space (%d).\n", space);
|
||||
KB_FREEALL(m);
|
||||
return;
|
||||
}
|
||||
KB_HEADADJ(m, sizeof(atm_intr_func_t) + sizeof(int));
|
||||
KB_DATASTART(m, cp, caddr_t);
|
||||
*((atm_intr_func_t *) cp) = idt_recv_stack;
|
||||
cp += sizeof(atm_intr_func_t);
|
||||
|
||||
*((void **)cp) = (void *)vcc;
|
||||
|
||||
/*
|
||||
* Schedule callback
|
||||
*/
|
||||
if (!_IF_QFULL(&atm_intrq)) {
|
||||
IF_ENQUEUE(&atm_intrq, m);
|
||||
schednetisr(NETISR_ATM);
|
||||
} else {
|
||||
KB_FREEALL(m);
|
||||
}
|
||||
}
|
323
sys/dev/idt/idt_pci.c
Normal file
323
sys/dev/idt/idt_pci.c
Normal file
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Matriplex, inc.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This driver is derived from the Nicstar driver by Mark Tinguely, and
|
||||
* some of the original driver still exists here. Those portions are...
|
||||
* Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
|
||||
* All rights reserved.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <sys/module.h>
|
||||
#include <machine/bus_memio.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
#include <netatm/port.h>
|
||||
#include <netatm/queue.h>
|
||||
#include <netatm/atm.h>
|
||||
#include <netatm/atm_sys.h>
|
||||
#include <netatm/atm_sap.h>
|
||||
#include <netatm/atm_cm.h>
|
||||
#include <netatm/atm_if.h>
|
||||
#include <netatm/atm_stack.h>
|
||||
#include <netatm/atm_pcb.h>
|
||||
#include <netatm/atm_var.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <dev/idt/idtreg.h>
|
||||
#include <dev/idt/idtvar.h>
|
||||
|
||||
#define IDT_VID 0x111d
|
||||
#define IDT_NICSTAR_DID 0x0001
|
||||
|
||||
struct pci_type {
|
||||
u_int16_t pci_vid;
|
||||
u_int16_t pci_did;
|
||||
char * pci_name;
|
||||
} pci_devs[] = {
|
||||
{ IDT_VID, IDT_NICSTAR_DID, "IDT IDT77201/211 NICStAR ATM Adapter" },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
uma_zone_t idt_nif_zone;
|
||||
uma_zone_t idt_vcc_zone;
|
||||
|
||||
static int idt_probe (device_t);
|
||||
static int idt_attach (device_t);
|
||||
static int idt_detach (device_t);
|
||||
static int idt_shutdown (device_t);
|
||||
static void idt_free (device_t);
|
||||
static int idt_modevent (module_t, int, void *);
|
||||
|
||||
static int
|
||||
idt_probe(device_t dev)
|
||||
{
|
||||
struct pci_type *t = pci_devs;
|
||||
|
||||
while(t->pci_name != NULL) {
|
||||
if ((pci_get_vendor(dev) == t->pci_vid) &&
|
||||
(pci_get_device(dev) == t->pci_did)) {
|
||||
device_set_desc(dev, t->pci_name);
|
||||
return(0);
|
||||
}
|
||||
t++;
|
||||
}
|
||||
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Attach device
|
||||
*
|
||||
* Date first: 11/14/2000 last: 06/10/2001
|
||||
*/
|
||||
|
||||
static int
|
||||
idt_attach(device_t dev)
|
||||
{
|
||||
struct idt_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
error = 0;
|
||||
|
||||
pci_enable_busmaster(dev);
|
||||
|
||||
/* count = 2 (times 32 PCI clocks) */
|
||||
pci_write_config(dev, PCIR_LATTIMER, 0x20, 1);
|
||||
|
||||
/* Map IDT registers */
|
||||
sc->mem_rid = 0x14;
|
||||
sc->mem_type = SYS_RES_MEMORY;
|
||||
sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
if (sc->mem == NULL) {
|
||||
device_printf(dev, "could not map registers.\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
sc->bustag = rman_get_bustag(sc->mem);
|
||||
sc->bushandle = rman_get_bushandle(sc->mem);
|
||||
|
||||
/* Map interrupt */
|
||||
sc->irq_rid = 0;
|
||||
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
|
||||
0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
|
||||
if (sc->irq == NULL) {
|
||||
device_printf(dev, "could not map interrupt.\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, nicstar_intr,
|
||||
sc, &sc->irq_ih);
|
||||
if (error) {
|
||||
device_printf(dev, "could not setup irq.\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sc->virt_baseaddr = (vm_offset_t)rman_get_virtual(sc->mem);
|
||||
sc->cmd_reg = sc->virt_baseaddr + REGCMD; /* old reg */
|
||||
sc->stat_reg = sc->virt_baseaddr + REGSTAT; /* old reg */
|
||||
sc->reg_cmd = (u_long *)(sc->virt_baseaddr + REGCMD);
|
||||
sc->reg_stat = (u_long *)(sc->virt_baseaddr + REGSTAT);
|
||||
sc->reg_cfg = (u_long *)(sc->virt_baseaddr + REGCFG);
|
||||
sc->reg_data = (u_long *)(sc->virt_baseaddr + 0);
|
||||
sc->reg_tsqh = (u_long *)(sc->virt_baseaddr + REGTSQH);
|
||||
sc->reg_gp = (u_long *)(sc->virt_baseaddr + REGGP);
|
||||
sc->pci_rev = pci_get_revid(dev);
|
||||
sc->timer_wrap = 0;
|
||||
|
||||
callout_handle_init(&sc->ch);
|
||||
|
||||
phys_init(sc); /* initialize the hardware */
|
||||
nicstar_init(sc); /* allocate and initialize */
|
||||
|
||||
error = idt_harp_init(sc);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
return (0);
|
||||
fail:
|
||||
idt_free(dev);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Detach device
|
||||
*
|
||||
* Date first: 11/14/2000 last: 11/14/2000
|
||||
*/
|
||||
|
||||
static int
|
||||
idt_detach(device_t dev)
|
||||
{
|
||||
struct idt_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = 0;
|
||||
|
||||
/*
|
||||
* De-Register this interface with ATM core services
|
||||
*/
|
||||
error = atm_physif_deregister(&sc->iu_cmn);
|
||||
|
||||
idt_device_stop(sc); /* Stop the device */
|
||||
|
||||
/*
|
||||
* Lock out all device interupts.
|
||||
*/
|
||||
DEVICE_LOCK(&sc->iu_cmn);
|
||||
idt_free(dev);
|
||||
idt_release_mem(sc);
|
||||
DEVICE_UNLOCK(&sc->iu_cmn);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Shutdown device
|
||||
*
|
||||
* Date first: 11/14/2000 last: 11/14/2000
|
||||
*/
|
||||
|
||||
static int
|
||||
idt_shutdown(device_t dev)
|
||||
{
|
||||
|
||||
struct idt_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
idt_device_stop(sc); /* Stop the device */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
idt_free (device_t dev)
|
||||
{
|
||||
struct idt_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (sc->irq_ih)
|
||||
bus_teardown_intr(dev, sc->irq, sc->irq_ih);
|
||||
if (sc->irq)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
|
||||
if (sc->mem)
|
||||
bus_release_resource(dev, sc->mem_type, sc->mem_rid, sc->mem);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
idt_modevent (module_t mod, int what, void *arg)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
idt_nif_zone = uma_zcreate("idt nif",
|
||||
sizeof(struct atm_nif),
|
||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
|
||||
if (idt_nif_zone == NULL)
|
||||
panic("hfa_modevent:uma_zcreate nif");
|
||||
uma_zone_set_max(idt_nif_zone, 20);
|
||||
|
||||
idt_vcc_zone = uma_zcreate("idt vcc",
|
||||
sizeof(Idt_vcc),
|
||||
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
|
||||
if (idt_vcc_zone == NULL)
|
||||
panic("hfa_modevent: uma_zcreate vcc");
|
||||
uma_zone_set_max(idt_vcc_zone, 100);
|
||||
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
uma_zdestroy(idt_nif_zone);
|
||||
uma_zdestroy(idt_vcc_zone);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static device_method_t idt_methods[] = {
|
||||
DEVMETHOD(device_probe, idt_probe),
|
||||
DEVMETHOD(device_attach, idt_attach),
|
||||
DEVMETHOD(device_detach, idt_detach),
|
||||
DEVMETHOD(device_shutdown, idt_shutdown),
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static driver_t idt_driver = {
|
||||
"idt",
|
||||
idt_methods,
|
||||
sizeof(struct idt_softc)
|
||||
};
|
||||
|
||||
static devclass_t idt_devclass;
|
||||
|
||||
DRIVER_MODULE(idt, pci, idt_driver, idt_devclass, idt_modevent, 0);
|
||||
MODULE_VERSION(idt, 1);
|
77
sys/dev/idt/idtreg.h
Normal file
77
sys/dev/idt/idtreg.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* this product includes software developed by Matriplex, inc.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This driver is derived from the Nicstar driver by Mark Tinguely, and
|
||||
* some of the original driver still exists here. Those portions are...
|
||||
* Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
|
||||
* All rights reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define IDT_VERSION "IDT 1.101"
|
||||
#define CBR_VERBOSE 1 /* show CBR time slots */
|
||||
|
||||
#define IDT_MAX_CBRSLOTS 2100 /* no smaller than value assigned to card */
|
||||
#define IDT_MAX_CBRQUEUE 64 /* max number of CBR connections: 1k each */
|
||||
|
||||
/* AAL types */
|
||||
#define IDTAAL0 0
|
||||
#define IDTAAL1 1
|
||||
#define IDTAAL3_4 3
|
||||
#define IDTAAL5 5
|
||||
|
||||
#define NICCBR 1
|
||||
#define NICVBR 2
|
||||
#define NICABR 3
|
||||
#define NICUBR 4
|
||||
|
||||
/* NICStAR Operation Registers */
|
||||
#define REGCMD 0x10 /* command w */
|
||||
#define REGCFG 0x14 /* configuration r/w */
|
||||
#define REGSTAT 0x18 /* status r/w */
|
||||
#define REGRSQB 0x1c /* RSQ base w */
|
||||
#define REGRSQT 0x20 /* RSQ tail r */
|
||||
#define REGRSQH 0x24 /* RSQ head w */
|
||||
#define REGCDC 0x28 /* cell drop cnt r/c */
|
||||
#define REGVPEC 0x2c /* vci/vpi er cnt r/c */
|
||||
#define REGICC 0x30 /* invalid cell r/c */
|
||||
#define REGRAWT 0x34 /* raw cell tail r */
|
||||
#define REGTMR 0x38 /* timer r */
|
||||
#define REGTSTB 0x3c /* TST base r/w */
|
||||
#define REGTSQB 0x40 /* TSQ base w */
|
||||
#define REGTSQT 0x44 /* TSQ tail r */
|
||||
#define REGTSQH 0x48 /* TSQ head w */
|
||||
#define REGGP 0x4c /* general purp r/w */
|
||||
#define REGVMSK 0x50 /* vci/vpi mask w */
|
228
sys/dev/idt/idtvar.h
Normal file
228
sys/dev/idt/idtvar.h
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Richard Hodges and Matriplex, inc.
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Matriplex, inc.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This driver is derived from the Nicstar driver by Mark Tinguely, and
|
||||
* some of the original driver still exists here. Those portions are...
|
||||
* Copyright (c) 1996, 1997, 1998, 1999 Mark Tinguely
|
||||
* All rights reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* This driver supports the Fore LE155, LE25, and IDT 77211 cards.
|
||||
*
|
||||
* ATM CBR connections are supported, and bandwidth is allocated in
|
||||
* slots of 64k each. Three VBR queues handle traffic for VBR and
|
||||
* UBR. Two UBR queues prioritize UBR traffic. ILMI and signalling
|
||||
* get the higher priority queue, as well as UBR traffic that specifies
|
||||
* a peak cell rate. All other UBR traffic goes into the lower queue.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* New data types
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
struct mbuf *mget; /* head of mbuf queue, pull mbufs from here */
|
||||
struct mbuf **mput; /* tail (ptr to m_nextpkt) put mbufs here */
|
||||
u_long scd; /* segmentation channel descriptor address */
|
||||
u_long *scq_base; /* segmentation channel queue base address */
|
||||
u_long *scq_next; /* next address */
|
||||
u_long *scq_last; /* last address written */
|
||||
int scq_len; /* size of SCQ buffer (64 or 512) */
|
||||
int scq_cur; /* current number entries in SCQ buffer */
|
||||
int rate; /* cells per second allocated to this queue */
|
||||
int vbr_m; /* VBR m/n = max duty cycle for queue */
|
||||
int vbr_n; /* 1 <= m <= 7 and 1 <= n <= 127 */
|
||||
} TX_QUEUE;
|
||||
|
||||
/* To avoid expensive SRAM reads, scq_cur tracks the number of SCQ entries
|
||||
* in use. Only idt_transmit_top may increase this, and only idt_intr_tsq
|
||||
* may decrease it.
|
||||
*/
|
||||
|
||||
/* mbuf chains on the queue use the fields:
|
||||
* m_next is the usual pointer to next mbuf
|
||||
* m_nextpkt is the next packet on the queue
|
||||
* m_pkthdr.rcvif is a pointer to the connection
|
||||
* m_pkthdr.header is a pointer to the TX queue
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
struct vccb *vccinf;
|
||||
char status; /* zero if closed */
|
||||
char vpi;
|
||||
u_short vci;
|
||||
TX_QUEUE *queue; /* transmit queue for this connection */
|
||||
struct mbuf *recv; /* current receive mbuf, or NULL */
|
||||
int rlen; /* current receive length */
|
||||
int maxpdu; /* largest PDU we will ever see */
|
||||
int traf_pcr; /* peak cell rate */
|
||||
int traf_scr; /* sustained cell rate */
|
||||
u_char aal; /* AAL for this connection */
|
||||
u_char class; /* T_ATM_CBR, T_ATM_VBR, or T_ATM_UBR */
|
||||
u_char flg_mpeg2ts:1; /* send data as 2 TS == 8 AAL5 cells */
|
||||
u_char flg_clp:1; /* CLP flag for outbound cells */
|
||||
} CONNECTION;
|
||||
|
||||
#define MAX_CONNECTION 4096 /* max number of connections */
|
||||
|
||||
#define GET_RDTSC(var) {__asm__ volatile("rdtsc":"=A"(var)); }
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Device softc structure
|
||||
*/
|
||||
|
||||
struct idt_softc {
|
||||
/* HARP data */
|
||||
/* XXX: must be first member of struct. */
|
||||
Cmn_unit iu_cmn; /* Common unit stuff */
|
||||
|
||||
#if 0
|
||||
struct arpcom idt_ac; /* ifnet for device */
|
||||
#endif
|
||||
|
||||
/* Device data */
|
||||
device_t dev;
|
||||
int debug;
|
||||
|
||||
struct resource * mem;
|
||||
int mem_rid;
|
||||
int mem_type;
|
||||
bus_space_tag_t bustag;
|
||||
bus_space_handle_t bushandle;
|
||||
|
||||
struct resource * irq;
|
||||
int irq_rid;
|
||||
void * irq_ih;
|
||||
|
||||
struct callout_handle ch;
|
||||
|
||||
struct mtx mtx;
|
||||
|
||||
vm_offset_t virt_baseaddr; /* nicstar register virtual address */
|
||||
vm_offset_t cmd_reg; /* command register offset 0x14 */
|
||||
vm_offset_t stat_reg; /* status register offset 0x60 */
|
||||
vm_offset_t fixbuf; /* buffer that holds TSQ, RSQ, variable SCQ */
|
||||
|
||||
u_long timer_wrap; /* keep track of wrapped timers */
|
||||
u_long rsqh; /* Recieve Status Queue, reg is write-only */
|
||||
|
||||
CONNECTION *connection; /* connection table */
|
||||
int conn_maxvpi; /* number of VPI values */
|
||||
int conn_maxvci; /* number of VCI values */
|
||||
int cellrate_rmax; /* max RX cells per second */
|
||||
int cellrate_tmax; /* max TX cells per second */
|
||||
int cellrate_rcur; /* current committed RX cellrate */
|
||||
int cellrate_tcur; /* current committed TX cellrate */
|
||||
int txslots_max; /* number of CBR TX slots for interface */
|
||||
int txslots_cur; /* current CBR TX slots in use */
|
||||
TX_QUEUE cbr_txqb[IDT_MAX_CBRQUEUE];
|
||||
TX_QUEUE *cbr_slot[IDT_MAX_CBRSLOTS];
|
||||
TX_QUEUE *cbr_free[IDT_MAX_CBRQUEUE];
|
||||
TX_QUEUE queue_vbr;
|
||||
TX_QUEUE queue_abr;
|
||||
TX_QUEUE queue_ubr;
|
||||
vm_offset_t cbr_base; /* base of memory for CBR TX queues */
|
||||
int cbr_size; /* size of memory for CBR TX queues */
|
||||
int cbr_freect;
|
||||
u_long raw_headp; /* head of raw cell queue, physical */
|
||||
struct mbuf *raw_headm; /* head of raw cell queue, virtual */
|
||||
u_long *tsq_base; /* virtual TSQ base address */
|
||||
u_long *tsq_head; /* virtual TSQ head pointer */
|
||||
int tsq_size; /* number of TSQ entries (1024) */
|
||||
volatile u_long *reg_cfg;
|
||||
volatile u_long *reg_cmd;
|
||||
volatile u_long *reg_data;
|
||||
volatile u_long *reg_tsqh;
|
||||
volatile u_long *reg_gp;
|
||||
volatile u_long *reg_stat;
|
||||
struct mbuf **mcheck;
|
||||
|
||||
int sram; /* amount of SRAM */
|
||||
int pci_rev; /* hardware revision ID */
|
||||
char *hardware; /* hardware description string */
|
||||
u_char flg_le25:1; /* flag indicates LE25 instead of LE155 */
|
||||
u_char flg_igcrc:1; /* ignore receive CRC errors */
|
||||
};
|
||||
|
||||
typedef struct idt_softc nicstar_reg_t;
|
||||
typedef struct idt_softc IDT;
|
||||
|
||||
#define iu_pif iu_cmn.cu_pif
|
||||
#define stats_ipdus iu_pif.pif_ipdus
|
||||
#define stats_opdus iu_pif.pif_opdus
|
||||
#define stats_ibytes iu_pif.pif_ibytes
|
||||
#define stats_obytes iu_pif.pif_obytes
|
||||
#define stats_ierrors iu_pif.pif_ierrors
|
||||
#define stats_oerrors iu_pif.pif_oerrors
|
||||
#define stats_cmderrors iu_pif.pif_cmderrors
|
||||
|
||||
/*
|
||||
* Device VCC Entry
|
||||
*
|
||||
* Contains the common and IDT-specific information for each VCC
|
||||
* which is opened through a IDT device.
|
||||
*/
|
||||
struct nidt_vcc {
|
||||
struct cmn_vcc iv_cmn; /* Common VCC stuff */
|
||||
};
|
||||
|
||||
typedef struct nidt_vcc Idt_vcc;
|
||||
|
||||
extern int idt_sysctl_logvcs;
|
||||
extern int idt_sysctl_vbriscbr;
|
||||
|
||||
void nicstar_intr(void *);
|
||||
void phys_init(nicstar_reg_t * const);
|
||||
void nicstar_init(nicstar_reg_t * const);
|
||||
int idt_harp_init(nicstar_reg_t * const);
|
||||
void idt_device_stop(IDT *);
|
||||
void idt_release_mem(IDT *);
|
||||
|
||||
CONNECTION *idt_connect_find(IDT *, int, int);
|
||||
caddr_t idt_mbuf_base(struct mbuf *);
|
||||
int idt_slots_cbr(IDT *, int);
|
||||
|
||||
int idt_connect_opencls(IDT *, CONNECTION *, int);
|
||||
int idt_connect_txopen(IDT *, CONNECTION *);
|
||||
int idt_connect_txclose(IDT *, CONNECTION *);
|
||||
|
||||
int nicstar_eeprom_rd(nicstar_reg_t * const, u_long);
|
||||
|
||||
void idt_receive(IDT *, struct mbuf *, int, int);
|
||||
void idt_transmit(IDT *, struct mbuf *, int, int, int);
|
9
sys/modules/idt/Makefile
Normal file
9
sys/modules/idt/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/idt
|
||||
|
||||
KMOD= idt
|
||||
SRCS= idt_pci.c idt_harp.c idt.c
|
||||
SRCS+= pci_if.h device_if.h bus_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user