Adding eshconfig, used to configure esh (HIPPI network interface)
This commit is contained in:
parent
e30b76288b
commit
d073a8144e
@ -1,11 +1,11 @@
|
||||
# $NetBSD: Makefile,v 1.91 1998/03/15 01:16:32 lukem Exp $
|
||||
# $NetBSD: Makefile,v 1.92 1998/05/16 18:55:17 kml Exp $
|
||||
# from: @(#)Makefile 5.20 (Berkeley) 6/12/93
|
||||
#
|
||||
# not yet done: catman
|
||||
|
||||
SUBDIR= ac accton amd apm apmd arp bad144 bootp \
|
||||
chown chroot chrtbl config cron dbsym dev_mkdb \
|
||||
dhcp diskpart dumpfs dumplfs edquota eeprom grfconfig \
|
||||
dhcp diskpart dumpfs dumplfs edquota eeprom eshconfig grfconfig \
|
||||
grfinfo gspa hilinfo inetd iostat ipf iteconfig kgmon \
|
||||
kvm_mkdb lastlogin lpr map-mbone mdconfig mdsetimage \
|
||||
mopd mountd mrinfo mrouted mtrace mtree named \
|
||||
|
6
usr.sbin/eshconfig/Makefile
Normal file
6
usr.sbin/eshconfig/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# $NetBSD: Makefile,v 1.1 1998/05/16 18:55:17 kml Exp $
|
||||
|
||||
PROG= eshconfig
|
||||
MAN= eshconfig.8
|
||||
|
||||
.include <bsd.prog.mk>
|
119
usr.sbin/eshconfig/eshconfig.8
Normal file
119
usr.sbin/eshconfig/eshconfig.8
Normal file
@ -0,0 +1,119 @@
|
||||
.\" $NetBSD: eshconfig.8,v 1.1 1998/05/16 18:55:18 kml Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
.\" by Kevin Lahey of the Numerical Aerospace Simulation Facility,
|
||||
.\" NASA Ames Research Center.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.Dd February 3, 1998
|
||||
.Dt ESHCONFIG 8
|
||||
.Os NetBSD 1.4
|
||||
.Sh NAME
|
||||
.Nm eshconfig
|
||||
.Nd configure Essential Communications' HIPPI network interface
|
||||
.Sh SYNOPSIS
|
||||
.Nm eshconfig
|
||||
.Op Fl b Ar bytes
|
||||
.Op Fl c Ar bytes
|
||||
.Op Fl d Ar filename
|
||||
.Op Fl e
|
||||
.Op Fl m Ar bytes
|
||||
.Op Fl r Ar bytes
|
||||
.Op Fl s
|
||||
.Op Fl t
|
||||
.Op Fl u Ar filename
|
||||
.Op Fl w Ar bytes
|
||||
.Op Ar interface
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is used to configure device-specific parameters and download new firmware
|
||||
to the Essential Communications RoadRunner-based HIPPI network interface.
|
||||
The interface is very sensitive to the DMA performance characteristics
|
||||
of the host, and so requires careful tuning to achieve reasonable
|
||||
performance.
|
||||
In addition, firmware is likely to change frequently, which necessitates
|
||||
a reasonably easy way to update that firmware.
|
||||
.Pp
|
||||
Available operands for
|
||||
.Nm eshconfig :
|
||||
.Bl -tag -width Ds
|
||||
.It Fl b
|
||||
Adjust the burst size for read (by NIC of host memory) DMA.
|
||||
.It Fl c
|
||||
Adjust the burst size for write (by NIC of host memory) DMA.
|
||||
.It Fl d
|
||||
Filename for file to download into NIC firmware.
|
||||
This must be a file in the standard Essential format, with :04 preceding
|
||||
every line, and a tag line at the end indicating the characteristics
|
||||
of the firmware file.
|
||||
.It Fl e
|
||||
Write data to EEPROM.
|
||||
Normally, setting tuning parameters will only persist until the
|
||||
system is rebooted.
|
||||
Setting this parameter ensures that the changes will be written to
|
||||
EEPROM.
|
||||
.It Fl m
|
||||
Minimum number of bytes to DMA in one direction (read or write)
|
||||
before allowing a DMA in the other direction. Tuning this prevents
|
||||
one direction from dominating the flow of bytes, and artificially
|
||||
throttling the NIC.
|
||||
.It Fl r
|
||||
Bytes before DMA starts for read (from host to NIC).
|
||||
This controls how soon the DMA is triggered; until this many bytes
|
||||
are requested, the DMA will not begin.
|
||||
.It Fl s
|
||||
Show statistics for the HIPPI NIC.
|
||||
Repeat the option to suppress non-zero statistics.
|
||||
.It Fl t
|
||||
Show current tuning parameters on the host.
|
||||
.It Fl u
|
||||
Name of file to which the NIC firmware should be uploaded.
|
||||
Not currently supported.
|
||||
.It Fl w
|
||||
Number of bytes required before write (from NIC to host) DMA
|
||||
is started.
|
||||
Until this many bytes are ready to be written, the DMA will not start.
|
||||
.Pp
|
||||
Only the super-user may modify the configuration of a network interface.
|
||||
.Sh DIAGNOSTICS
|
||||
Messages indicating the specified interface does not exist
|
||||
or the user is not privileged and
|
||||
tried to alter an interface's configuration.
|
||||
.Sh SEE ALSO
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr esh 4
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.Bx NetBSD 1.4.
|
750
usr.sbin/eshconfig/eshconfig.c
Normal file
750
usr.sbin/eshconfig/eshconfig.c
Normal file
@ -0,0 +1,750 @@
|
||||
/* $NetBSD: eshconfig.c,v 1.1 1998/05/16 18:55:18 kml Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code contributed to The NetBSD Foundation by Kevin M. Lahey
|
||||
* of the Numerical Aerospace Simulation Facility, NASA Ames Research
|
||||
* Center.
|
||||
*
|
||||
* 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>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: eshconfig.c,v 1.1 1998/05/16 18:55:18 kml Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <dev/ic/rrunnerreg.h>
|
||||
#include <dev/ic/rrunnervar.h>
|
||||
|
||||
/*
|
||||
* Create a simple pair of tables to map possible burst DMA values
|
||||
* to the values required by the RoadRunner.
|
||||
*/
|
||||
|
||||
struct map_dma {
|
||||
int value;
|
||||
u_int32_t rr_value;
|
||||
};
|
||||
|
||||
struct map_dma read_dma_map[] = {{0, RR_PS_READ_DISABLE},
|
||||
{4, RR_PS_READ_4},
|
||||
{16, RR_PS_READ_16},
|
||||
{32, RR_PS_READ_32},
|
||||
{64, RR_PS_READ_64},
|
||||
{128, RR_PS_READ_128},
|
||||
{256, RR_PS_READ_256},
|
||||
{1024, RR_PS_READ_1024},
|
||||
{-1, 0}};
|
||||
|
||||
struct map_dma write_dma_map[] = {{0, RR_PS_WRITE_DISABLE},
|
||||
{4, RR_PS_WRITE_4},
|
||||
{16, RR_PS_WRITE_16},
|
||||
{32, RR_PS_WRITE_32},
|
||||
{64, RR_PS_WRITE_64},
|
||||
{128, RR_PS_WRITE_128},
|
||||
{256, RR_PS_WRITE_256},
|
||||
{1024, RR_PS_WRITE_1024},
|
||||
{-1, 0}};
|
||||
|
||||
/*
|
||||
* The RunCode is composed of separate segments, each of which has a
|
||||
* starting address in SRAM memory (for running) and in EEPROM
|
||||
* (for storage).
|
||||
*/
|
||||
|
||||
|
||||
struct rr_seg_descr {
|
||||
u_int32_t start_addr;
|
||||
u_int32_t length;
|
||||
u_int32_t ee_addr;
|
||||
};
|
||||
|
||||
static u_int32_t do_map __P((int, struct map_dma *));
|
||||
static void eeprom_upload __P((const char *));
|
||||
static void eeprom_download __P((const char *));
|
||||
static u_int32_t rr_checksum __P((const u_int32_t *, int));
|
||||
static void esh_tune __P((void));
|
||||
static void esh_tune_eeprom __P((void));
|
||||
static void esh_tuning_stats __P((void));
|
||||
static void esh_stats __P((int));
|
||||
static int drvspec_ioctl __P((char *, int, int, int, caddr_t));
|
||||
static void usage __P((void));
|
||||
int main __P((int, char *[]));
|
||||
|
||||
|
||||
struct ifreq ifr;
|
||||
char name[30] = "esh0";
|
||||
int s;
|
||||
|
||||
#define RR_EE_SIZE 8192
|
||||
u_int32_t eeprom[RR_EE_SIZE];
|
||||
u_int32_t runcode[RR_EE_SIZE];
|
||||
|
||||
struct ifdrv ifd;
|
||||
|
||||
/* drvspec_ioctl
|
||||
*
|
||||
* We defined a driver-specific socket ioctl to allow us to tweak
|
||||
* the characteristics of network devices. This routine will
|
||||
* provide a shortcut to calling this routine, which would otherwise
|
||||
* require lots of costly and annoying setup.
|
||||
*/
|
||||
|
||||
static int
|
||||
drvspec_ioctl(char *name, int fd, int cmd, int len, caddr_t data)
|
||||
{
|
||||
strcpy(ifd.ifd_name, name);
|
||||
ifd.ifd_cmd = cmd;
|
||||
ifd.ifd_len = len;
|
||||
ifd.ifd_data = data;
|
||||
|
||||
return ioctl(fd, SIOCSDRVSPEC, (caddr_t) &ifd);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "eshconfig -- configure Essential Communications "
|
||||
"HIPPI driver\n");
|
||||
fprintf(stderr, "-b burst size for read\n");
|
||||
fprintf(stderr, "-c burst size for write:\n");
|
||||
fprintf(stderr, "\t0 (no limit), 5, 16, 32, 64, 128, 256, 1024\n");
|
||||
fprintf(stderr, "-d download filename\n");
|
||||
fprintf(stderr, "-e write data to EEPROM\n");
|
||||
fprintf(stderr, "-m minimum bytes DMA per direction\n");
|
||||
fprintf(stderr, "-r bytes before DMA starts for read\n");
|
||||
fprintf(stderr, "-s show statistics (-ss to display only non-zero)\n");
|
||||
fprintf(stderr, "-t show tuning parameters\n");
|
||||
fprintf(stderr, "-u upload filename [not working]\n");
|
||||
fprintf(stderr, "-w bytes before DMA starts for write\n");
|
||||
fprintf(stderr, "-i interrupt delay in usecs\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* do_map
|
||||
*
|
||||
* Map between values for burst DMA sizes and the values expected by
|
||||
* the RoadRunner chip.
|
||||
*/
|
||||
|
||||
static u_int32_t
|
||||
do_map(int value, struct map_dma *map)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; map[i].value != -1; i++)
|
||||
if (value == map[i].value)
|
||||
return map[i].rr_value;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* do_map_dma
|
||||
*
|
||||
* Reverse the mapping.
|
||||
*/
|
||||
|
||||
static int
|
||||
do_map_dma(int value, struct map_dma *map)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; map[i].value != -1; i++)
|
||||
if (value == map[i].rr_value)
|
||||
return map[i].value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int dma_thresh_read = -1;
|
||||
int dma_thresh_write = -1;
|
||||
int dma_min_grab = -1;
|
||||
int dma_max_read = -1;
|
||||
int dma_max_write = -1;
|
||||
|
||||
int interrupt_delay = -1;
|
||||
|
||||
int get_stats = 0;
|
||||
int get_tuning_stats = 0;
|
||||
int eeprom_write = 0;
|
||||
char *eeprom_download_filename = NULL;
|
||||
char *eeprom_upload_filename = NULL;
|
||||
|
||||
struct rr_tuning rr_tune;
|
||||
struct rr_eeprom rr_eeprom;
|
||||
struct rr_stats rr_stats;
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
int ch;
|
||||
|
||||
/* Parse command-line options */
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:c:d:ei:m:r:stu:w:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
dma_max_read = atoi(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
dma_max_write = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
eeprom_download_filename = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
eeprom_write++;
|
||||
break;
|
||||
case 'i':
|
||||
interrupt_delay = atoi(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
dma_min_grab = atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
dma_thresh_read = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
get_stats++;
|
||||
break;
|
||||
case 't':
|
||||
get_tuning_stats++;
|
||||
break;
|
||||
case 'u':
|
||||
eeprom_upload_filename = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
dma_thresh_write = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 1)
|
||||
usage();
|
||||
if (argc == 1) {
|
||||
(void) strncpy(name, argv[0], sizeof(name));
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
err(1, "socket");
|
||||
|
||||
if (eeprom_upload_filename)
|
||||
eeprom_upload(eeprom_upload_filename);
|
||||
|
||||
if (eeprom_download_filename)
|
||||
eeprom_download(eeprom_download_filename);
|
||||
|
||||
if (get_stats) {
|
||||
esh_stats(get_stats);
|
||||
}
|
||||
|
||||
if (drvspec_ioctl(name, s, EIOCGTUNE, sizeof(struct rr_tuning),
|
||||
(caddr_t) &rr_tune) < 0) {
|
||||
err(1, "ioctl(EIOCGTUNE)");
|
||||
}
|
||||
|
||||
if (get_tuning_stats) {
|
||||
if (get_stats)
|
||||
printf("\n");
|
||||
esh_tuning_stats();
|
||||
}
|
||||
|
||||
if (eeprom_write || dma_thresh_read != -1 ||
|
||||
dma_thresh_write != -1 ||
|
||||
dma_min_grab != -1 ||
|
||||
dma_max_read != -1 ||
|
||||
dma_max_write != -1 ||
|
||||
interrupt_delay != -1) {
|
||||
esh_tune();
|
||||
}
|
||||
|
||||
if (eeprom_write)
|
||||
esh_tune_eeprom();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
esh_tune()
|
||||
{
|
||||
dma_max_read = do_map(dma_max_read, read_dma_map);
|
||||
if (dma_max_read != -1) {
|
||||
rr_tune.rt_pci_state &= ~RR_PS_READ_MASK;
|
||||
rr_tune.rt_pci_state |= dma_max_read;
|
||||
}
|
||||
|
||||
dma_max_write = do_map(dma_max_write, write_dma_map);
|
||||
if (dma_max_write != -1) {
|
||||
rr_tune.rt_pci_state &= ~RR_PS_WRITE_MASK;
|
||||
rr_tune.rt_pci_state |= dma_max_write;
|
||||
}
|
||||
|
||||
if (dma_min_grab != -1) {
|
||||
if ((dma_min_grab & (RR_PS_MIN_DMA_MASK >> RR_PS_MIN_DMA_SHIFT))
|
||||
!= dma_min_grab)
|
||||
usage();
|
||||
rr_tune.rt_pci_state &= ~RR_PS_MIN_DMA_MASK;
|
||||
rr_tune.rt_pci_state |=
|
||||
(dma_min_grab << RR_PS_MIN_DMA_SHIFT);
|
||||
}
|
||||
|
||||
if (dma_thresh_write != -1) {
|
||||
if (dma_thresh_write < 1 || dma_thresh_write > RR_DW_THRESHOLD_MAX)
|
||||
usage();
|
||||
rr_tune.rt_dma_write_state &= ~RR_DW_THRESHOLD_MASK;
|
||||
rr_tune.rt_dma_write_state |=
|
||||
dma_thresh_write << RR_DW_THRESHOLD_SHIFT;
|
||||
}
|
||||
|
||||
if (dma_thresh_read != -1) {
|
||||
if (dma_thresh_read < 1 || dma_thresh_read > RR_DR_THRESHOLD_MAX)
|
||||
usage();
|
||||
rr_tune.rt_dma_read_state &= ~RR_DR_THRESHOLD_MASK;
|
||||
rr_tune.rt_dma_read_state |=
|
||||
dma_thresh_read << RR_DR_THRESHOLD_SHIFT;
|
||||
}
|
||||
|
||||
rr_tune.rt_stats_timer = ESH_STATS_TIMER_DEFAULT;
|
||||
|
||||
if (interrupt_delay != -1)
|
||||
rr_tune.rt_interrupt_timer = interrupt_delay;
|
||||
|
||||
if (drvspec_ioctl(name, s, EIOCSTUNE, sizeof(struct rr_tuning),
|
||||
(caddr_t) &rr_tune) < 0)
|
||||
err(1, "EIOCSTUNE");
|
||||
}
|
||||
|
||||
/* esh_tune_eeprom
|
||||
*
|
||||
* Store the current tuning data into the eeprom.
|
||||
*/
|
||||
|
||||
static void
|
||||
esh_tune_eeprom()
|
||||
{
|
||||
#define LAST (RR_EE_HEADER_CHECKSUM / RR_EE_WORD_LEN)
|
||||
#define FIRST (RR_EE_HEADER_CHECKSUM / RR_EE_WORD_LEN)
|
||||
|
||||
u_int32_t tuning_data[LAST + 1];
|
||||
|
||||
rr_eeprom.ifr_buffer = tuning_data;
|
||||
rr_eeprom.ifr_length = sizeof(tuning_data);
|
||||
rr_eeprom.ifr_offset = 0;
|
||||
|
||||
if (drvspec_ioctl(name, s, EIOCGEEPROM, sizeof(struct rr_eeprom),
|
||||
(caddr_t) &rr_eeprom) == -1)
|
||||
err(6, "ioctl to retrieve tuning information from EEPROM");
|
||||
|
||||
tuning_data[RR_EE_PCI_STATE / RR_EE_WORD_LEN] =
|
||||
rr_tune.rt_pci_state;
|
||||
tuning_data[RR_EE_DMA_WRITE_STATE / RR_EE_WORD_LEN] =
|
||||
rr_tune.rt_dma_write_state;
|
||||
tuning_data[RR_EE_DMA_READ_STATE / RR_EE_WORD_LEN] =
|
||||
rr_tune.rt_dma_read_state;
|
||||
tuning_data[RR_EE_INTERRUPT_TIMER / RR_EE_WORD_LEN] = rr_tune.rt_interrupt_timer;
|
||||
tuning_data[RR_EE_STATS_TIMER / RR_EE_WORD_LEN] =
|
||||
ESH_STATS_TIMER_DEFAULT;
|
||||
|
||||
tuning_data[RR_EE_HEADER_CHECKSUM / RR_EE_WORD_LEN] =
|
||||
rr_checksum(&tuning_data[FIRST], LAST - FIRST);
|
||||
|
||||
rr_eeprom.ifr_buffer = tuning_data;
|
||||
rr_eeprom.ifr_length = sizeof(tuning_data);
|
||||
rr_eeprom.ifr_offset = 0;
|
||||
|
||||
if (drvspec_ioctl(name, s, EIOCSEEPROM, sizeof(struct rr_eeprom),
|
||||
(caddr_t) &rr_eeprom) == -1)
|
||||
err(7, "ioctl to set tuning information from EEPROM");
|
||||
}
|
||||
|
||||
/* eeprom_upload
|
||||
*
|
||||
* Upload the EEPROM from the card and store in the data file.
|
||||
*/
|
||||
|
||||
static void
|
||||
eeprom_upload(const char *filename)
|
||||
{
|
||||
int fd;
|
||||
|
||||
bzero(eeprom, sizeof(eeprom));
|
||||
if ((fd = open(filename, O_WRONLY | O_CREAT, 0644)) < 0)
|
||||
err(4, "Couldn't open %s for output", filename);
|
||||
|
||||
rr_eeprom.ifr_buffer = eeprom;
|
||||
rr_eeprom.ifr_length = sizeof(eeprom);
|
||||
rr_eeprom.ifr_offset = 0;
|
||||
|
||||
if (drvspec_ioctl(name, s, EIOCGEEPROM, sizeof(struct rr_eeprom),
|
||||
(caddr_t) &rr_eeprom) == -1)
|
||||
err(5, "ioctl to retrieve all of EEPROM");
|
||||
|
||||
write(fd, eeprom, sizeof(eeprom));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* eeprom_download
|
||||
*
|
||||
* Download into eeprom the contents of a file. The file is made up
|
||||
* of ASCII text; the first three characters can be ignored, the next
|
||||
* four hex characters define an address, the next two characters can
|
||||
* be ignored, and the final eight hex characters are the data.
|
||||
*/
|
||||
|
||||
static void
|
||||
eeprom_download(const char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
struct rr_seg_descr *segd = NULL;
|
||||
char id[BUFSIZ];
|
||||
char pad[BUFSIZ];
|
||||
char buffer[BUFSIZ];
|
||||
u_int32_t address = 0;
|
||||
u_int32_t last_address = 0;
|
||||
u_int32_t value;
|
||||
u_int32_t length = 0;
|
||||
int segment_start = 0;
|
||||
int seg_table_start;
|
||||
int seg_count_offset;
|
||||
int phase2_start;
|
||||
int phase2_checksum;
|
||||
int in_segment = 0;
|
||||
int segment = 0;
|
||||
int eof = 0;
|
||||
int line = 0;
|
||||
int zero_count = 0;
|
||||
int i;
|
||||
|
||||
/* Clear out eeprom storage space, then read in the value on the card */
|
||||
|
||||
bzero(eeprom, sizeof(eeprom));
|
||||
bzero(runcode, sizeof(runcode));
|
||||
|
||||
rr_eeprom.ifr_buffer = eeprom;
|
||||
rr_eeprom.ifr_length = sizeof(eeprom);
|
||||
rr_eeprom.ifr_offset = 0;
|
||||
if (drvspec_ioctl(name, s, EIOCGEEPROM, sizeof(struct rr_eeprom),
|
||||
(caddr_t) &rr_eeprom) == -1)
|
||||
err(5, "ioctl to retrieve EEPROM");
|
||||
|
||||
/*
|
||||
* Open the input file and proceed to read the data file, storing
|
||||
* the data and counting the number of segments.
|
||||
*/
|
||||
|
||||
if ((fp = fopen(filename, "r")) == NULL)
|
||||
err(2, "fopen");
|
||||
|
||||
do {
|
||||
if (fgets(buffer, sizeof(buffer), fp) == NULL)
|
||||
errx(3, "premature, unmarked end of file, line %d", line);
|
||||
line++;
|
||||
|
||||
if (!strncmp(buffer + 7, "01", 2)) { /* check for EOF marker... */
|
||||
eof = 1;
|
||||
} else {
|
||||
sscanf(buffer, "%3s%4x%2s%8x%2s",
|
||||
id, &address, pad, &value, pad);
|
||||
if (strcmp(id, ":04") != 0)
|
||||
errx(3, "bad initial id on line %d", line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if we terminated a segment; this happens
|
||||
* when we are at end of file, or we hit a non-sequential
|
||||
* address value, or we see three or more zeroes in a row.
|
||||
*/
|
||||
|
||||
if ((length == RR_EE_SEG_SIZE || eof || zero_count >= 3 ||
|
||||
(last_address && last_address != address - 1)) && in_segment) {
|
||||
|
||||
length -= zero_count;
|
||||
segment_start += length;
|
||||
segd[segment].length = length;
|
||||
|
||||
printf("segment %d, %d words\n", segment, length);
|
||||
last_address = in_segment = zero_count = length = 0;
|
||||
segment++;
|
||||
}
|
||||
|
||||
if (eof)
|
||||
break;
|
||||
|
||||
/* Skip zero values starting a segment */
|
||||
|
||||
if (!in_segment && value == 0)
|
||||
continue;
|
||||
last_address = address;
|
||||
|
||||
/*
|
||||
* If we haven't started a segment yet, do so now.
|
||||
* Store away the address at which this code should be placed
|
||||
* in memory and the address of the code in the EEPROM.
|
||||
*/
|
||||
|
||||
if (!in_segment) {
|
||||
in_segment = 1;
|
||||
|
||||
segd = realloc(segd, sizeof(struct rr_seg_descr) * (segment + 1));
|
||||
if (segd == NULL)
|
||||
err(6, "couldn't realloc segment descriptor space");
|
||||
|
||||
segd[segment].start_addr = address * sizeof(u_int32_t);
|
||||
segd[segment].ee_addr = segment_start;
|
||||
}
|
||||
|
||||
/* Keep track of consecutive zeroes */
|
||||
|
||||
if (in_segment && value == 0)
|
||||
zero_count++;
|
||||
else
|
||||
zero_count = 0;
|
||||
|
||||
/* Store away the actual data */
|
||||
|
||||
runcode[segment_start + length++] = value;
|
||||
} while (!eof);
|
||||
fclose(fp);
|
||||
|
||||
/* Now that we have a segment count, fill in the EEPROM image. */
|
||||
|
||||
seg_count_offset = eeprom[RR_EE_RUNCODE_SEGMENTS / RR_EE_WORD_LEN];
|
||||
seg_count_offset = (seg_count_offset - RR_EE_OFFSET) / RR_EE_WORD_LEN;
|
||||
seg_table_start = seg_count_offset + 1;
|
||||
phase2_checksum = seg_table_start + 3 * segment;
|
||||
phase2_start = eeprom[RR_EE_PHASE2_EE_START / RR_EE_WORD_LEN];
|
||||
phase2_start = (phase2_start - RR_EE_OFFSET) / RR_EE_WORD_LEN;
|
||||
|
||||
printf("segment table start = %x, segments = %d\n",
|
||||
seg_table_start, eeprom[seg_count_offset]);
|
||||
|
||||
/* We'll fill in anything after the segment count, so clear it */
|
||||
|
||||
bzero(eeprom + seg_count_offset,
|
||||
sizeof(eeprom) - seg_count_offset * sizeof(eeprom[0]));
|
||||
|
||||
eeprom[seg_count_offset] = segment;
|
||||
|
||||
for (i = 0; i < segment; i++)
|
||||
segd[i].ee_addr = RR_EE_OFFSET +
|
||||
(segd[i].ee_addr + phase2_checksum + 1) * RR_EE_WORD_LEN;
|
||||
|
||||
bcopy(segd, &eeprom[seg_table_start],
|
||||
sizeof(struct rr_seg_descr) * segment);
|
||||
|
||||
bcopy(runcode, &eeprom[phase2_checksum + 1],
|
||||
segment_start * sizeof(u_int32_t));
|
||||
|
||||
eeprom[phase2_checksum] = rr_checksum(&eeprom[phase2_start],
|
||||
phase2_checksum - phase2_start);
|
||||
|
||||
eeprom[segment_start + phase2_checksum + 1] =
|
||||
rr_checksum(&eeprom[phase2_checksum + 1], segment_start);
|
||||
|
||||
printf("phase2 checksum %x, runcode checksum %x\n",
|
||||
eeprom[phase2_checksum],
|
||||
eeprom[segment_start + phase2_checksum + 1]);
|
||||
|
||||
rr_eeprom.ifr_buffer = eeprom;
|
||||
rr_eeprom.ifr_length = sizeof(eeprom);
|
||||
rr_eeprom.ifr_offset = 0;
|
||||
if (drvspec_ioctl(name, s, EIOCSEEPROM, sizeof(struct rr_eeprom),
|
||||
(caddr_t) &rr_eeprom) == -1)
|
||||
err(5, "ioctl to retrieve EEPROM");
|
||||
}
|
||||
|
||||
/* rr_checksum
|
||||
*
|
||||
* Perform checksum on RunCode. Length is in words. Ugh.
|
||||
*/
|
||||
|
||||
static u_int32_t
|
||||
rr_checksum(const u_int32_t *data, int length)
|
||||
{
|
||||
u_int32_t checksum = 0;
|
||||
|
||||
while (length--)
|
||||
checksum += *data++;
|
||||
|
||||
checksum = 0 - checksum;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
struct stats_values {
|
||||
int offset;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct stats_values stats_values[] = {
|
||||
{0x04, "receive rings created"},
|
||||
{0x08, "receive rings deleted"},
|
||||
{0x0c, "interrupts"},
|
||||
{0x10, "event overflows"},
|
||||
{0x14, "invalid commands"},
|
||||
{0x18, "DMA read errors"},
|
||||
{0x1c, "DMA write errors"},
|
||||
{0x20, "stats updates per timer"},
|
||||
{0x24, "stats updates per host"},
|
||||
{0x28, "watchdog"},
|
||||
{0x2c, "trace"},
|
||||
{0x30, "link ready sync established"},
|
||||
{0x34, "GLink errors"},
|
||||
{0x38, "alternating flag errors"},
|
||||
{0x3c, "overhead bit 8 synchronized"},
|
||||
{0x40, "remote serial parity errors"},
|
||||
{0x44, "remote parallel parity errors"},
|
||||
{0x48, "remote loopback requested"},
|
||||
{0x50, "transmit connections established"},
|
||||
{0x54, "transmit connections rejected"},
|
||||
{0x58, "transmit connections retried"},
|
||||
{0x5c, "transmit connections timed out"},
|
||||
{0x60, "transmit connections disconnected"},
|
||||
{0x64, "transmit parity errors"},
|
||||
{0x68, "packets sent"},
|
||||
{0x74, "short first burst sent"},
|
||||
{0x80, "transmit data not moving"},
|
||||
{0x90, "receive connections accepted"},
|
||||
{0x94, "receive connections rejected -- bad parity"},
|
||||
{0x98, "receive connections rejected -- 64-bit width"},
|
||||
{0x9c, "receive connections rejected -- buffers low"},
|
||||
{0xa0, "receive connections disconnected"},
|
||||
{0xa4, "receive connections with no data"},
|
||||
{0xa8, "packets received"},
|
||||
{0xb4, "short first burst received"},
|
||||
{0xc0, "receive parity error"},
|
||||
{0xc4, "receive LLRC error"},
|
||||
{0xc8, "receive burst size error"},
|
||||
{0xcc, "receive state error"},
|
||||
{0xd0, "receive ready ULP"},
|
||||
{0xd4, "receive invalid ULP"},
|
||||
{0xd8, "receive packets flow control due to buffer space"},
|
||||
{0xdc, "receive packets flow control due to descriptors"},
|
||||
{0xe0, "receive ring fulls"},
|
||||
{0xe4, "packet length errors"},
|
||||
{0xe8, "packets with checksum error"},
|
||||
{0xec, "packets dropped"},
|
||||
{0xf0, "ring low on space"},
|
||||
{0xf4, "data in ring at close"},
|
||||
{0xf8, "receives to ring not moving data"},
|
||||
{0xfc, "receiver idles"},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static void
|
||||
esh_stats(int get_stats)
|
||||
{
|
||||
u_int32_t *stats;
|
||||
long long value;
|
||||
int offset;
|
||||
|
||||
if (drvspec_ioctl(name, s, EIOCGSTATS, sizeof(struct rr_stats),
|
||||
(caddr_t) &rr_stats) < 0)
|
||||
err(1, "ioctl(EIOCGTUNE)");
|
||||
|
||||
stats = rr_stats.rs_stats;
|
||||
|
||||
value = (((long long) stats[0x78 / 4]) << 32) | stats[0x7c / 4];
|
||||
if (get_stats == 1 || value > 0)
|
||||
printf("%12qd bytes sent\n", value);
|
||||
value = ((long long) stats[0xb8 / 4] << 32) | stats[0xbc / 4];
|
||||
if (get_stats == 1 || value > 0)
|
||||
printf("%12qd bytes received\n", value);
|
||||
|
||||
for (offset = 0; stats_values[offset].offset != 0; offset++) {
|
||||
if (get_stats == 1 || stats[stats_values[offset].offset / 4] > 0)
|
||||
printf("%12d %s\n", stats[stats_values[offset].offset / 4],
|
||||
stats_values[offset].name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
esh_tuning_stats()
|
||||
{
|
||||
printf("rt_mode_and_status = %x\n",
|
||||
rr_tune.rt_mode_and_status);
|
||||
printf("rt_conn_retry_count = %x\n",
|
||||
rr_tune.rt_conn_retry_count);
|
||||
printf("rt_conn_retry_timer = %x\n",
|
||||
rr_tune.rt_conn_retry_timer);
|
||||
printf("rt_conn_timeout = %x\n", rr_tune.rt_conn_timeout);
|
||||
printf("rt_stats_timer = %x\n", rr_tune.rt_stats_timer);
|
||||
printf("rt_interrupt_timer = %x\n",
|
||||
rr_tune.rt_interrupt_timer);
|
||||
printf("rt_tx_timeout = %x\n", rr_tune.rt_tx_timeout);
|
||||
printf("rt_rx_timeout = %x\n", rr_tune.rt_rx_timeout);
|
||||
printf("rt_pci_state = %x"
|
||||
" min dma %x read max %x write max %x\n",
|
||||
rr_tune.rt_pci_state,
|
||||
(rr_tune.rt_pci_state & RR_PS_MIN_DMA_MASK)
|
||||
>> RR_PS_MIN_DMA_SHIFT,
|
||||
do_map_dma(rr_tune.rt_pci_state & RR_PS_READ_MASK,
|
||||
read_dma_map),
|
||||
do_map_dma(rr_tune.rt_pci_state & RR_PS_WRITE_MASK,
|
||||
write_dma_map));
|
||||
printf("rt_dma_write_state = %x\n",
|
||||
rr_tune.rt_dma_write_state);
|
||||
printf("rt_dma_read_state = %x\n", rr_tune.rt_dma_read_state);
|
||||
printf("rt_driver_param = %x\n", rr_tune.rt_driver_param);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user