pdq.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,590 行 · 第 1/4 页

C
1,590
字号
/*- * Copyright (c) 1995,1996 Matt Thomas <matt@3am-software.com> * 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. The name of the author may not be used to endorse or promote products *    derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: pdq.c,v 1.2.6.1 1999/01/29 06:41:33 dillon Exp $ * *//* * DEC PDQ FDDI Controller O/S independent code * * This module should work any PDQ based board.  Note that changes for * MIPS and Alpha architectures (or any other architecture which requires * a flushing of memory or write buffers and/or has incoherent caches) * have yet to be made. * * However, it is expected that the PDQ_CSR_WRITE macro will cause a  * flushing of the write buffers. */#define	PDQ_HWSUPPORT	/* for pdq.h */#if defined(__FreeBSD__)#include <dev/pdq/pdqvar.h>#include <dev/pdq/pdqreg.h>#else#include "pdqvar.h"#include "pdqreg.h"#endif#define	PDQ_ROUNDUP(n, x)	(((n) + ((x) - 1)) & ~((x) - 1))#define	PDQ_CMD_RX_ALIGNMENT	16#if (defined(PDQTEST) && !defined(PDQ_NOPRINTF)) || defined(PDQVERBOSE)#define	PDQ_PRINTF(x)	printf x#else#define	PDQ_PRINTF(x)	do { } while (0)#endifstatic const char * const pdq_halt_codes[] = {    "Selftest Timeout", "Host Bus Parity Error", "Host Directed Fault",    "Software Fault", "Hardware Fault", "PC Trace Path Test",    "DMA Error", "Image CRC Error", "Adapter Processer Error"};static const char * const pdq_adapter_states[] = {    "Reset", "Upgrade", "DMA Unavailable", "DMA Available",    "Link Available", "Link Unavailable", "Halted", "Ring Member"};/* * The following are used in conjunction with  * unsolicited events */static const char * const pdq_entities[] = {    "Station", "Link", "Phy Port"};static const char * const pdq_station_events[] = {    "Trace Received"};static const char * const pdq_station_arguments[] = {    "Reason"};static const char * const pdq_link_events[] = {    "Transmit Underrun",    "Transmit Failed",    "Block Check Error (CRC)",    "Frame Status Error",    "PDU Length Error",    NULL,    NULL,    "Receive Data Overrun",    NULL,    "No User Buffer",    "Ring Initialization Initiated",    "Ring Initialization Received",    "Ring Beacon Initiated",    "Duplicate Address Failure",    "Duplicate Token Detected",    "Ring Purger Error",    "FCI Strip Error",    "Trace Initiated",    "Directed Beacon Received",};static const char * const pdq_link_arguments[] = {    "Reason",    "Data Link Header",    "Source",    "Upstream Neighbor"};static const char * const pdq_phy_events[] = {    "LEM Error Monitor Reject",    "Elasticy Buffer Error",    "Link Confidence Test Reject"};static const char * const pdq_phy_arguments[] = {    "Direction"};static const char * const * const pdq_event_arguments[] = {    pdq_station_arguments,    pdq_link_arguments,    pdq_phy_arguments};static const char * const * const pdq_event_codes[] = {    pdq_station_events,    pdq_link_events,    pdq_phy_events};static const char * const pdq_station_types[] = {    "SAS", "DAC", "SAC", "NAC", "DAS"};static const char * const pdq_smt_versions[] = { "", "V6.2", "V7.2", "V7.3" };static const char pdq_phy_types[] = "ABSM";static const char * const pdq_pmd_types0[] = {    "ANSI Multi-Mode", "ANSI Single-Mode Type 1", "ANSI Single-Mode Type 2",    "ANSI Sonet"};static const char * const pdq_pmd_types100[] = {    "Low Power", "Thin Wire", "Shielded Twisted Pair",    "Unshielded Twisted Pair"};static const char * const * const pdq_pmd_types[] = {     pdq_pmd_types0, pdq_pmd_types100};static const char * const pdq_descriptions[] = {    "DEFPA PCI",    "DEFEA EISA",    "DEFTA TC",    "DEFAA Futurebus",    "DEFQA Q-bus",};static voidpdq_print_fddi_chars(    pdq_t *pdq,    const pdq_response_status_chars_get_t *rsp){    const char hexchars[] = "0123456789abcdef";    printf(#if !defined(__bsdi__) && !defined(__NetBSD__)	   PDQ_OS_PREFIX#else	   ": "#endif	   "DEC %s FDDI %s Controller\n",#if !defined(__bsdi__) && !defined(__NetBSD__)	   PDQ_OS_PREFIX_ARGS,#endif	   pdq_descriptions[pdq->pdq_type],	   pdq_station_types[rsp->status_chars_get.station_type]);    printf(PDQ_OS_PREFIX "FDDI address %c%c:%c%c:%c%c:%c%c:%c%c:%c%c, FW=%c%c%c%c, HW=%c",	   PDQ_OS_PREFIX_ARGS,	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[0] >> 4],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[0] & 0x0F],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[1] >> 4],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[1] & 0x0F],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[2] >> 4],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[2] & 0x0F],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[3] >> 4],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[3] & 0x0F],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[4] >> 4],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[4] & 0x0F],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[5] >> 4],	   hexchars[pdq->pdq_hwaddr.lanaddr_bytes[5] & 0x0F],	   pdq->pdq_fwrev.fwrev_bytes[0], pdq->pdq_fwrev.fwrev_bytes[1],	   pdq->pdq_fwrev.fwrev_bytes[2], pdq->pdq_fwrev.fwrev_bytes[3],	   rsp->status_chars_get.module_rev.fwrev_bytes[0]);    if (rsp->status_chars_get.smt_version_id < PDQ_ARRAY_SIZE(pdq_smt_versions)) {	printf(", SMT %s\n", pdq_smt_versions[rsp->status_chars_get.smt_version_id]);    }    printf(PDQ_OS_PREFIX "FDDI Port%s = %c (PMD = %s)",	   PDQ_OS_PREFIX_ARGS,	   rsp->status_chars_get.station_type == PDQ_STATION_TYPE_DAS ? "[A]" : "",	   pdq_phy_types[rsp->status_chars_get.phy_type[0]],	   pdq_pmd_types[rsp->status_chars_get.pmd_type[0] / 100][rsp->status_chars_get.pmd_type[0] % 100]);    if (rsp->status_chars_get.station_type == PDQ_STATION_TYPE_DAS)	printf(", FDDI Port[B] = %c (PMD = %s)",	       pdq_phy_types[rsp->status_chars_get.phy_type[1]],	       pdq_pmd_types[rsp->status_chars_get.pmd_type[1] / 100][rsp->status_chars_get.pmd_type[1] % 100]);    printf("\n");}static voidpdq_init_csrs(    pdq_csrs_t *csrs,    pdq_bus_t bus,    pdq_bus_memaddr_t csr_base,    size_t csrsize){    csrs->csr_bus = bus;    csrs->csr_base = csr_base;    csrs->csr_port_reset		= PDQ_CSR_OFFSET(csr_base,  0 * csrsize);    csrs->csr_host_data			= PDQ_CSR_OFFSET(csr_base,  1 * csrsize);    csrs->csr_port_control		= PDQ_CSR_OFFSET(csr_base,  2 * csrsize);    csrs->csr_port_data_a		= PDQ_CSR_OFFSET(csr_base,  3 * csrsize);    csrs->csr_port_data_b		= PDQ_CSR_OFFSET(csr_base,  4 * csrsize);    csrs->csr_port_status		= PDQ_CSR_OFFSET(csr_base,  5 * csrsize);    csrs->csr_host_int_type_0		= PDQ_CSR_OFFSET(csr_base,  6 * csrsize);    csrs->csr_host_int_enable		= PDQ_CSR_OFFSET(csr_base,  7 * csrsize);    csrs->csr_type_2_producer		= PDQ_CSR_OFFSET(csr_base,  8 * csrsize);    csrs->csr_cmd_response_producer	= PDQ_CSR_OFFSET(csr_base, 10 * csrsize);    csrs->csr_cmd_request_producer	= PDQ_CSR_OFFSET(csr_base, 11 * csrsize);    csrs->csr_host_smt_producer		= PDQ_CSR_OFFSET(csr_base, 12 * csrsize);    csrs->csr_unsolicited_producer	= PDQ_CSR_OFFSET(csr_base, 13 * csrsize);}static voidpdq_init_pci_csrs(    pdq_pci_csrs_t *csrs,    pdq_bus_t bus,    pdq_bus_memaddr_t csr_base,    size_t csrsize){    csrs->csr_bus = bus;    csrs->csr_base = csr_base;    csrs->csr_pfi_mode_control	= PDQ_CSR_OFFSET(csr_base, 16 * csrsize);    csrs->csr_pfi_status	= PDQ_CSR_OFFSET(csr_base, 17 * csrsize);    csrs->csr_fifo_write	= PDQ_CSR_OFFSET(csr_base, 18 * csrsize);    csrs->csr_fifo_read		= PDQ_CSR_OFFSET(csr_base, 19 * csrsize);}static voidpdq_flush_databuf_queue(    pdq_databuf_queue_t *q){    PDQ_OS_DATABUF_T *pdu;    for (;;) {	PDQ_OS_DATABUF_DEQUEUE(q, pdu);	if (pdu == NULL)	    return;	PDQ_OS_DATABUF_FREE(pdu);    }}static pdq_boolean_tpdq_do_port_control(    const pdq_csrs_t * const csrs,    pdq_uint32_t cmd){    int cnt = 0;    PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_CSR_CMD_DONE);    PDQ_CSR_WRITE(csrs, csr_port_control, PDQ_PCTL_CMD_ERROR | cmd);    while ((PDQ_CSR_READ(csrs, csr_host_int_type_0) & PDQ_HOST_INT_CSR_CMD_DONE) == 0 && cnt < 33000000)	cnt++;    PDQ_PRINTF(("CSR cmd spun %d times\n", cnt));    if (PDQ_CSR_READ(csrs, csr_host_int_type_0) & PDQ_HOST_INT_CSR_CMD_DONE) {	PDQ_CSR_WRITE(csrs, csr_host_int_type_0, PDQ_HOST_INT_CSR_CMD_DONE);	return (PDQ_CSR_READ(csrs, csr_port_control) & PDQ_PCTL_CMD_ERROR) ? PDQ_FALSE : PDQ_TRUE;    }    /* adapter failure */    PDQ_ASSERT(0);    return PDQ_FALSE;}static voidpdq_read_mla(    const pdq_csrs_t * const csrs,    pdq_lanaddr_t *hwaddr){    pdq_uint32_t data;    PDQ_CSR_WRITE(csrs, csr_port_data_a, 0);    pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);    data = PDQ_CSR_READ(csrs, csr_host_data);    hwaddr->lanaddr_bytes[0] = (data >> 0) & 0xFF;    hwaddr->lanaddr_bytes[1] = (data >> 8) & 0xFF;    hwaddr->lanaddr_bytes[2] = (data >> 16) & 0xFF;    hwaddr->lanaddr_bytes[3] = (data >> 24) & 0xFF;    PDQ_CSR_WRITE(csrs, csr_port_data_a, 1);    pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);    data = PDQ_CSR_READ(csrs, csr_host_data);    hwaddr->lanaddr_bytes[4] = (data >> 0) & 0xFF;    hwaddr->lanaddr_bytes[5] = (data >> 8) & 0xFF;}static voidpdq_read_fwrev(    const pdq_csrs_t * const csrs,    pdq_fwrev_t *fwrev){    pdq_uint32_t data;    pdq_do_port_control(csrs, PDQ_PCTL_FW_REV_READ);    data = PDQ_CSR_READ(csrs, csr_host_data);    fwrev->fwrev_bytes[3] = (data >> 0) & 0xFF;    fwrev->fwrev_bytes[2] = (data >> 8) & 0xFF;    fwrev->fwrev_bytes[1] = (data >> 16) & 0xFF;    fwrev->fwrev_bytes[0] = (data >> 24) & 0xFF;}static pdq_boolean_tpdq_read_error_log(    pdq_t *pdq,    pdq_response_error_log_get_t *log_entry){    const pdq_csrs_t * const csrs = &pdq->pdq_csrs;    pdq_uint32_t *ptr = (pdq_uint32_t *) log_entry;    pdq_do_port_control(csrs, PDQ_PCTL_ERROR_LOG_START);    while (pdq_do_port_control(csrs, PDQ_PCTL_FW_REV_READ) == PDQ_TRUE) {	*ptr++ = PDQ_CSR_READ(csrs, csr_host_data);	if ((pdq_uint8_t *) ptr - (pdq_uint8_t *) log_entry == sizeof(*log_entry))	    break;    }    return (ptr == (pdq_uint32_t *) log_entry) ? PDQ_FALSE : PDQ_TRUE;}static pdq_chip_rev_tpdq_read_chiprev(    const pdq_csrs_t * const csrs){    pdq_uint32_t data;    PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_PDQ_REV_GET);    pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);    data = PDQ_CSR_READ(csrs, csr_host_data);    return (pdq_chip_rev_t) data;}static const struct {    size_t cmd_len;    size_t rsp_len;    const char *cmd_name;} pdq_cmd_info[] = {    { sizeof(pdq_cmd_generic_t),		/* 0 - PDQC_START */      sizeof(pdq_response_generic_t),      "Start"    },    { sizeof(pdq_cmd_filter_set_t),		/* 1 - PDQC_FILTER_SET */      sizeof(pdq_response_generic_t),      "Filter Set"    },    { sizeof(pdq_cmd_generic_t),		/* 2 - PDQC_FILTER_GET */      sizeof(pdq_response_filter_get_t),      "Filter Get"    },    { sizeof(pdq_cmd_chars_set_t),		/* 3 - PDQC_CHARS_SET */      sizeof(pdq_response_generic_t),      "Chars Set"    },    { sizeof(pdq_cmd_generic_t),		/* 4 - PDQC_STATUS_CHARS_GET */      sizeof(pdq_response_status_chars_get_t),      "Status Chars Get"    },#if 0    { sizeof(pdq_cmd_generic_t),		/* 5 - PDQC_COUNTERS_GET */      sizeof(pdq_response_counters_get_t),      "Counters Get"    },    { sizeof(pdq_cmd_counters_set_t),		/* 6 - PDQC_COUNTERS_SET */      sizeof(pdq_response_generic_t),      "Counters Set"

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?