This commit was manufactured by cvs2svn to create branch 'RELENG_6'.

This commit is contained in:
cvs2svn 2006-12-20 22:02:46 +00:00
parent 50c44d102c
commit 472436dd42
11 changed files with 9169 additions and 0 deletions

View File

@ -0,0 +1,246 @@
/* $NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Emmanuel Dreyfus.
*
* 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 the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#if 0
__KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
#endif
#include "opt_compat.h"
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/signal.h>
#include <sys/stdint.h>
#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/proc.h>
#ifdef COMPAT_LINUX32
#include <machine/../linux32/linux.h>
#include <machine/../linux32/linux32_proto.h>
#else
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
#endif
static void native_to_linux_timespec(struct l_timespec *,
struct timespec *);
static int linux_to_native_timespec(struct timespec *,
struct l_timespec *);
static int linux_to_native_clockid(clockid_t *, clockid_t);
static void
native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
{
ltp->tv_sec = ntp->tv_sec;
ltp->tv_nsec = ntp->tv_nsec;
}
static int
linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
{
if (ltp->tv_sec < 0 || ltp->tv_nsec > (l_long)999999999L)
return (EINVAL);
ntp->tv_sec = ltp->tv_sec;
ntp->tv_nsec = ltp->tv_nsec;
return (0);
}
static int
linux_to_native_clockid(clockid_t *n, clockid_t l)
{
switch (l) {
case LINUX_CLOCK_REALTIME:
*n = CLOCK_REALTIME;
break;
case LINUX_CLOCK_MONOTONIC:
*n = CLOCK_MONOTONIC;
break;
case LINUX_CLOCK_PROCESS_CPUTIME_ID:
case LINUX_CLOCK_THREAD_CPUTIME_ID:
case LINUX_CLOCK_REALTIME_HR:
case LINUX_CLOCK_MONOTONIC_HR:
default:
return (EINVAL);
break;
}
return (0);
}
int
linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
{
struct l_timespec lts;
int error;
clockid_t nwhich = 0; /* XXX: GCC */
struct timespec tp;
error = linux_to_native_clockid(&nwhich, args->which);
if (error != 0)
return (error);
error = kern_clock_gettime(td, nwhich, &tp);
if (error != 0)
return (error);
native_to_linux_timespec(&lts, &tp);
return (copyout(&lts, args->tp, sizeof lts));
}
int
linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
{
struct timespec ts;
struct l_timespec lts;
int error;
clockid_t nwhich = 0; /* XXX: GCC */
error = linux_to_native_clockid(&nwhich, args->which);
if (error != 0)
return (error);
error = copyin(args->tp, &lts, sizeof lts);
if (error != 0)
return (error);
error = linux_to_native_timespec(&ts, &lts);
if (error != 0)
return (error);
return (kern_clock_settime(td, nwhich, &ts));
}
int
linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
{
struct timespec ts;
struct l_timespec lts;
int error;
clockid_t nwhich = 0; /* XXX: GCC */
if (args->tp == NULL)
return (0);
error = linux_to_native_clockid(&nwhich, args->which);
if (error != 0)
return (error);
error = kern_clock_getres(td, nwhich, &ts);
if (error != 0)
return (error);
native_to_linux_timespec(&lts, &ts);
return (copyout(&lts, args->tp, sizeof lts));
}
int
linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
{
struct timespec *rmtp;
struct l_timespec lrqts, lrmts;
struct timespec rqts, rmts;
int error;
error = copyin(args->rqtp, &lrqts, sizeof lrqts);
if (error != 0)
return (error);
if (args->rmtp != NULL)
rmtp = &rmts;
else
rmtp = NULL;
error = linux_to_native_timespec(&rqts, &lrqts);
if (error != 0)
return (error);
error = kern_nanosleep(td, &rqts, rmtp);
if (error != 0)
return (error);
if (args->rmtp != NULL) {
native_to_linux_timespec(&lrmts, rmtp);
error = copyout(&lrmts, args->rmtp, sizeof(lrmts));
if (error != 0)
return (error);
}
return (0);
}
int
linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
{
struct timespec *rmtp;
struct l_timespec lrqts, lrmts;
struct timespec rqts, rmts;
int error;
if (args->flags != 0)
return (EINVAL); /* XXX deal with TIMER_ABSTIME */
if (args->which != LINUX_CLOCK_REALTIME)
return (EINVAL);
error = copyin(args->rqtp, &lrqts, sizeof lrqts);
if (error != 0)
return (error);
if (args->rmtp != NULL)
rmtp = &rmts;
else
rmtp = NULL;
error = linux_to_native_timespec(&rqts, &lrqts);
if (error != 0)
return (error);
error = kern_nanosleep(td, &rqts, rmtp);
if (error != 0)
return (error);
if (args->rmtp != NULL) {
native_to_linux_timespec(&lrmts, rmtp);
error = copyout(&lrmts, args->rmtp, sizeof lrmts );
if (error != 0)
return (error);
}
return (0);
}

View File

