1/* $NetBSD: eshconfig.c,v 1.9 2009/04/15 05:50:20 lukem Exp $ */ 2 3/* 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code contributed to The NetBSD Foundation by Kevin M. Lahey 8 * of the Numerical Aerospace Simulation Facility, NASA Ames Research 9 * Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34#ifndef lint 35__RCSID("$NetBSD: eshconfig.c,v 1.9 2009/04/15 05:50:20 lukem Exp $"); 36#endif /* not lint */ 37 38#include <sys/param.h> 39#include <sys/socket.h> 40#include <sys/ioctl.h> 41#include <sys/sockio.h> 42#include <fcntl.h> 43 44#include <net/if.h> 45#include <net/if_dl.h> 46#include <net/if_media.h> 47#include <netinet/in.h> 48#include <arpa/inet.h> 49 50#include <ctype.h> 51#include <err.h> 52#include <errno.h> 53#include <stdio.h> 54#include <stdlib.h> 55#include <string.h> 56#include <unistd.h> 57 58#include <dev/ic/rrunnerreg.h> 59#include <dev/ic/rrunnervar.h> 60 61/* 62 * Create a simple pair of tables to map possible burst DMA values 63 * to the values required by the RoadRunner. 64 */ 65 66struct map_dma { 67 int value; 68 u_int32_t rr_value; 69}; 70 71static struct map_dma read_dma_map[] = {{0, RR_PS_READ_DISABLE}, 72 {4, RR_PS_READ_4}, 73 {16, RR_PS_READ_16}, 74 {32, RR_PS_READ_32}, 75 {64, RR_PS_READ_64}, 76 {128, RR_PS_READ_128}, 77 {256, RR_PS_READ_256}, 78 {1024, RR_PS_READ_1024}, 79 {-1, 0}}; 80 81static struct map_dma write_dma_map[] = {{0, RR_PS_WRITE_DISABLE}, 82 {4, RR_PS_WRITE_4}, 83 {16, RR_PS_WRITE_16}, 84 {32, RR_PS_WRITE_32}, 85 {64, RR_PS_WRITE_64}, 86 {128, RR_PS_WRITE_128}, 87 {256, RR_PS_WRITE_256}, 88 {1024, RR_PS_WRITE_1024}, 89 {-1, 0}}; 90 91/* 92 * The RunCode is composed of separate segments, each of which has a 93 * starting address in SRAM memory (for running) and in EEPROM 94 * (for storage). 95 */ 96 97 98struct rr_seg_descr { 99 u_int32_t start_addr; 100 u_int32_t length; 101 u_int32_t ee_addr; 102}; 103 104static u_int32_t do_map(int, struct map_dma *); 105static void eeprom_upload(const char *); 106static void eeprom_download(const char *); 107static u_int32_t rr_checksum(const u_int32_t *, int); 108static void esh_tune(void); 109static void esh_tune_eeprom(void); 110static void esh_tuning_stats(void); 111static void esh_stats(int); 112static void esh_reset(void); 113static int drvspec_ioctl(char *, int, int, int, caddr_t); 114__dead static void usage(void); 115 116static char name[30] = "esh0"; 117static int s; 118 119#define RR_EE_SIZE 8192 120static u_int32_t eeprom[RR_EE_SIZE]; 121static u_int32_t runcode[RR_EE_SIZE]; 122 123static struct ifdrv ifd; 124 125/* drvspec_ioctl 126 * 127 * We defined a driver-specific socket ioctl to allow us to tweak 128 * the characteristics of network devices. This routine will 129 * provide a shortcut to calling this routine, which would otherwise 130 * require lots of costly and annoying setup. 131 */ 132 133static int 134drvspec_ioctl(char *lname, int fd, int cmd, int len, caddr_t data) 135{ 136 strcpy(ifd.ifd_name, lname); 137 ifd.ifd_cmd = cmd; 138 ifd.ifd_len = len; 139 ifd.ifd_data = data; 140 141 return ioctl(fd, SIOCSDRVSPEC, (caddr_t) &ifd); 142} 143 144static void 145usage(void) 146{ 147 fprintf(stderr, "eshconfig -- configure Essential Communications " 148 "HIPPI driver\n"); 149 fprintf(stderr, "-b burst size for read\n"); 150 fprintf(stderr, "-c burst size for write:\n"); 151 fprintf(stderr, "\t0 (no limit), 5, 16, 32, 64, 128, 256, 1024\n"); 152 fprintf(stderr, "-d download filename\n"); 153 fprintf(stderr, "-e write data to EEPROM\n"); 154 fprintf(stderr, "-m minimum bytes DMA per direction\n"); 155 fprintf(stderr, "-r bytes before DMA starts for read\n"); 156 fprintf(stderr, "-s show statistics (-ss to display only non-zero)\n"); 157 fprintf(stderr, "-t show tuning parameters\n"); 158 fprintf(stderr, "-u upload filename [not working]\n"); 159 fprintf(stderr, "-w bytes before DMA starts for write\n"); 160 fprintf(stderr, "-i interrupt delay in usecs\n"); 161 fprintf(stderr, "-x reset interface\n"); 162 exit(1); 163} 164 165/* do_map 166 * 167 * Map between values for burst DMA sizes and the values expected by 168 * the RoadRunner chip. 169 */ 170 171static u_int32_t 172do_map(int value, struct map_dma *map) 173{ 174 int i; 175 176 for (i = 0; map[i].value != -1; i++) 177 if (value == map[i].value) 178 return map[i].rr_value; 179 180 return -1; 181} 182 183/* do_map_dma 184 * 185 * Reverse the mapping. 186 */ 187 188static int 189do_map_dma(uint32_t value, struct map_dma *map) 190{ 191 int i; 192 193 for (i = 0; map[i].value != -1; i++) 194 if (value == map[i].rr_value) 195 return map[i].value; 196 197 return 0; 198} 199 200 201static int dma_thresh_read = -1; 202static int dma_thresh_write = -1; 203static int dma_min_grab = -1; 204static int dma_max_read = -1; 205static int dma_max_write = -1; 206 207static int interrupt_delay = -1; 208 209static int get_stats = 0; 210static int get_tuning_stats = 0; 211static int eeprom_write = 0; 212static char *eeprom_download_filename = NULL; 213static char *eeprom_upload_filename = NULL; 214static int reset = 0; 215 216static struct rr_tuning rr_tune; 217struct rr_eeprom rr_eeprom; 218struct rr_stats rr_stats; 219 220int 221main(int argc, char *argv[]) 222{ 223 int ch; 224 225 /* Parse command-line options */ 226 227 while ((ch = getopt(argc, argv, "b:c:d:ei:m:r:stu:w:x")) != -1) { 228 switch (ch) { 229 case 'b': 230 dma_max_read = atoi(optarg); 231 break; 232 case 'c': 233 dma_max_write = atoi(optarg); 234 break; 235 case 'd': 236 eeprom_download_filename = optarg; 237 break; 238 case 'e': 239 eeprom_write++; 240 break; 241 case 'i': 242 interrupt_delay = atoi(optarg); 243 break; 244 case 'm': 245 dma_min_grab = atoi(optarg); 246 break; 247 case 'r': 248 dma_thresh_read = atoi(optarg); 249 break; 250 case 's': 251 get_stats++; 252 break; 253 case 't': 254 get_tuning_stats++; 255 break; 256 case 'u': 257 eeprom_upload_filename = optarg; 258 break; 259 case 'w': 260 dma_thresh_write = atoi(optarg); 261 break; 262 case 'x': 263 reset = 1; 264 break; 265 default: 266 usage(); 267 /* NOTREACHED */ 268 } 269 } 270 argc -= optind; 271 argv += optind; 272 273 if (argc > 1) 274 usage(); 275 if (argc == 1) { 276 (void) strncpy(name, argv[0], sizeof(name)); 277 argc--; argv++; 278 } 279 280 s = socket(AF_INET, SOCK_DGRAM, 0); 281 if (s < 0) 282 err(1, "socket"); 283 284 if (eeprom_upload_filename) 285 eeprom_upload(eeprom_upload_filename); 286 287 if (eeprom_download_filename) 288 eeprom_download(eeprom_download_filename); 289 290 if (get_stats) { 291 esh_stats(get_stats); 292 } 293 294 if (drvspec_ioctl(name, s, EIOCGTUNE, sizeof(struct rr_tuning), 295 (caddr_t) &rr_tune) < 0) { 296 err(1, "ioctl(EIOCGTUNE)"); 297 } 298 299 if (get_tuning_stats) { 300 if (get_stats) 301 printf("\n"); 302 esh_tuning_stats(); 303 } 304 305 if (eeprom_write || dma_thresh_read != -1 || 306 dma_thresh_write != -1 || 307 dma_min_grab != -1 || 308 dma_max_read != -1 || 309 dma_max_write != -1 || 310 interrupt_delay != -1) { 311 esh_tune(); 312 } 313 314 if (eeprom_write) 315 esh_tune_eeprom(); 316 317 if (reset) 318 esh_reset(); 319 320 exit(0); 321} 322 323static void 324esh_tune(void) 325{ 326 dma_max_read = do_map(dma_max_read, read_dma_map); 327 if (dma_max_read != -1) { 328 rr_tune.rt_pci_state &= ~RR_PS_READ_MASK; 329 rr_tune.rt_pci_state |= dma_max_read; 330 } 331 332 dma_max_write = do_map(dma_max_write, write_dma_map); 333 if (dma_max_write != -1) { 334 rr_tune.rt_pci_state &= ~RR_PS_WRITE_MASK; 335 rr_tune.rt_pci_state |= dma_max_write; 336 } 337 338 if (dma_min_grab != -1) { 339 if ((dma_min_grab & (RR_PS_MIN_DMA_MASK >> RR_PS_MIN_DMA_SHIFT)) 340 != dma_min_grab) 341 usage(); 342 rr_tune.rt_pci_state &= ~RR_PS_MIN_DMA_MASK; 343 rr_tune.rt_pci_state |= 344 (dma_min_grab << RR_PS_MIN_DMA_SHIFT); 345 } 346 347 if (dma_thresh_write != -1) { 348 if (dma_thresh_write < 1 || dma_thresh_write > RR_DW_THRESHOLD_MAX) 349 usage(); 350 rr_tune.rt_dma_write_state &= ~RR_DW_THRESHOLD_MASK; 351 rr_tune.rt_dma_write_state |= 352 dma_thresh_write << RR_DW_THRESHOLD_SHIFT; 353 } 354 355 if (dma_thresh_read != -1) { 356 if (dma_thresh_read < 1 || dma_thresh_read > RR_DR_THRESHOLD_MAX) 357 usage(); 358 rr_tune.rt_dma_read_state &= ~RR_DR_THRESHOLD_MASK; 359 rr_tune.rt_dma_read_state |= 360 dma_thresh_read << RR_DR_THRESHOLD_SHIFT; 361 } 362 363 rr_tune.rt_stats_timer = ESH_STATS_TIMER_DEFAULT; 364 365 if (interrupt_delay != -1) 366 rr_tune.rt_interrupt_timer = interrupt_delay; 367 368 if (drvspec_ioctl(name, s, EIOCSTUNE, sizeof(struct rr_tuning), 369 (caddr_t) &rr_tune) < 0) 370 err(1, "EIOCSTUNE"); 371} 372 373/* esh_tune_eeprom 374 * 375 * Store the current tuning data into the eeprom. 376 */ 377 378static void 379esh_tune_eeprom(void) 380{ 381#define LAST (RR_EE_HEADER_CHECKSUM / RR_EE_WORD_LEN) 382#define FIRST (RR_EE_HEADER_CHECKSUM / RR_EE_WORD_LEN) 383 384 u_int32_t tuning_data[LAST + 1]; 385 386 rr_eeprom.ifr_buffer = tuning_data; 387 rr_eeprom.ifr_length = sizeof(tuning_data); 388 rr_eeprom.ifr_offset = 0; 389 390 if (drvspec_ioctl(name, s, EIOCGEEPROM, sizeof(struct rr_eeprom), 391 (caddr_t) &rr_eeprom) == -1) 392 err(6, "ioctl to retrieve tuning information from EEPROM"); 393 394 tuning_data[RR_EE_PCI_STATE / RR_EE_WORD_LEN] = 395 rr_tune.rt_pci_state; 396 tuning_data[RR_EE_DMA_WRITE_STATE / RR_EE_WORD_LEN] = 397 rr_tune.rt_dma_write_state; 398 tuning_data[RR_EE_DMA_READ_STATE / RR_EE_WORD_LEN] = 399 rr_tune.rt_dma_read_state; 400 tuning_data[RR_EE_INTERRUPT_TIMER / RR_EE_WORD_LEN] = rr_tune.rt_interrupt_timer; 401 tuning_data[RR_EE_STATS_TIMER / RR_EE_WORD_LEN] = 402 ESH_STATS_TIMER_DEFAULT; 403 404 tuning_data[RR_EE_HEADER_CHECKSUM / RR_EE_WORD_LEN] = 405 rr_checksum(&tuning_data[FIRST], LAST - FIRST); 406 407 rr_eeprom.ifr_buffer = tuning_data; 408 rr_eeprom.ifr_length = sizeof(tuning_data); 409 rr_eeprom.ifr_offset = 0; 410 411 if (drvspec_ioctl(name, s, EIOCSEEPROM, sizeof(struct rr_eeprom), 412 (caddr_t) &rr_eeprom) == -1) 413 err(7, "ioctl to set tuning information from EEPROM"); 414} 415 416/* eeprom_upload 417 * 418 * Upload the EEPROM from the card and store in the data file. 419 */ 420 421static void 422eeprom_upload(const char *filename) 423{ 424 int fd; 425 426 bzero(eeprom, sizeof(eeprom)); 427 if ((fd = open(filename, O_WRONLY | O_CREAT, 0644)) < 0) 428 err(4, "Couldn't open %s for output", filename); 429 430 rr_eeprom.ifr_buffer = eeprom; 431 rr_eeprom.ifr_length = sizeof(eeprom); 432 rr_eeprom.ifr_offset = 0; 433 434 if (drvspec_ioctl(name, s, EIOCGEEPROM, sizeof(struct rr_eeprom), 435 (caddr_t) &rr_eeprom) == -1) 436 err(5, "ioctl to retrieve all of EEPROM"); 437 438 write(fd, eeprom, sizeof(eeprom)); 439 close(fd); 440} 441 442/* eeprom_download 443 * 444 * Download into eeprom the contents of a file. The file is made up 445 * of ASCII text; the first three characters can be ignored, the next 446 * four hex characters define an address, the next two characters can 447 * be ignored, and the final eight hex characters are the data. 448 */ 449 450static void 451eeprom_download(const char *filename) 452{ 453 FILE *fp; 454 struct rr_seg_descr *segd = NULL, *nsegd; 455 char id[BUFSIZ]; 456 char pad[BUFSIZ]; 457 char buffer[BUFSIZ]; 458 u_int32_t address = 0; 459 u_int32_t last_address = 0; 460 u_int32_t value; 461 u_int32_t length = 0; 462 int segment_start = 0; 463 int seg_table_start; 464 int seg_count_offset; 465 int phase2_start; 466 int phase2_checksum; 467 int in_segment = 0; 468 int segment = 0; 469 int eof = 0; 470 int line = 0; 471 int zero_count = 0; 472 int i; 473 474 /* Clear out eeprom storage space, then read in the value on the card */ 475 476 bzero(eeprom, sizeof(eeprom)); 477 bzero(runcode, sizeof(runcode)); 478 479 rr_eeprom.ifr_buffer = eeprom; 480 rr_eeprom.ifr_length = sizeof(eeprom); 481 rr_eeprom.ifr_offset = 0; 482 if (drvspec_ioctl(name, s, EIOCGEEPROM, sizeof(struct rr_eeprom), 483 (caddr_t) &rr_eeprom) == -1) 484 err(5, "ioctl to retrieve EEPROM"); 485 486 /* 487 * Open the input file and proceed to read the data file, storing 488 * the data and counting the number of segments. 489 */ 490 491 if ((fp = fopen(filename, "r")) == NULL) 492 err(2, "fopen"); 493 494 do { 495 if (fgets(buffer, sizeof(buffer), fp) == NULL) 496 errx(3, "premature, unmarked end of file, line %d", line); 497 line++; 498 499 if (!strncmp(buffer + 7, "01", 2)) { /* check for EOF marker... */ 500 eof = 1; 501 } else { 502 sscanf(buffer, "%3s%4x%2s%8x%2s", 503 id, &address, pad, &value, pad); 504 if (strcmp(id, ":04") != 0) 505 errx(3, "bad initial id on line %d", line); 506 } 507 508 /* 509 * Check to see if we terminated a segment; this happens 510 * when we are at end of file, or we hit a non-sequential 511 * address value, or we see three or more zeroes in a row. 512 */ 513 514 if ((length == RR_EE_SEG_SIZE || eof || zero_count >= 3 || 515 (last_address && last_address != address - 1)) && in_segment) { 516 517 length -= zero_count; 518 segment_start += length; 519 segd[segment].length = length; 520 521 printf("segment %d, %d words\n", segment, length); 522 last_address = in_segment = zero_count = length = 0; 523 segment++; 524 } 525 526 if (eof) 527 break; 528 529 /* Skip zero values starting a segment */ 530 531 if (!in_segment && value == 0) 532 continue; 533 last_address = address; 534 535 /* 536 * If we haven't started a segment yet, do so now. 537 * Store away the address at which this code should be placed 538 * in memory and the address of the code in the EEPROM. 539 */ 540 541 if (!in_segment) { 542 in_segment = 1; 543 544 nsegd = realloc(segd, sizeof(struct rr_seg_descr) * (segment + 1)); 545 if (nsegd == NULL) 546 err(6, "couldn't realloc segment descriptor space"); 547 segd = nsegd; 548 549 segd[segment].start_addr = address * sizeof(u_int32_t); 550 segd[segment].ee_addr = segment_start; 551 } 552 553 /* Keep track of consecutive zeroes */ 554 555 if (in_segment && value == 0) 556 zero_count++; 557 else 558 zero_count = 0; 559 560 /* Store away the actual data */ 561 562 runcode[segment_start + length++] = value; 563 } while (!eof); 564 fclose(fp); 565 566 /* Now that we have a segment count, fill in the EEPROM image. */ 567 568 seg_count_offset = eeprom[RR_EE_RUNCODE_SEGMENTS / RR_EE_WORD_LEN]; 569 seg_count_offset = (seg_count_offset - RR_EE_OFFSET) / RR_EE_WORD_LEN; 570 seg_table_start = seg_count_offset + 1; 571 phase2_checksum = seg_table_start + 3 * segment; 572 phase2_start = eeprom[RR_EE_PHASE2_EE_START / RR_EE_WORD_LEN]; 573 phase2_start = (phase2_start - RR_EE_OFFSET) / RR_EE_WORD_LEN; 574 575 printf("segment table start = %x, segments = %d\n", 576 seg_table_start, eeprom[seg_count_offset]); 577 578 /* We'll fill in anything after the segment count, so clear it */ 579 580 bzero(eeprom + seg_count_offset, 581 sizeof(eeprom) - seg_count_offset * sizeof(eeprom[0])); 582 583 eeprom[seg_count_offset] = segment; 584 585 for (i = 0; i < segment; i++) 586 segd[i].ee_addr = RR_EE_OFFSET + 587 (segd[i].ee_addr + phase2_checksum + 1) * RR_EE_WORD_LEN; 588 589 bcopy(segd, &eeprom[seg_table_start], 590 sizeof(struct rr_seg_descr) * segment); 591 592 bcopy(runcode, &eeprom[phase2_checksum + 1], 593 segment_start * sizeof(u_int32_t)); 594 595 eeprom[phase2_checksum] = rr_checksum(&eeprom[phase2_start], 596 phase2_checksum - phase2_start); 597 598 eeprom[segment_start + phase2_checksum + 1] = 599 rr_checksum(&eeprom[phase2_checksum + 1], segment_start); 600 601 printf("phase2 checksum %x, runcode checksum %x\n", 602 eeprom[phase2_checksum], 603 eeprom[segment_start + phase2_checksum + 1]); 604 605 rr_eeprom.ifr_buffer = eeprom; 606 rr_eeprom.ifr_length = sizeof(eeprom); 607 rr_eeprom.ifr_offset = 0; 608 if (drvspec_ioctl(name, s, EIOCSEEPROM, sizeof(struct rr_eeprom), 609 (caddr_t) &rr_eeprom) == -1) 610 err(5, "ioctl to retrieve EEPROM"); 611} 612 613/* rr_checksum 614 * 615 * Perform checksum on RunCode. Length is in words. Ugh. 616 */ 617 618static u_int32_t 619rr_checksum(const u_int32_t *data, int length) 620{ 621 u_int32_t checksum = 0; 622 623 while (length--) 624 checksum += *data++; 625 626 checksum = 0 - checksum; 627 return checksum; 628} 629 630static struct stats_values { 631 int offset; 632 const char *name; 633} stats_values[] = { 634 {0x04, "receive rings created"}, 635 {0x08, "receive rings deleted"}, 636 {0x0c, "interrupts"}, 637 {0x10, "event overflows"}, 638 {0x14, "invalid commands"}, 639 {0x18, "DMA read errors"}, 640 {0x1c, "DMA write errors"}, 641 {0x20, "stats updates per timer"}, 642 {0x24, "stats updates per host"}, 643 {0x28, "watchdog"}, 644 {0x2c, "trace"}, 645 {0x30, "link ready sync established"}, 646 {0x34, "GLink errors"}, 647 {0x38, "alternating flag errors"}, 648 {0x3c, "overhead bit 8 synchronized"}, 649 {0x40, "remote serial parity errors"}, 650 {0x44, "remote parallel parity errors"}, 651 {0x48, "remote loopback requested"}, 652 {0x50, "transmit connections established"}, 653 {0x54, "transmit connections rejected"}, 654 {0x58, "transmit connections retried"}, 655 {0x5c, "transmit connections timed out"}, 656 {0x60, "transmit connections disconnected"}, 657 {0x64, "transmit parity errors"}, 658 {0x68, "packets sent"}, 659 {0x74, "short first burst sent"}, 660 {0x80, "transmit data not moving"}, 661 {0x90, "receive connections accepted"}, 662 {0x94, "receive connections rejected -- bad parity"}, 663 {0x98, "receive connections rejected -- 64-bit width"}, 664 {0x9c, "receive connections rejected -- buffers low"}, 665 {0xa0, "receive connections disconnected"}, 666 {0xa4, "receive connections with no data"}, 667 {0xa8, "packets received"}, 668 {0xb4, "short first burst received"}, 669 {0xc0, "receive parity error"}, 670 {0xc4, "receive LLRC error"}, 671 {0xc8, "receive burst size error"}, 672 {0xcc, "receive state error"}, 673 {0xd0, "receive ready ULP"}, 674 {0xd4, "receive invalid ULP"}, 675 {0xd8, "receive packets flow control due to buffer space"}, 676 {0xdc, "receive packets flow control due to descriptors"}, 677 {0xe0, "receive ring fulls"}, 678 {0xe4, "packet length errors"}, 679 {0xe8, "packets with checksum error"}, 680 {0xec, "packets dropped"}, 681 {0xf0, "ring low on space"}, 682 {0xf4, "data in ring at close"}, 683 {0xf8, "receives to ring not moving data"}, 684 {0xfc, "receiver idles"}, 685 {0, 0}, 686}; 687 688static void 689esh_reset(void) 690{ 691 if (drvspec_ioctl(name, s, EIOCRESET, 0, 0) < 0) 692 err(1, "ioctl(EIOCRESET)"); 693} 694 695static void 696esh_stats(int lget_stats) 697{ 698 u_int32_t *stats; 699 long long value; 700 int offset; 701 702 if (drvspec_ioctl(name, s, EIOCGSTATS, sizeof(struct rr_stats), 703 (caddr_t) &rr_stats) < 0) 704 err(1, "ioctl(EIOCGTUNE)"); 705 706 stats = rr_stats.rs_stats; 707 708 value = (((long long) stats[0x78 / 4]) << 32) | stats[0x7c / 4]; 709 if (lget_stats == 1 || value > 0) 710 printf("%12lld bytes sent\n", value); 711 value = ((long long) stats[0xb8 / 4] << 32) | stats[0xbc / 4]; 712 if (lget_stats == 1 || value > 0) 713 printf("%12lld bytes received\n", value); 714 715 for (offset = 0; stats_values[offset].offset != 0; offset++) { 716 if (lget_stats == 1 || stats[stats_values[offset].offset / 4] > 0) 717 printf("%12d %s\n", stats[stats_values[offset].offset / 4], 718 stats_values[offset].name); 719 } 720} 721 722 723static void 724esh_tuning_stats(void) 725{ 726 printf("rt_mode_and_status = %x\n", 727 rr_tune.rt_mode_and_status); 728 printf("rt_conn_retry_count = %x\n", 729 rr_tune.rt_conn_retry_count); 730 printf("rt_conn_retry_timer = %x\n", 731 rr_tune.rt_conn_retry_timer); 732 printf("rt_conn_timeout = %x\n", rr_tune.rt_conn_timeout); 733 printf("rt_stats_timer = %x\n", rr_tune.rt_stats_timer); 734 printf("rt_interrupt_timer = %x\n", 735 rr_tune.rt_interrupt_timer); 736 printf("rt_tx_timeout = %x\n", rr_tune.rt_tx_timeout); 737 printf("rt_rx_timeout = %x\n", rr_tune.rt_rx_timeout); 738 printf("rt_pci_state = %x" 739 " min DMA %x read max %x write max %x\n", 740 rr_tune.rt_pci_state, 741 (rr_tune.rt_pci_state & RR_PS_MIN_DMA_MASK) 742 >> RR_PS_MIN_DMA_SHIFT, 743 do_map_dma(rr_tune.rt_pci_state & RR_PS_READ_MASK, 744 read_dma_map), 745 do_map_dma(rr_tune.rt_pci_state & RR_PS_WRITE_MASK, 746 write_dma_map)); 747 printf("rt_dma_write_state = %x\n", 748 rr_tune.rt_dma_write_state); 749 printf("rt_dma_read_state = %x\n", rr_tune.rt_dma_read_state); 750 printf("rt_driver_param = %x\n", rr_tune.rt_driver_param); 751 752} 753 754