@ -0,0 +1,121 @@
/*-
* Copyright (c) 2006 Sam Leffler, Errno Consulting
* Copyright (c) 2006 Atheros Communications, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms 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 NO
* ''WARRANTY'' disclaimer below (''Disclaimer''), without
* modification.
* 2. Redistributions in binary form must reproduce at minimum a
* disclaimer similar to the Disclaimer below and any redistribution
* must be conditioned upon including a substantially similar
* Disclaimer requirement for further binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the
* names of any contributors may be used to endorse or promote
* product derived from this software without specific prior written
* permission.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT,
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
* FOR 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 DAMAGES.
*
* $Id: //depot/sw/branches/sam_hal/public/wackelf.c#3 $
*/
/*
* Program to zap flags field in the ELF header of an object
* file so that it appears to use VFP soft floating point.
* This is done because there is no standard way to specify
* this on the command line to gcc/binutils.
*
* Derived from code by Olivier Houchard <cognet@freebsd.org>
*/
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <fcntl.h>
#include <err.h>
#ifdef __linux__
#include <endian.h>
#include <byteswap.h>
#define _LITTLE_ENDIAN __LITTLE_ENDIAN
#define _BIG_ENDIAN __BIG_ENDIAN
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define htobe16(x) __bswap_16((x))
#define htobe32(x) __bswap_32((x))
#define htole16(x) ((uint16_t)(x))
#define htole32(x) ((uint32_t)(x))
#else /* _BYTE_ORDER != _LITTLE_ENDIAN */
#define htobe16(x) ((uint16_t)(x))
#define htobe32(x) ((uint32_t)(x))
#define htole16(x) __bswap_16((x))
#define htole32(x) __bswap_32((x))
#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */
#else
#include <sys/endian.h>
#endif
int
main(int argc, char *argv[])
{
int fd, endian, oflags;
int format = 0x400; /* default to VFP */
Elf32_Ehdr ehdr;
if (argc > 2) {
if (strcmp(argv[1], "-fpa") == 0) {
format = 0x200;
argc--, argv++;
} else if (strcmp(argv[1], "-vfp") == 0) {
format = 0x400;
argc--, argv++;
} else if (strcmp(argv[1], "-none") == 0) {
format = 0;
argc--, argv++;
}
}
if (argc != 2) {
fprintf(stderr, "usage: %s [-fpa|-vfp|-none] file\n", argv[0]);
exit(-1);
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
err(1, "could not open %s", argv[1]);
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
err(1, "could not read the ELF header");
if (ehdr.e_machine == htole16(EM_ARM))
endian = _LITTLE_ENDIAN;
else if (ehdr.e_machine == htobe16(EM_ARM))
endian = _BIG_ENDIAN;
else
errx(1, "not an ARM ELF object (machine 0x%x)", ehdr.e_machine);
oflags = ehdr.e_flags;
if (endian == _BIG_ENDIAN) {
ehdr.e_flags &= ~htobe32(0x600); /* Remove FPA Soft float */
ehdr.e_flags |= htobe32(format); /* VFP Soft Float */
} else {
ehdr.e_flags &= ~htole32(0x600); /* Remove FPA Soft float */
ehdr.e_flags |= htole32(format); /* VFP Soft Float */
}
printf("%s: e_flags 0x%x => 0x%x\n", argv[1], oflags, ehdr.e_flags);
if (lseek(fd, (off_t) 0, SEEK_SET) != 0)
err(1, "lseek");
if (write(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
err(1, "yow, elf header write failed");
close(fd);
return 0;
}

2843
sys/dev/ral/rt2560.c Normal file

File diff suppressed because it is too large Load Diff

170
sys/dev/ral/rt2560var.h Normal file
View File

@ -0,0 +1,170 @@
/* $FreeBSD$ */
/*-
* Copyright (c) 2005, 2006
* Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct rt2560_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsf;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
uint8_t wr_antenna;
uint8_t wr_antsignal;
};
#define RT2560_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_TSFT) | \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_ANTENNA) | \
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL))
struct rt2560_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
uint8_t wt_antenna;
};
#define RT2560_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_ANTENNA))
struct rt2560_tx_data {
bus_dmamap_t map;
struct mbuf *m;
struct ieee80211_node *ni;
struct ral_rssdesc id;
};
struct rt2560_tx_ring {
bus_dma_tag_t desc_dmat;
bus_dma_tag_t data_dmat;
bus_dmamap_t desc_map;
bus_addr_t physaddr;
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
int count;
int queued;
int cur;
int next;
int cur_encrypt;
int next_encrypt;
};
struct rt2560_rx_data {
bus_dmamap_t map;
struct mbuf *m;
int drop;
};
struct rt2560_rx_ring {
bus_dma_tag_t desc_dmat;
bus_dma_tag_t data_dmat;
bus_dmamap_t desc_map;
bus_addr_t physaddr;
struct rt2560_rx_desc *desc;
struct rt2560_rx_data *data;
int count;
int cur;
int next;
int cur_decrypt;
};
struct rt2560_node {
struct ieee80211_node ni;
struct ral_rssadapt rssadapt;
};
struct rt2560_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
struct mtx sc_mtx;
struct callout watchdog_ch;
struct callout scan_ch;
struct callout rssadapt_ch;
int sc_tx_timer;
uint32_t asic_rev;
uint32_t eeprom_rev;
uint8_t rf_rev;
struct rt2560_tx_ring txq;
struct rt2560_tx_ring prioq;
struct rt2560_tx_ring atimq;
struct rt2560_tx_ring bcnq;
struct rt2560_rx_ring rxq;
struct ieee80211_beacon_offsets sc_bo;
uint32_t rf_regs[4];
uint8_t txpow[14];
struct {
uint8_t reg;
uint8_t val;
} bbp_prom[16];
int led_mode;
int hw_radio;
int rx_ant;
int tx_ant;
int nb_ant;
int dwelltime;
struct bpf_if *sc_drvbpf;
union {
struct rt2560_rx_radiotap_header th;
uint8_t pad[64];
} sc_rxtapu;
#define sc_rxtap sc_rxtapu.th
int sc_rxtap_len;
union {
struct rt2560_tx_radiotap_header th;
uint8_t pad[64];
} sc_txtapu;
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
};
int rt2560_attach(device_t, int);
int rt2560_detach(void *);
void rt2560_shutdown(void *);
void rt2560_suspend(void *);
void rt2560_resume(void *);
void rt2560_intr(void *);
#define RAL_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
#define RAL_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)

2901
sys/dev/ral/rt2661.c Normal file

File diff suppressed because it is too large Load Diff

172
sys/dev/ral/rt2661var.h Normal file
View File

@ -0,0 +1,172 @@
/* $FreeBSD$ */
/*-
* Copyright (c) 2005
* Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
struct rt2661_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
uint64_t wr_tsf;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
uint16_t wr_chan_flags;
uint8_t wr_antsignal;
} __packed;
#define RT2661_RX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_TSFT) | \
(1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL))
struct rt2661_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
uint8_t wt_flags;
uint8_t wt_rate;
uint16_t wt_chan_freq;
uint16_t wt_chan_flags;
} __packed;
#define RT2661_TX_RADIOTAP_PRESENT \
((1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL))
struct rt2661_tx_data {
bus_dmamap_t map;
struct mbuf *m;
struct ieee80211_node *ni;
struct ral_rssdesc id;
};
struct rt2661_tx_ring {
bus_dma_tag_t desc_dmat;
bus_dma_tag_t data_dmat;
bus_dmamap_t desc_map;
bus_addr_t physaddr;
struct rt2661_tx_desc *desc;
struct rt2661_tx_data *data;
int count;
int queued;
int cur;
int next;
int stat;
};
struct rt2661_rx_data {
bus_dmamap_t map;
struct mbuf *m;
};
struct rt2661_rx_ring {
bus_dma_tag_t desc_dmat;
bus_dma_tag_t data_dmat;
bus_dmamap_t desc_map;
bus_addr_t physaddr;
struct rt2661_rx_desc *desc;
struct rt2661_rx_data *data;
int count;
int cur;
int next;
};
struct rt2661_node {
struct ieee80211_node ni;
struct ral_rssadapt rssadapt;
};
struct rt2661_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
struct mtx sc_mtx;
struct callout watchdog_ch;
struct callout scan_ch;
struct callout rssadapt_ch;
int sc_tx_timer;
struct ieee80211_channel *sc_curchan;
uint8_t rf_rev;
uint8_t rfprog;
uint8_t rffreq;
struct rt2661_tx_ring txq[4];
struct rt2661_tx_ring mgtq;
struct rt2661_rx_ring rxq;
uint32_t rf_regs[4];
int8_t txpow[38];
struct {
uint8_t reg;
uint8_t val;
} bbp_prom[16];
int hw_radio;
int rx_ant;
int tx_ant;
int nb_ant;
int ext_2ghz_lna;
int ext_5ghz_lna;
int rssi_2ghz_corr;
int rssi_5ghz_corr;
uint8_t bbp18;
uint8_t bbp21;
uint8_t bbp22;
uint8_t bbp16;
uint8_t bbp17;
uint8_t bbp64;
int dwelltime;
struct bpf_if *sc_drvbpf;
union {
struct rt2661_rx_radiotap_header th;
uint8_t pad[64];
} sc_rxtapu;
#define sc_rxtap sc_rxtapu.th
int sc_rxtap_len;
union {
struct rt2661_tx_radiotap_header th;
uint8_t pad[64];
} sc_txtapu;
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
};
int rt2661_attach(device_t, int);
int rt2661_detach(void *);
void rt2661_shutdown(void *);
void rt2661_suspend(void *);
void rt2661_resume(void *);
void rt2661_intr(void *);
#define RAL_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
#define RAL_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
* Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
* 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, WHETHERIN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/* -------------------------------------------------------------------- */
/* PCI device ID */
#define PCIV_ENVY24 0x1412
#define PCID_ENVY24HT 0x1724
#define PCIR_CCS 0x10 /* Controller I/O Base Address */
#define ENVY24HT_PCIR_MT 0x14 /* Multi-Track I/O Base Address */
/* Controller Registers */
#define ENVY24HT_CCS_CTL 0x00 /* Control/Status Register */
#define ENVY24HT_CCS_CTL_RESET 0x80 /* Entire Chip soft reset */
#define ENVY24HT_CCS_IMASK 0x01 /* Interrupt Mask Register */
#define ENVY24HT_CCS_IMASK_PMT 0x10 /* Professional Multi-track */
#define ENVY24HT_CCS_I2CDEV 0x10 /* I2C Port Device Address Register */
#define ENVY24HT_CCS_I2CDEV_ADDR 0xfe /* I2C device address */
#define ENVY24HT_CCS_I2CDEV_ROM 0xa0 /* reserved for the external I2C E2PROM */
#define ENVY24HT_CCS_I2CDEV_WR 0x01 /* write */
#define ENVY24HT_CCS_I2CDEV_RD 0x00 /* read */
#define ENVY24HT_CCS_I2CADDR 0x11 /* I2C Port Byte Address Register */
#define ENVY24HT_CCS_I2CDATA 0x12 /* I2C Port Read/Write Data Register */
#define ENVY24HT_CCS_I2CSTAT 0x13 /* I2C Port Control and Status Register */
#define ENVY24HT_CCS_I2CSTAT_ROM 0x80 /* external E2PROM exists */
#define ENVY24HT_CCS_I2CSTAT_BSY 0x01 /* I2C port read/write status busy */
#define ENVY24HT_CCS_SCFG 0x04 /* System Configuration Register */
#define ENVY24HT_CCSM_SCFG_XIN2 0xc0 /* XIN2 Clock Source Configuration */
/* 00: 24.576MHz(96kHz*256) */
/* 01: 49.152MHz(192kHz*256) */
/* 1x: Reserved */
#define ENVY24HT_CCSM_SCFG_MPU 0x20 /* 0(not implemented)/1(1) MPU-401 UART */
#define ENVY24HT_CCSM_SCFG_ADC 0x0c /* 1-2 stereo ADC connected, S/PDIF receiver connected */
#define ENVY24HT_CCSM_SCFG_DAC 0x03 /* 1-4 stereo DAC connected */
#define ENVY24HT_CCS_ACL 0x05 /* AC-Link Configuration Register */
#define ENVY24HT_CCSM_ACL_MTC 0x80 /* Multi-track converter type: 0:AC'97 1:I2S */
#define ENVY24HT_CCSM_ACL_OMODE 0x02 /* AC 97 codec SDATA_OUT 0:split 1:packed */
#define ENVY24HT_CCS_I2S 0x06 /* I2S Converters Features Register */
#define ENVY24HT_CCSM_I2S_VOL 0x80 /* I2S codec Volume and mute */
#define ENVY24HT_CCSM_I2S_96KHZ 0x40 /* I2S converter 96kHz sampling rate support */
#define ENVY24HT_CCSM_I2S_192KHZ 0x08 /* I2S converter 192kHz sampling rate support */
#define ENVY24HT_CCSM_I2S_RES 0x30 /* Converter resolution */
#define ENVY24HT_CCSM_I2S_16BIT 0x00 /* 16bit */
#define ENVY24HT_CCSM_I2S_18BIT 0x10 /* 18bit */
#define ENVY24HT_CCSM_I2S_20BIT 0x20 /* 20bit */
#define ENVY24HT_CCSM_I2S_24BIT 0x30 /* 24bit */
#define ENVY24HT_CCSM_I2S_ID 0x07 /* Other I2S IDs */
#define ENVY24HT_CCS_SPDIF 0x07 /* S/PDIF Configuration Register */
#define ENVY24HT_CCSM_SPDIF_INT_EN 0x80 /* Enable integrated S/PDIF transmitter */
#define ENVY24HT_CCSM_SPDIF_INT_OUT 0x40 /* Internal S/PDIF Out implemented */
#define ENVY24HT_CCSM_SPDIF_ID 0x3c /* S/PDIF chip ID */
#define ENVY24HT_CCSM_SPDIF_IN 0x02 /* S/PDIF Stereo In is present */
#define ENVY24HT_CCSM_SPDIF_OUT 0x01 /* External S/PDIF Out implemented */
/* Professional Multi-Track Control Registers */
#define ENVY24HT_MT_INT_STAT 0x00 /* DMA Interrupt Mask and Status Register */
#define ENVY24HT_MT_INT_RSTAT 0x02 /* Multi-track record interrupt status */
#define ENVY24HT_MT_INT_PSTAT 0x01 /* Multi-track playback interrupt status */
#define ENVY24HT_MT_INT_MASK 0x03
#define ENVY24HT_MT_INT_RMASK 0x02 /* Multi-track record interrupt mask */
#define ENVY24HT_MT_INT_PMASK 0x01 /* Multi-track playback interrupt mask */
#define ENVY24HT_MT_RATE 0x01 /* Sampling Rate Select Register */
#define ENVY24HT_MT_RATE_SPDIF 0x10 /* S/PDIF input clock as the master */
#define ENVY24HT_MT_RATE_48000 0x00
#define ENVY24HT_MT_RATE_24000 0x01
#define ENVY24HT_MT_RATE_12000 0x02
#define ENVY24HT_MT_RATE_9600 0x03
#define ENVY24HT_MT_RATE_32000 0x04
#define ENVY24HT_MT_RATE_16000 0x05
#define ENVY24HT_MT_RATE_8000 0x06
#define ENVY24HT_MT_RATE_96000 0x07
#define ENVY24HT_MT_RATE_64000 0x0f
#define ENVY24HT_MT_RATE_44100 0x08
#define ENVY24HT_MT_RATE_22050 0x09
#define ENVY24HT_MT_RATE_11025 0x0a
#define ENVY24HT_MT_RATE_88200 0x0b
#define ENVY24HT_MT_RATE_MASK 0x0f
#define ENVY24HT_MT_PADDR 0x10 /* Playback DMA Current/Base Address Register */
#define ENVY24HT_MT_PCNT 0x14 /* Playback DMA Current/Base Count Register */
#define ENVY24HT_MT_PTERM 0x1C /* Playback Current/Base Terminal Count Register */
#define ENVY24HT_MT_PCTL 0x18 /* Global Playback and Record DMA Start/Stop Register */
#define ENVY24HT_MT_PCTL_RSTART 0x02 /* 1: Record start; 0: Record stop */
#define ENVY24HT_MT_PCTL_PSTART 0x01 /* 1: Playback start; 0: Playback stop */
#define ENVY24HT_MT_RADDR 0x20 /* Record DMA Current/Base Address Register */
#define ENVY24HT_MT_RCNT 0x24 /* Record DMA Current/Base Count Register */
#define ENVY24HT_MT_RTERM 0x26 /* Record Current/Base Terminal Count Register */
/*
These map values are refferd from ALSA sound driver.
*/
/* ENVY24 configuration E2PROM map */
#define ENVY24HT_E2PROM_SUBVENDOR 0x02
#define ENVY24HT_E2PROM_SUBDEVICE 0x00
#define ENVY24HT_E2PROM_SIZE 0x04
#define ENVY24HT_E2PROM_VERSION 0x05
#define ENVY24HT_E2PROM_SCFG 0x06
#define ENVY24HT_E2PROM_ACL 0x07
#define ENVY24HT_E2PROM_I2S 0x08
#define ENVY24HT_E2PROM_SPDIF 0x09
#define ENVY24HT_E2PROM_GPIOMASK 0x0d
#define ENVY24HT_E2PROM_GPIOSTATE 0x10
#define ENVY24HT_E2PROM_GPIODIR 0x0a
/* ENVY24 mixer channel defines */
/*
ENVY24 mixer has original line matrix. So, general mixer command is not
able to use for this. If system has consumer AC'97 output, AC'97 line is
used as master mixer, and it is able to control.
*/
#define ENVY24HT_CHAN_NUM 11 /* Play * 5 + Record * 5 + Mix * 1 */
#define ENVY24HT_CHAN_PLAY_DAC1 0
#define ENVY24HT_CHAN_PLAY_DAC2 1
#define ENVY24HT_CHAN_PLAY_DAC3 2
#define ENVY24HT_CHAN_PLAY_DAC4 3
#define ENVY24HT_CHAN_PLAY_SPDIF 4
#define ENVY24HT_CHAN_REC_ADC1 5
#define ENVY24HT_CHAN_REC_ADC2 6
#define ENVY24HT_CHAN_REC_ADC3 7
#define ENVY24HT_CHAN_REC_ADC4 8
#define ENVY24HT_CHAN_REC_SPDIF 9
#define ENVY24HT_CHAN_REC_MIX 10
#define ENVY24HT_MIX_MASK 0x3fd
#define ENVY24HT_MIX_REC_MASK 0x3e0
/* volume value constants */
#define ENVY24HT_VOL_MAX 0 /* 0db(negate) */
#define ENVY24HT_VOL_MIN 96 /* -144db(negate) */
#define ENVY24HT_VOL_MUTE 127 /* mute */
#define BUS_SPACE_MAXADDR_ENVY24 0x0fffffff /* Address space beyond 256MB is not
supported */
#define BUS_SPACE_MAXSIZE_ENVY24 0x3fffc /* 64k x 4byte(1dword) */
#define ENVY24HT_CCS_GPIO_HDATA 0x1E
#define ENVY24HT_CCS_GPIO_LDATA 0x14
#define ENVY24HT_CCS_GPIO_LMASK 0x16
#define ENVY24HT_CCS_GPIO_HMASK 0x1F
#define ENVY24HT_CCS_GPIO_CTLDIR 0x18

View File

@ -0,0 +1,589 @@
/*-
* Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org>
* 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.
*
* Bridge MIB implementation for SNMPd.
* Bridge addresses.
*
* $FreeBSD$
*/
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_mib.h>
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <bsnmp/snmpmod.h>
#include <bsnmp/snmp_mibII.h>
#include "bridge_tree.h"
#include "bridge_snmp.h"
TAILQ_HEAD(tp_entries, tp_entry);
/*
* Free the bridge address list.
*/
static void
bridge_tpe_free(struct tp_entries *headp)
{
struct tp_entry *t;
while ((t = TAILQ_FIRST(headp)) != NULL) {
TAILQ_REMOVE(headp, t, tp_e);
free(t);
}
}
/*
* Free the bridge address entries from the address list,
* for the specified bridge interface only.
*/
static void
bridge_tpe_bif_free(struct tp_entries *headp,
struct bridge_if *bif)
{
struct tp_entry *tp;
while (bif->f_tpa != NULL && bif->sysindex == bif->f_tpa->sysindex) {
tp = TAILQ_NEXT(bif->f_tpa, tp_e);
TAILQ_REMOVE(headp, bif->f_tpa, tp_e);
free(bif->f_tpa);
bif->f_tpa = tp;
}
}
/*
* Compare two mac addresses.
* m1 < m2 : -1
* m1 > m2 : +1
* m1 = m2 : 0
*/
static int
bridge_compare_macs(const uint8_t *m1, const uint8_t *m2)
{
int i;
for (i = 0; i < ETHER_ADDR_LEN; i++) {
if (m1[i] < m2[i])
return (-1);
if (m1[i] > m2[i])
return (1);
}
return (0);
}
/*
* Insert an address entry in the bridge address TAILQ starting to search
* for its place from the position of the first bridge address for the bridge
* interface. Update the first bridge address if neccessary.
*/
static void
bridge_addrs_insert_at(struct tp_entries *headp,
struct tp_entry *ta, struct tp_entry **f_tpa)
{
struct tp_entry *t1;
assert(f_tpa != NULL);
for (t1 = *f_tpa;
t1 != NULL && ta->sysindex == t1->sysindex;
t1 = TAILQ_NEXT(t1, tp_e)) {
if (bridge_compare_macs(ta->tp_addr, t1->tp_addr) < 0) {
TAILQ_INSERT_BEFORE(t1, ta, tp_e);
if (*f_tpa == t1)
(*f_tpa) = ta;
return;
}
}
if (t1 == NULL)
TAILQ_INSERT_TAIL(headp, ta, tp_e);
else
TAILQ_INSERT_BEFORE(t1, ta, tp_e);
}
/*
* Find an address entry's possition in the address list
* according to bridge interface name.
*/
static struct tp_entry *
bridge_addrs_find_pos(struct tp_entries *headp, uint32_t b_idx)
{
uint32_t t_idx;
struct tp_entry *t1;
if ((t1 = TAILQ_FIRST(headp)) == NULL ||
bridge_compare_sysidx(b_idx, t1->sysindex) < 0)
return (NULL);
t_idx = t1->sysindex;
for (t1 = TAILQ_NEXT(t1, tp_e); t1 != NULL; t1 = TAILQ_NEXT(t1, tp_e)) {
if (t1->sysindex != t_idx) {
if (bridge_compare_sysidx(b_idx, t1->sysindex) < 0)
return (TAILQ_PREV(t1, tp_entries, tp_e));
else
t_idx = t1->sysindex;
}
}
if (t1 == NULL)
t1 = TAILQ_LAST(headp, tp_entries);
return (t1);
}
/*
* Insert a bridge address in the bridge addresses list.
*/
static void
bridge_addrs_bif_insert(struct tp_entries *headp, struct tp_entry *te,
struct tp_entry **f_tpa)
{
struct tp_entry *temp;
if (*f_tpa != NULL)
bridge_addrs_insert_at(headp, te, f_tpa);
else {
temp = bridge_addrs_find_pos(headp, te->sysindex);
if (temp == NULL)
TAILQ_INSERT_HEAD(headp, te, tp_e);
else
TAILQ_INSERT_AFTER(headp, temp, te, tp_e);
*f_tpa = te;
}
}
static struct tp_entries tp_entries = TAILQ_HEAD_INITIALIZER(tp_entries);
static time_t address_list_age;
void
bridge_addrs_update_listage(void)
{
address_list_age = time(NULL);
}
void
bridge_addrs_fini(void)
{
bridge_tpe_free(&tp_entries);
}
void
bridge_addrs_free(struct bridge_if *bif)
{
bridge_tpe_bif_free(&tp_entries, bif);
}
/*
* Find the first address in the list.
*/
static struct tp_entry *
bridge_addrs_first(void)
{
return (TAILQ_FIRST(&tp_entries));
}
/*
* Find the next address in the list.
*/
static struct tp_entry *
bridge_addrs_next(struct tp_entry *te)
{
return (TAILQ_NEXT(te, tp_e));
}
/*
* Find the first address, learnt by the specified bridge interface.
*/
struct tp_entry *
bridge_addrs_bif_first(struct bridge_if *bif)
{
return (bif->f_tpa);
}
/*
* Find the next address, learnt by the specified bridge interface.
*/
struct tp_entry *
bridge_addrs_bif_next(struct tp_entry *te)
{
struct tp_entry *te_next;
if ((te_next = TAILQ_NEXT(te, tp_e)) == NULL ||
te_next->sysindex != te->sysindex)
return (NULL);
return (te_next);
}
/*
* Remove a bridge address from the list.
*/
void
bridge_addrs_remove(struct tp_entry *te, struct bridge_if *bif)
{
if (bif->f_tpa == te)
bif->f_tpa = bridge_addrs_bif_next(te);
TAILQ_REMOVE(&tp_entries, te, tp_e);
free(te);
}
/*
* Allocate memory for a new bridge address and insert it in the list.
*/
struct tp_entry *
bridge_new_addrs(uint8_t *mac, struct bridge_if *bif)
{
struct tp_entry *te;
if ((te = (struct tp_entry *) malloc(sizeof(*te))) == NULL) {
syslog(LOG_ERR, "bridge new address: failed: %s",
strerror(errno));
return (NULL);
}
bzero(te, sizeof(*te));
te->sysindex = bif->sysindex;
bcopy(mac, te->tp_addr, ETHER_ADDR_LEN);
bridge_addrs_bif_insert(&tp_entries, te, &(bif->f_tpa));
return (te);
}
/*
* Given a mac address, learnt on a bridge,
* find the corrsponding TP entry for it.
*/
struct tp_entry *
bridge_addrs_find(uint8_t *mac, struct bridge_if *bif)
{
struct tp_entry *te;
for (te = bif->f_tpa; te != NULL; te = TAILQ_NEXT(te, tp_e)) {
if (te->sysindex != bif->sysindex) {
te = NULL;
break;
}
if (bridge_compare_macs(te->tp_addr, mac) == 0)
break;
}
return (te);
}
void
bridge_addrs_dump(struct bridge_if *bif)
{
struct tp_entry *te;
syslog(LOG_ERR, "Addresses count - %d", bif->num_addrs);
for (te = bridge_addrs_bif_first(bif); te != NULL;
te = bridge_addrs_bif_next(te)) {
syslog(LOG_ERR, "address %x:%x:%x:%x:%x:%x on port %d.%d",
te->tp_addr[0], te->tp_addr[1], te->tp_addr[2],
te->tp_addr[3], te->tp_addr[4], te->tp_addr[5],
te->sysindex, te->port_no);
}
}
/*
* RFC4188 specifics.
*/
/*
* Construct the SNMP index from the address DST Mac.
*/
static void
bridge_addrs_index_append(struct asn_oid *oid, uint sub,
const struct tp_entry *te)
{
int i;
oid->len = sub + ETHER_ADDR_LEN + 1;
oid->subs[sub] = ETHER_ADDR_LEN;
for (i = 1; i <= ETHER_ADDR_LEN; i++)
oid->subs[sub + i] = te->tp_addr[i - 1];
}
/*
* Find the address entry for the SNMP index from the default bridge only.
*/
static struct tp_entry *
bridge_addrs_get(const struct asn_oid *oid, uint sub,
struct bridge_if *bif)
{
int i;
uint8_t tp_addr[ETHER_ADDR_LEN];
if (oid->len - sub != ETHER_ADDR_LEN + 1 ||
oid->subs[sub] != ETHER_ADDR_LEN)
return (NULL);
for (i = 0; i < ETHER_ADDR_LEN; i++)
tp_addr[i] = oid->subs[sub + i + 1];
return (bridge_addrs_find(tp_addr, bif));
}
/*
* Find the next address entry for the SNMP index
* from the default bridge only.
*/
static struct tp_entry *
bridge_addrs_getnext(const struct asn_oid *oid, uint sub,
struct bridge_if *bif)
{
int i;
uint8_t tp_addr[ETHER_ADDR_LEN];
static struct tp_entry *te;
if (oid->len - sub == 0)
return (bridge_addrs_bif_first(bif));
if (oid->len - sub != ETHER_ADDR_LEN + 1 ||
oid->subs[sub] != ETHER_ADDR_LEN)
return (NULL);
for (i = 0; i < ETHER_ADDR_LEN; i++)
tp_addr[i] = oid->subs[sub + i + 1];
if ((te = bridge_addrs_find(tp_addr, bif)) == NULL)
return (NULL);
return (bridge_addrs_bif_next(te));
}
int
op_dot1d_tp_fdb(struct snmp_context *c __unused, struct snmp_value *val,
uint sub, uint iidx __unused, enum snmp_op op)
{
struct bridge_if *bif;
struct tp_entry *te;
if ((bif = bridge_get_default()) == NULL)
return (SNMP_ERR_NOSUCHNAME);
if (time(NULL) - bif->addrs_age > bridge_get_data_maxage() &&
bridge_update_addrs(bif) <= 0)
return (SNMP_ERR_NOSUCHNAME);
switch (op) {
case SNMP_OP_GET:
if ((te = bridge_addrs_get(&val->var, sub, bif)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
goto get;
case SNMP_OP_GETNEXT:
if ((te = bridge_addrs_getnext(&val->var, sub, bif)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
bridge_addrs_index_append(&val->var, sub, te);
goto get;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
break;
}
abort();
get:
switch (val->var.subs[sub - 1]) {
case LEAF_dot1dTpFdbAddress:
return (string_get(val, te->tp_addr, ETHER_ADDR_LEN));
case LEAF_dot1dTpFdbPort :
val->v.integer = te->port_no;
return (SNMP_ERR_NOERROR);
case LEAF_dot1dTpFdbStatus:
val->v.integer = te->status;
return (SNMP_ERR_NOERROR);
}
abort();
}
/*
* Private BEGEMOT-BRIDGE-MIB specifics.
*/
/*
* Construct the SNMP index from the bridge interface name
* and the address DST Mac.
*/
static int
bridge_addrs_begemot_index_append(struct asn_oid *oid, uint sub,
const struct tp_entry *te)
{
uint i, n_len;
const char *b_name;
if ((b_name = bridge_if_find_name(te->sysindex)) == NULL)
return (-1);
n_len = strlen(b_name);
oid->len = sub++;
oid->subs[oid->len++] = n_len;
for (i = 1; i <= n_len; i++)
oid->subs[oid->len++] = b_name[i - 1];
oid->subs[oid->len++] = ETHER_ADDR_LEN;
for (i = 1 ; i <= ETHER_ADDR_LEN; i++)
oid->subs[oid->len++] = te->tp_addr[i - 1];
return (0);
}
/*
* Find a bridge address entry by the bridge interface name
* and the address DST Mac.
*/
static struct tp_entry *
bridge_addrs_begemot_get(const struct asn_oid *oid, uint sub)
{
uint i, n_len;
uint8_t tp_addr[ETHER_ADDR_LEN];
char bif_name[IFNAMSIZ];
struct bridge_if *bif;
n_len = oid->subs[sub];
if (oid->len - sub != n_len + ETHER_ADDR_LEN + 3 ||
n_len >= IFNAMSIZ || oid->subs[sub + n_len + 1] != ETHER_ADDR_LEN)
return (NULL);
for (i = 0; i < n_len; i++)
bif_name[i] = oid->subs[n_len + i + 1];
bif_name[i] = '\0';
for (i = 1; i <= ETHER_ADDR_LEN; i++)
tp_addr[i - 1] = oid->subs[n_len + i + 1];
if ((bif = bridge_if_find_ifname(bif_name)) == NULL)
return (NULL);
return (bridge_addrs_find(tp_addr, bif));
}
/*
* Find the next bridge address entry by the bridge interface name
* and the address DST Mac.
*/
static struct tp_entry *
bridge_addrs_begemot_getnext(const struct asn_oid *oid, uint sub)
{
uint i, n_len;
uint8_t tp_addr[ETHER_ADDR_LEN];
char bif_name[IFNAMSIZ];
struct bridge_if *bif;
struct tp_entry *tp;
if (oid->len - sub == 0)
return (bridge_addrs_first());
n_len = oid->subs[sub];
if (oid->len - sub != n_len + ETHER_ADDR_LEN + 2 ||
n_len >= IFNAMSIZ || oid->subs[sub + n_len + 1] != ETHER_ADDR_LEN)
return (NULL);
for (i = 1; i <= n_len; i++)
bif_name[i - 1] = oid->subs[sub + i];
bif_name[i - 1] = '\0';
for (i = 1; i <= ETHER_ADDR_LEN; i++)
tp_addr[i - 1] = oid->subs[sub + n_len + i + 1];
if ((bif = bridge_if_find_ifname(bif_name)) == NULL ||
(tp = bridge_addrs_find(tp_addr, bif)) == NULL)
return (NULL);
return (bridge_addrs_next(tp));
}
int
op_begemot_tp_fdb(struct snmp_context *c __unused, struct snmp_value *val,
uint sub, uint iidx __unused, enum snmp_op op)
{
struct tp_entry *te;
if (time(NULL) - address_list_age > bridge_get_data_maxage())
bridge_update_all_addrs();
switch (op) {
case SNMP_OP_GET:
if ((te = bridge_addrs_begemot_get(&val->var, sub)) == NULL)
return (SNMP_ERR_NOSUCHNAME);
goto get;
case SNMP_OP_GETNEXT:
if ((te = bridge_addrs_begemot_getnext(&val->var,
sub)) == NULL ||
bridge_addrs_begemot_index_append(&val->var,
sub, te) < 0)
return (SNMP_ERR_NOSUCHNAME);
goto get;
case SNMP_OP_SET:
return (SNMP_ERR_NOT_WRITEABLE);
case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
break;
}
abort();
get:
switch (val->var.subs[sub - 1]) {
case LEAF_begemotBridgeTpFdbAddress:
return (string_get(val, te->tp_addr, ETHER_ADDR_LEN));
case LEAF_begemotBridgeTpFdbPort:
val->v.integer = te->port_no;
return (SNMP_ERR_NOERROR);
case LEAF_begemotBridgeTpFdbStatus:
val->v.integer = te->status;
return (SNMP_ERR_NOERROR);
}
abort();
}

View File

@ -0,0 +1,116 @@
/*-
* Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org>
* 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.
*
* Bridge MIB implementation for SNMPd.
* Bridge pfil controls.
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_mib.h>
#include <net/if_types.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <bsnmp/snmpmod.h>
#include <bsnmp/snmp_mibII.h>
#include "bridge_tree.h"
#include "bridge_snmp.h"
static int
val2snmp_truth(uint8_t val)
{
if (val == 0)
return (2);
return (1);
}
static int
snmp_truth2val(int32_t truth)
{
if (truth == 2)
return (0);
else if (truth == 1)
return (1);
return (-1);
}
int
op_begemot_bridge_pf(struct snmp_context *ctx, struct snmp_value *val,
uint sub, uint iidx __unused, enum snmp_op op)
{
int k_val;
if (val->var.subs[sub - 1] > LEAF_begemotBridgeLayer2PfStatus)
return (SNMP_ERR_NOSUCHNAME);
switch (op) {
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_ROLLBACK:
bridge_do_pfctl(val->var.subs[sub - 1] - 1,
op, &(ctx->scratch->int1));
return (SNMP_ERR_NOERROR);
case SNMP_OP_COMMIT:
return (SNMP_ERR_NOERROR);
case SNMP_OP_SET:
ctx->scratch->int1 =
bridge_get_pfval(val->var.subs[sub - 1]);
if ((k_val = snmp_truth2val(val->v.integer)) < 0)
return (SNMP_ERR_BADVALUE);
return (SNMP_ERR_NOERROR);
case SNMP_OP_GET:
switch (val->var.subs[sub - 1]) {
case LEAF_begemotBridgePfilStatus:
case LEAF_begemotBridgePfilMembers:
case LEAF_begemotBridgePfilIpOnly:
case LEAF_begemotBridgeLayer2PfStatus:
if (bridge_do_pfctl(val->var.subs[sub - 1] - 1,
op, &k_val) < 0)
return (SNMP_ERR_GENERR);
val->v.integer = val2snmp_truth(k_val);
return (SNMP_ERR_NOERROR);
}
abort();
}
abort();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,338 @@
/*-
* Copyright (c) 2006 Shteryana Shopova <syrinx@FreeBSD.org>
* 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.
*
* Bridge MIB implementation for SNMPd.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_mib.h>
#include <net/if_types.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <bsnmp/snmpmod.h>
#include <bsnmp/snmp_mibII.h>
#include "bridge_tree.h"
#include "bridge_snmp.h"
#include "bridge_oid.h"
static struct lmodule *bridge_module;
/* For the registration. */
static const struct asn_oid oid_dot1Bridge = OIDX_dot1dBridge;
/* The registration. */
static uint reg_bridge;
/* Periodic timer for polling all bridges' data. */
static void *bridge_data_timer;
static void *bridge_tc_timer;
static int bridge_data_maxage = SNMP_BRIDGE_DATA_MAXAGE;
static int bridge_poll_ticks = SNMP_BRIDGE_POLL_INTERVAL * 100;
static int bridge_tc_poll_ticks = SNMP_BRIDGE_TC_POLL_INTERVAL * 100;
/*
* Our default bridge, whose info will be visible under
* the dot1dBridge subtree and functions to set/fetch it.
*/
static char bif_default_name[IFNAMSIZ] = "bridge0";
static struct bridge_if *bif_default;
struct bridge_if *
bridge_get_default(void)
{
struct mibif *ifp;
if (bif_default != NULL) {
/* Walk through the mibII interface list. */
for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp))
if (strcmp(ifp->name, bif_default->bif_name) == 0)
break;
if (ifp == NULL)
bif_default = NULL;
}
return (bif_default);
}
void
bridge_set_default(struct bridge_if *bif)
{
bif_default = bif;
syslog(LOG_ERR, "Set default bridge interface to: %s",
bif == NULL ? "(none)" : bif->bif_name);
}
const char *
bridge_get_default_name(void)
{
return (bif_default_name);
}
static int
bridge_set_default_name(const char *bif_name, uint len)
{
struct bridge_if *bif;
if (len >= IFNAMSIZ)
return (-1);
bcopy(bif_name, bif_default_name, len);
bif_default_name[len] = '\0';
if ((bif = bridge_if_find_ifname(bif_default_name)) == NULL) {
bif_default = NULL;
return (0);
}
bif_default = bif;
return (1);
}
int
bridge_get_data_maxage(void)
{
return (bridge_data_maxage);
}
static void
bridge_set_poll_ticks(int poll_ticks)
{
if (bridge_data_timer != NULL)
timer_stop(bridge_data_timer);
bridge_poll_ticks = poll_ticks;
bridge_data_timer = timer_start_repeat(bridge_poll_ticks,
bridge_poll_ticks, bridge_update_all, NULL, bridge_module);
}
/*
* The bridge module configuration via SNMP.
*/
static int
bridge_default_name_save(struct snmp_context *ctx, const char *bridge_default)
{
if ((ctx->scratch->int1 = strlen(bridge_default)) >= IFNAMSIZ)
return (-1);
if ((ctx->scratch->ptr1 = malloc(IFNAMSIZ)) == NULL)
return (-1);
strncpy(ctx->scratch->ptr1, bridge_default, ctx->scratch->int1);
return (0);
}
int
op_begemot_bridge_config(struct snmp_context *ctx, struct snmp_value *val,
uint sub, uint iidx __unused, enum snmp_op op)
{
switch (op) {
case SNMP_OP_GET:
switch (val->var.subs[sub - 1]) {
case LEAF_begemotBridgeDefaultBridgeIf:
return (string_get(val, bridge_get_default_name(), -1));
case LEAF_begemotBridgeDataUpdate:
val->v.integer = bridge_data_maxage;
return (SNMP_ERR_NOERROR);
case LEAF_begemotBridgeDataPoll:
val->v.integer = bridge_poll_ticks / 100;
return (SNMP_ERR_NOERROR);
}
abort();
case SNMP_OP_GETNEXT:
abort();
case SNMP_OP_SET:
switch (val->var.subs[sub - 1]) {
case LEAF_begemotBridgeDefaultBridgeIf:
/*
* Cannot use string_save() here - requires either
* a fixed-sized or var-length string - not less
* than or equal.
*/
if (bridge_default_name_save(ctx,
bridge_get_default_name()) < 0)
return (SNMP_ERR_RES_UNAVAIL);
if (bridge_set_default_name(val->v.octetstring.octets,
val->v.octetstring.len) < 0)
return (SNMP_ERR_BADVALUE);
return (SNMP_ERR_NOERROR);
case LEAF_begemotBridgeDataUpdate:
if (val->v.integer < SNMP_BRIDGE_DATA_MAXAGE_MIN ||
val->v.integer > SNMP_BRIDGE_DATA_MAXAGE_MAX)
return (SNMP_ERR_WRONG_VALUE);
ctx->scratch->int1 = bridge_data_maxage;
bridge_data_maxage = val->v.integer;
return (SNMP_ERR_NOERROR);
case LEAF_begemotBridgeDataPoll:
if (val->v.integer < SNMP_BRIDGE_POLL_INTERVAL_MIN ||
val->v.integer > SNMP_BRIDGE_POLL_INTERVAL_MAX)
return (SNMP_ERR_WRONG_VALUE);
ctx->scratch->int1 = val->v.integer;
return (SNMP_ERR_NOERROR);
}
abort();
case SNMP_OP_ROLLBACK:
switch (val->var.subs[sub - 1]) {
case LEAF_begemotBridgeDefaultBridgeIf:
bridge_set_default_name(ctx->scratch->ptr1,
ctx->scratch->int1);
free(ctx->scratch->ptr1);
break;
case LEAF_begemotBridgeDataUpdate:
bridge_data_maxage = ctx->scratch->int1;
break;
}
return (SNMP_ERR_NOERROR);
case SNMP_OP_COMMIT:
switch (val->var.subs[sub - 1]) {
case LEAF_begemotBridgeDefaultBridgeIf:
free(ctx->scratch->ptr1);
break;
case LEAF_begemotBridgeDataPoll:
bridge_set_poll_ticks(ctx->scratch->int1 * 100);
break;
}
return (SNMP_ERR_NOERROR);
}
abort();
}
/*
* Bridge mib module initialization hook.
* Returns 0 on success, < 0 on error.
*/
static int
bridge_init(struct lmodule * mod, int argc __unused, char *argv[] __unused)
{
bridge_module = mod;
if (bridge_kmod_load() < 0)
return (-1);
if (bridge_ioctl_init() < 0)
return (-1);
/* Register to get creation messages for bridge interfaces. */
if (mib_register_newif(bridge_attach_newif, bridge_module)) {
syslog(LOG_ERR, "Cannot register newif function: %s",
strerror(errno));
return (-1);
}
return (0);
}
/*
* Bridge mib module finalization hook.
*/
static int
bridge_fini(void)
{
mib_unregister_newif(bridge_module);
or_unregister(reg_bridge);
if (bridge_data_timer != NULL) {
timer_stop(bridge_data_timer);
bridge_data_timer = NULL;
}
if (bridge_tc_timer != NULL) {
timer_stop(bridge_tc_timer);
bridge_tc_timer = NULL;
}
bridge_ifs_fini();
bridge_ports_fini();
bridge_addrs_fini();
return (0);
}
/*
* Bridge mib module start operation.
*/
static void
bridge_start(void)
{
reg_bridge = or_register(&oid_dot1Bridge,
"The IETF MIB for Bridges (RFC 4188).", bridge_module);
bridge_data_timer = timer_start_repeat(bridge_poll_ticks,
bridge_poll_ticks, bridge_update_all, NULL, bridge_module);
bridge_tc_timer = timer_start_repeat(bridge_tc_poll_ticks,
bridge_tc_poll_ticks, bridge_update_tc_time, NULL, bridge_module);
}
static void
bridge_dump(void)
{
struct bridge_if *bif;
if ((bif = bridge_get_default()) == NULL)
syslog(LOG_ERR, "Dump: no default bridge interface");
else
syslog(LOG_ERR, "Dump: default bridge interface %s",
bif->bif_name);
bridge_ifs_dump();
bridge_pf_dump();
}
const struct snmp_module config = {
.comment = "This module implements the bridge mib (RFC 4188).",
.init = bridge_init,
.fini = bridge_fini,
.start = bridge_start,
.tree = bridge_ctree,
.dump = bridge_dump,
.tree_size = bridge_CTREE_SIZE,
};