summaryrefslogtreecommitdiffstats
path: root/sys/pci/pdq.c
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1997-01-17 23:54:45 +0000
committerjoerg <joerg@FreeBSD.org>1997-01-17 23:54:45 +0000
commit14cfba618c3dd1fe8025d11f956ade25ad77120f (patch)
treea4f5eddb9b3bd12e23dcdc7e486d3c75a0f4e6f5 /sys/pci/pdq.c
parent912bcfa966638919ab4759ca32c659243a368883 (diff)
downloadFreeBSD-src-14cfba618c3dd1fe8025d11f956ade25ad77120f.zip
FreeBSD-src-14cfba618c3dd1fe8025d11f956ade25ad77120f.tar.gz
This mega-merge brings Matt Thomas' 960801 FDDI driver (almost) up
to -current. Thanks goes to Ulrike Nitzsche <ulrike@ifw-dresden.de> for giving me a chance to test this. Only the PCI driver is tested though. One final patch will follow in a separate commit. This is so that everything up to here can be dragged into 2.2, if we decide so. Reviewed by: joerg Submitted by: Matt Thomas <matt@3am-software.com>
Diffstat (limited to 'sys/pci/pdq.c')
-rw-r--r--sys/pci/pdq.c1577
1 files changed, 0 insertions, 1577 deletions
diff --git a/sys/pci/pdq.c b/sys/pci/pdq.c
deleted file mode 100644
index ad00410..0000000
--- a/sys/pci/pdq.c
+++ /dev/null
@@ -1,1577 +0,0 @@
-/*-
- * Copyright (c) 1995 Matt Thomas (matt@lkg.dec.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.
- *
- * $FreeBSD$
- *
- * Revision 1.8 1995/03/14 01:52:52 thomas
- * Update for new FreeBSD PCI Interrupt interface
- *
- * Revision 1.7 1995/03/07 23:03:16 thomas
- * Fix SMT queue processing
- *
- * Revision 1.6 1995/03/06 18:03:47 thomas
- * restart trasmitter once link is available
- *
- * Revision 1.5 1995/03/06 17:07:56 thomas
- * Add copyright/disclaimer
- * Add error recovery code.
- * Add BPF SMT support
- *
- * Revision 1.3 1995/03/03 13:48:35 thomas
- * more fixes
- *
- *
- */
-
-/*
- * DEC PDQ FDDI Controller O/S independent code
- *
- * Written by Matt Thomas <matt@lkg.dec.com>
- *
- * 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.
- */
-
-#include <pci/pdqreg.h>
-#include <pci/pdq_os.h>
-
-#define PDQ_ROUNDUP(n, x) (((n) + ((x) - 1)) & ~((x) - 1))
-#define PDQ_CMD_RX_ALIGNMENT 16
-
-#if defined(PDQTEST) && !defined(PDQ_NOPRINTF)
-#define PDQ_PRINTF(x) printf x
-#else
-#define PDQ_PRINTF(x)
-#endif
-
-static void pdq_process_transmitted_data(pdq_t *pdq);
-static void pdq_flush_transmitter(pdq_t *pdq);
-static void pdq_print_fddi_chars(pdq_t *pdq, const pdq_response_status_chars_get_t *rsp);
-
-static void pdq_init_csrs(pdq_csrs_t *csrs, void *csrs_va, size_t csr_size);
-static void pdq_init_pci_csrs(pdq_pci_csrs_t *csrs, void *csrs_va, size_t csr_size);
-
-static void pdq_flush_databuf_queue(pdq_databuf_queue_t *q);
-
-static pdq_boolean_t pdq_do_port_control(const pdq_csrs_t * const csrs, pdq_uint32_t cmd);
-static void pdq_read_mla(const pdq_csrs_t * const csrs, pdq_lanaddr_t *hwaddr);
-static void pdq_read_fwrev(const pdq_csrs_t * const csrs, pdq_fwrev_t *fwrev);
-static pdq_boolean_t pdq_read_error_log(pdq_t *pdq, pdq_response_error_log_get_t *log_entry);
-static pdq_chip_rev_t pdq_read_chiprev(const pdq_csrs_t * const csrs);
-
-static void pdq_queue_commands(pdq_t *pdq);
-static void pdq_process_command_responses(pdq_t *pdq);
-static void pdq_process_unsolicited_events(pdq_t *pdq);
-
-static void pdq_process_received_data(pdq_t *pdq, pdq_rx_info_t *rx,
- pdq_rxdesc_t *receives,
- pdq_uint32_t completion_goal,
- pdq_uint32_t ring_mask);
-
-static 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" };
-
-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",
-};
-
-static void
-pdq_print_fddi_chars(
- pdq_t *pdq,
- const pdq_response_status_chars_get_t *rsp)
-{
-
- printf(PDQ_OS_PREFIX "DEC %s FDDI %s Controller\n",
- PDQ_OS_PREFIX_ARGS, pdq_descriptions[pdq->pdq_type],
- pdq_station_types[rsp->status_chars_get.station_type]);
-
- printf(PDQ_OS_PREFIX "FDDI address %6D, FW=%4.4s, HW=%c",
- PDQ_OS_PREFIX_ARGS, pdq->pdq_hwaddr.lanaddr_bytes, ":",
- pdq->pdq_fwrev.fwrev_bytes,
- 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 void
-pdq_init_csrs(
- pdq_csrs_t *csrs,
- void *csr_va,
- size_t csrsize)
-{
- volatile pdq_uint32_t *csr_base = (volatile pdq_uint32_t *) csr_va;
-
- csrs->csr_port_reset = &csr_base[0 * csrsize];
- csrs->csr_host_data = &csr_base[1 * csrsize];
- csrs->csr_port_control = &csr_base[2 * csrsize];
- csrs->csr_port_data_a = &csr_base[3 * csrsize];
- csrs->csr_port_data_b = &csr_base[4 * csrsize];
- csrs->csr_port_status = &csr_base[5 * csrsize];
- csrs->csr_host_int_type_0 = &csr_base[6 * csrsize];
- csrs->csr_host_int_enable = &csr_base[7 * csrsize];
- csrs->csr_type_2_producer = &csr_base[8 * csrsize];
- csrs->csr_cmd_response_producer = &csr_base[10 * csrsize];
- csrs->csr_cmd_request_producer = &csr_base[11 * csrsize];
- csrs->csr_host_smt_producer = &csr_base[12 * csrsize];
- csrs->csr_unsolicited_producer = &csr_base[13 * csrsize];
-}
-
-static void
-pdq_init_pci_csrs(
- pdq_pci_csrs_t *csrs,
- void *csr_va,
- size_t csrsize)
-{
- volatile pdq_uint32_t *csr_base = (volatile pdq_uint32_t *) csr_va;
-
- csrs->csr_pfi_mode_control = &csr_base[16 * csrsize];
- csrs->csr_pfi_status = &csr_base[17 * csrsize];
- csrs->csr_fifo_write = &csr_base[18 * csrsize];
- csrs->csr_fifo_read = &csr_base[19 * csrsize];
-}
-
-static void
-pdq_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_t
-pdq_do_port_control(
- const pdq_csrs_t * const csrs,
- pdq_uint32_t cmd)
-{
- int cnt = 0;
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_CSR_CMD_DONE;
- *csrs->csr_port_control = PDQ_PCTL_CMD_ERROR | cmd;
- while ((*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 (*csrs->csr_host_int_type_0 & PDQ_HOST_INT_CSR_CMD_DONE) {
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_CSR_CMD_DONE;
- return (*csrs->csr_port_control & PDQ_PCTL_CMD_ERROR) ? PDQ_FALSE : PDQ_TRUE;
- }
- /* adapter failure */
- PDQ_ASSERT(0);
- return PDQ_FALSE;
-}
-
-static void
-pdq_read_mla(
- const pdq_csrs_t * const csrs,
- pdq_lanaddr_t *hwaddr)
-{
- pdq_uint32_t data;
-
- *csrs->csr_port_data_a = 0;
- pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);
- data = *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;
-
- *csrs->csr_port_data_a = 1;
- pdq_do_port_control(csrs, PDQ_PCTL_MLA_READ);
- data = *csrs->csr_host_data;
-
- hwaddr->lanaddr_bytes[4] = (data >> 0) & 0xFF;
- hwaddr->lanaddr_bytes[5] = (data >> 8) & 0xFF;
-}
-
-static void
-pdq_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 = *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_t
-pdq_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++ = *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_t
-pdq_read_chiprev(
- const pdq_csrs_t * const csrs)
-{
- pdq_uint32_t data;
-
- *csrs->csr_port_data_a = PDQ_SUB_CMD_PDQ_REV_GET;
- pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
- data = *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"
- },
-#else
- { 0, 0, "Counters Get" },
- { 0, 0, "Counters Set" },
-#endif
- { sizeof(pdq_cmd_addr_filter_set_t), /* 7 - PDQC_ADDR_FILTER_SET */
- sizeof(pdq_response_generic_t),
- "Addr Filter Set"
- },
- { sizeof(pdq_cmd_generic_t), /* 8 - PDQC_ADDR_FILTER_GET */
- sizeof(pdq_response_addr_filter_get_t),
- "Addr Filter Get"
- },
-#if 0
- { sizeof(pdq_cmd_generic_t), /* 9 - PDQC_ERROR_LOG_CLEAR */
- sizeof(pdq_response_generic_t),
- "Error Log Clear"
- },
- { sizeof(pdq_cmd_generic_t), /* 10 - PDQC_ERROR_LOG_SET */
- sizeof(pdq_response_generic_t),
- "Error Log Set"
- },
- { sizeof(pdq_cmd_generic_t), /* 11 - PDQC_FDDI_MIB_GET */
- sizeof(pdq_response_generic_t),
- "FDDI MIB Get"
- },
- { sizeof(pdq_cmd_generic_t), /* 12 - PDQC_DEC_EXT_MIB_GET */
- sizeof(pdq_response_generic_t),
- "DEC Ext MIB Get"
- },
- { sizeof(pdq_cmd_generic_t), /* 13 - PDQC_DEC_SPECIFIC_GET */
- sizeof(pdq_response_generic_t),
- "DEC Specific Get"
- },
- { sizeof(pdq_cmd_generic_t), /* 14 - PDQC_SNMP_SET */
- sizeof(pdq_response_generic_t),
- "SNMP Set"
- },
- { 0, 0, "N/A" },
- { sizeof(pdq_cmd_generic_t), /* 16 - PDQC_SMT_MIB_GET */
- sizeof(pdq_response_generic_t),
- "SMT MIB Get"
- },
- { sizeof(pdq_cmd_generic_t), /* 17 - PDQC_SMT_MIB_SET */
- sizeof(pdq_response_generic_t),
- "SMT MIB Set",
- },
-#endif
-};
-
-static void
-pdq_queue_commands(
- pdq_t *pdq)
-{
- const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
- pdq_command_info_t *ci = &pdq->pdq_command_info;
- pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
- pdq_txdesc_t *txd;
- pdq_rxdesc_t *rxd;
- pdq_cmd_code_t op;
- pdq_uint32_t cmdlen, rsplen;
- pdq_uint8_t *bufptr;
- unsigned cmds;
-
- for (cmds = 0; ci->ci_pending_commands != 0; cmds++) {
- pdq_uint32_t mask;
- /*
- * If there is no free space in the queues, stop queuing
- * commands.
- */
- if (ci->ci_request_free == 0 || ci->ci_response_free == 0)
- break;
- /*
- * If there are no commands nor responses pending, then reset
- * the command/response buffer back to the start.
- */
- if (ci->ci_request_free == ci->ci_request_max
- && ci->ci_response_free == ci->ci_response_max) {
- ci->ci_bufptr = ci->ci_bufstart;
- ci->ci_buffree = sizeof(pdq->pdq_dbp->pdqdb_command_pool);
- }
- /*
- * Determine which commands need to be queued.
- */
- op = PDQC_SMT_MIB_SET;
- for (mask = 1 << ((int) op); (mask & ci->ci_pending_commands) == 0; mask >>= 1)
- op = (pdq_cmd_code_t) ((int) op - 1);
- /*
- * Obtain the sizes needed for the command and response.
- * Round up to PDQ_CMD_RX_ALIGNMENT so the receive buffer is
- * always properly aligned.
- */
- cmdlen = PDQ_ROUNDUP(pdq_cmd_info[op].cmd_len, PDQ_CMD_RX_ALIGNMENT);
- rsplen = PDQ_ROUNDUP(pdq_cmd_info[op].rsp_len, PDQ_CMD_RX_ALIGNMENT);
- if (cmdlen < rsplen)
- cmdlen = rsplen;
- /*
- * If there's not enough space or if there isn't enough continguous
- * space, then wait for some to be freed.
- */
- if (cmdlen > ci->ci_buffree)
- break;
- if (cmdlen > ci->ci_bufend - ci->ci_bufptr)
- break;
-
- /*
- * Allocate the space for the command and the repsonse.
- */
- bufptr = ci->ci_bufptr;
- ci->ci_bufptr += cmdlen;
- ci->ci_buffree -= cmdlen;
- if (ci->ci_bufptr == ci->ci_bufend)
- ci->ci_bufptr = ci->ci_bufstart;
-
- /*
- * Obtain and fill in the descriptor for the command
- */
- txd = &dbp->pdqdb_command_requests[ci->ci_request_producer];
- PDQ_ADVANCE(ci->ci_request_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests));
- ci->ci_request_free--;
-
- txd->txd_pa_lo = ci->ci_pa_bufstart + (bufptr - ci->ci_bufstart);
- txd->txd_eop = txd->txd_sop = 1;
- txd->txd_seg_len = cmdlen;
- txd->txd_pa_hi = 0;
-
- /*
- * Obtain and fill in the descriptor for the response
- */
- rxd = &dbp->pdqdb_command_responses[ci->ci_response_producer];
- PDQ_ADVANCE(ci->ci_response_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses));
- ci->ci_response_free--;
-
- rxd->rxd_pa_lo = ci->ci_pa_bufstart + (bufptr - ci->ci_bufstart);
- rxd->rxd_sop = 1;
- rxd->rxd_seg_cnt = 0;
- rxd->rxd_seg_len_lo = 0;
- rxd->rxd_seg_len_hi = cmdlen / 16;
- rxd->rxd_pa_hi = 0;
-
- /*
- * Clear the command area, set the opcode, and the command from the pending
- * mask.
- */
-
- PDQ_OS_MEMZERO(bufptr, cmdlen);
- *(pdq_cmd_code_t *) bufptr = op;
- ci->ci_pending_commands &= ~mask;
-
- /*
- * Fill in the command area, if needed.
- */
- switch (op) {
- case PDQC_FILTER_SET: {
- pdq_cmd_filter_set_t *filter_set = (pdq_cmd_filter_set_t *) bufptr;
- unsigned idx = 0;
- filter_set->filter_set_items[idx].item_code = PDQI_IND_GROUP_PROM;
- filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_PROMISC ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
- idx++;
- filter_set->filter_set_items[idx].item_code = PDQI_GROUP_PROM;
- filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_ALLMULTI ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
- idx++;
- filter_set->filter_set_items[idx].item_code = PDQI_SMT_PROM;
- filter_set->filter_set_items[idx].filter_state = ((pdq->pdq_flags & (PDQ_PROMISC|PDQ_PASS_SMT)) == (PDQ_PROMISC|PDQ_PASS_SMT) ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
- idx++;
- filter_set->filter_set_items[idx].item_code = PDQI_SMT_USER;
- filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_PASS_SMT ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
- idx++;
- filter_set->filter_set_items[idx].item_code = PDQI_EOL;
- break;
- }
- case PDQC_ADDR_FILTER_SET: {
- pdq_cmd_addr_filter_set_t *addr_filter_set = (pdq_cmd_addr_filter_set_t *) bufptr;
- pdq_lanaddr_t *addr = addr_filter_set->addr_filter_set_addresses;
- addr->lanaddr_bytes[0] = 0xFF;
- addr->lanaddr_bytes[1] = 0xFF;
- addr->lanaddr_bytes[2] = 0xFF;
- addr->lanaddr_bytes[3] = 0xFF;
- addr->lanaddr_bytes[4] = 0xFF;
- addr->lanaddr_bytes[5] = 0xFF;
- addr++;
- pdq_os_addr_fill(pdq, addr, 61);
- break;
- }
- default:
- break;
- }
- /*
- * At this point the command is done. All that needs to be done is to
- * produce it to the PDQ. That will be done after the loop exits.
- */
- PDQ_PRINTF(("PDQ Queue Command Request: %s queued\n",
- pdq_cmd_info[op].cmd_name));
- }
- if (cmds > 0) {
- *csrs->csr_cmd_response_producer = ci->ci_response_producer | (ci->ci_response_completion << 8);
- *csrs->csr_cmd_request_producer = ci->ci_request_producer | (ci->ci_request_completion << 8);
- }
-}
-
-static void
-pdq_process_command_responses(
- pdq_t *pdq)
-{
- const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
- pdq_command_info_t *ci = &pdq->pdq_command_info;
- volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp;
- pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
- pdq_txdesc_t *txd;
- pdq_rxdesc_t *rxd;
- const pdq_response_generic_t *rspgen;
- unsigned cmds;
-
- /*
- * We have to process the command and response in tandem so
- * just wait for the response to be consumed. If it has been
- * consumed then the command must have been as well.
- */
-
- for (cmds = 0; cbp->pdqcb_command_response != ci->ci_response_completion; cmds = 1) {
- PDQ_ASSERT (cbp->pdqcb_command_request != ci->ci_request_completion);
-
- txd = &dbp->pdqdb_command_requests[ci->ci_request_completion];
- rxd = &dbp->pdqdb_command_responses[ci->ci_response_completion];
-
- rspgen = (const pdq_response_generic_t *) (ci->ci_bufstart + rxd->rxd_pa_lo - ci->ci_pa_bufstart);
- PDQ_ASSERT(rspgen->generic_status == PDQR_SUCCESS);
- PDQ_PRINTF(("PDQ Process Command Response: %s completed\n",
- pdq_cmd_info[rspgen->generic_op].cmd_name));
-
- if (rspgen->generic_op == PDQC_STATUS_CHARS_GET && (pdq->pdq_flags & PDQ_PRINTCHARS)) {
- pdq->pdq_flags &= ~PDQ_PRINTCHARS;
- pdq_print_fddi_chars(pdq, (const pdq_response_status_chars_get_t *) rspgen);
- }
-
- PDQ_ADVANCE(ci->ci_request_completion, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests));
- PDQ_ADVANCE(ci->ci_response_completion, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses));
- ci->ci_response_free++;
- ci->ci_request_free++;
- ci->ci_buffree += txd->txd_seg_len;
- }
-
- if (cmds > 0) {
- *csrs->csr_cmd_response_producer = ci->ci_response_producer | (ci->ci_response_completion << 8);
- *csrs->csr_cmd_request_producer = ci->ci_request_producer | (ci->ci_request_completion << 8);
- if (ci->ci_pending_commands != 0)
- pdq_queue_commands(pdq);
- }
-}
-
-/*
- * This following routine processes unsolicited events.
- * In addition, it also fills the unsolicited queue with
- * event buffers so it can be used to initialize the queue
- * as well.
- */
-static void
-pdq_process_unsolicited_events(
- pdq_t *pdq)
-{
- const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
- pdq_unsolicited_info_t *ui = &pdq->pdq_unsolicited_info;
- volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp;
- pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
- const pdq_unsolicited_event_t *event;
- pdq_rxdesc_t *rxd;
-
- /*
- * Process each unsolicited event (if any).
- */
-
- while (cbp->pdqcb_unsolicited_event != ui->ui_completion) {
- rxd = &dbp->pdqdb_unsolicited_events[ui->ui_completion];
- event = &ui->ui_events[ui->ui_completion & (PDQ_NUM_UNSOLICITED_EVENTS-1)];
-
- switch (event->event_type) {
- case PDQ_UNSOLICITED_EVENT: {
- printf(PDQ_OS_PREFIX "Unsolicited Event: %s: %s",
- PDQ_OS_PREFIX_ARGS,
- pdq_entities[event->event_entity],
- pdq_event_codes[event->event_entity][event->event_code.value]);
- if (event->event_type == PDQ_ENTITY_PHY_PORT)
- printf("[%d]", event->event_index);
- printf("\n");
- break;
- }
- case PDQ_UNSOLICITED_COUNTERS: {
- break;
- }
- }
- PDQ_ADVANCE(ui->ui_completion, 1, PDQ_RING_MASK(dbp->pdqdb_unsolicited_events));
- ui->ui_free++;
- }
-
- /*
- * Now give back the event buffers back to the PDQ.
- */
- PDQ_ADVANCE(ui->ui_producer, ui->ui_free, PDQ_RING_MASK(dbp->pdqdb_unsolicited_events));
- ui->ui_free = 0;
-
- *csrs->csr_unsolicited_producer = ui->ui_producer | (ui->ui_completion << 8);
-}
-
-static void
-pdq_process_received_data(
- pdq_t *pdq,
- pdq_rx_info_t *rx,
- pdq_rxdesc_t *receives,
- pdq_uint32_t completion_goal,
- pdq_uint32_t ring_mask)
-{
- pdq_uint32_t completion = rx->rx_completion;
- pdq_uint32_t producer = rx->rx_producer;
- PDQ_OS_DATABUF_T **buffers = (PDQ_OS_DATABUF_T **) rx->rx_buffers;
- pdq_rxdesc_t *rxd;
- pdq_uint32_t idx;
-
- while (completion != completion_goal) {
- PDQ_OS_DATABUF_T *fpdu, *lpdu, *npdu;
- pdq_uint8_t *dataptr;
- pdq_uint32_t fc, datalen, pdulen, segcnt;
- pdq_rxstatus_t status;
-
- fpdu = lpdu = buffers[completion];
- PDQ_ASSERT(fpdu != NULL);
-
- dataptr = PDQ_OS_DATABUF_PTR(fpdu);
- status = *(pdq_rxstatus_t *) dataptr;
- if ((status.rxs_status & 0x200000) == 0) {
- datalen = status.rxs_status & 0x1FFF;
- fc = dataptr[PDQ_RX_FC_OFFSET];
- switch (fc & (PDQ_FDDIFC_C|PDQ_FDDIFC_L|PDQ_FDDIFC_F)) {
- case PDQ_FDDI_LLC_ASYNC:
- case PDQ_FDDI_LLC_SYNC:
- case PDQ_FDDI_IMP_ASYNC:
- case PDQ_FDDI_IMP_SYNC: {
- if (datalen > PDQ_FDDI_MAX || datalen < PDQ_FDDI_LLC_MIN) {
- printf("discard: bad length %d\n", datalen);
- goto discard_frame;
- }
- break;
- }
- case PDQ_FDDI_SMT: {
- if (datalen > PDQ_FDDI_MAX || datalen < PDQ_FDDI_SMT_MIN)
- goto discard_frame;
- break;
- }
- default: {
- printf("discard: bad fc 0x%x\n", fc);
- goto discard_frame;
- }
- }
- /*
- * Update the lengths of the data buffers now that we know
- * the real length.
- */
- pdulen = datalen - 4 /* CRC */ + 1 /* FC */;
- segcnt = (pdulen + PDQ_RX_FC_OFFSET + PDQ_OS_DATABUF_SIZE - 1) / PDQ_OS_DATABUF_SIZE;
- PDQ_OS_DATABUF_ALLOC(npdu);
- if (npdu == NULL) {
- printf("discard: no databuf #0\n");
- goto discard_frame;
- }
- buffers[completion] = npdu;
- for (idx = 1; idx < segcnt; idx++) {
- PDQ_OS_DATABUF_ALLOC(npdu);
- if (npdu == NULL) {
- PDQ_OS_DATABUF_NEXT_SET(lpdu, NULL);
- PDQ_OS_DATABUF_FREE(fpdu);
- goto discard_frame;
- }
- PDQ_OS_DATABUF_NEXT_SET(lpdu, buffers[(completion + idx) & ring_mask]);
- lpdu = PDQ_OS_DATABUF_NEXT(lpdu);
- buffers[(completion + idx) & ring_mask] = npdu;
- }
- PDQ_OS_DATABUF_NEXT_SET(lpdu, NULL);
- for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) {
- buffers[(producer + idx) & ring_mask] =
- buffers[(completion + idx) & ring_mask];
- buffers[(completion + idx) & ring_mask] = NULL;
- }
- PDQ_OS_DATABUF_PTR_ADJ(fpdu, PDQ_RX_FC_OFFSET);
- if (segcnt == 1) {
- PDQ_OS_DATABUF_LEN_SET(fpdu, pdulen);
- } else {
- PDQ_OS_DATABUF_LEN_SET(lpdu, pdulen + PDQ_RX_FC_OFFSET - (segcnt - 1) * PDQ_OS_DATABUF_SIZE);
- PDQ_OS_DATABUF_LEN_ADJ(fpdu, -PDQ_RX_FC_OFFSET);
- }
- pdq_os_receive_pdu(pdq, fpdu, pdulen);
- rx->rx_free += PDQ_RX_SEGCNT;
- PDQ_ADVANCE(producer, PDQ_RX_SEGCNT, ring_mask);
- PDQ_ADVANCE(completion, PDQ_RX_SEGCNT, ring_mask);
- continue;
- } else {
- printf("discard: bad pdu 0x%x(%d.%d.%d.%d.%d)\n", status.rxs_status,
- status.rxs_rcc_badpdu, status.rxs_rcc_badcrc,
- status.rxs_rcc_reason, status.rxs_fsc, status.rxs_fsb_e);
- if (status.rxs_rcc_reason == 7)
- goto discard_frame;
- if (status.rxs_rcc_reason != 0)
- /* hardware fault */
- if (status.rxs_rcc_badcrc) {
- /* rx->rx_badcrc++; */
- } else if (status.rxs_fsc == 0 | status.rxs_fsb_e == 1) {
- /* rx->rx_frame_status_errors++; */
- } else {
- /* hardware fault */
- }
- }
- discard_frame:
- /*
- * Discarded frames go right back on the queue; therefore
- * ring entries were freed.
- */
- for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) {
- buffers[producer] = buffers[completion];
- buffers[completion] = NULL;
- rxd = &receives[rx->rx_producer];
- if (idx == 0) {
- rxd->rxd_sop = 1; rxd->rxd_seg_cnt = PDQ_RX_SEGCNT - 1;
- } else {
- rxd->rxd_sop = 0; rxd->rxd_seg_cnt = 0;
- }
- rxd->rxd_pa_hi = 0;
- rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16;
- rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(PDQ_OS_DATABUF_PTR(buffers[rx->rx_producer]));
- PDQ_ADVANCE(rx->rx_producer, 1, ring_mask);
- PDQ_ADVANCE(producer, 1, ring_mask);
- PDQ_ADVANCE(completion, 1, ring_mask);
- }
- }
- rx->rx_completion = completion;
-
- while (rx->rx_free > PDQ_RX_SEGCNT && rx->rx_free > rx->rx_target) {
- PDQ_OS_DATABUF_T *pdu;
- /*
- * Allocate the needed number of data buffers.
- * Try to obtain them from our free queue before
- * asking the system for more.
- */
- for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) {
- if ((pdu = buffers[(rx->rx_producer + idx) & ring_mask]) == NULL) {
- PDQ_OS_DATABUF_ALLOC(pdu);
- if (pdu == NULL)
- break;
- buffers[(rx->rx_producer + idx) & ring_mask] = pdu;
- }
- rxd = &receives[(rx->rx_producer + idx) & ring_mask];
- if (idx == 0) {
- rxd->rxd_sop = 1; rxd->rxd_seg_cnt = PDQ_RX_SEGCNT - 1;
- } else {
- rxd->rxd_sop = 0; rxd->rxd_seg_cnt = 0;
- }
- rxd->rxd_pa_hi = 0;
- rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16;
- rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(PDQ_OS_DATABUF_PTR(pdu));
- }
- if (idx < PDQ_RX_SEGCNT) {
- /*
- * We didn't get all databufs required to complete a new
- * receive buffer. Keep the ones we got and retry a bit
- * later for the rest.
- */
- break;
- }
- PDQ_ADVANCE(rx->rx_producer, PDQ_RX_SEGCNT, ring_mask);
- rx->rx_free -= PDQ_RX_SEGCNT;
- }
-}
-
-pdq_boolean_t
-pdq_queue_transmit_data(
- pdq_t *pdq,
- PDQ_OS_DATABUF_T *pdu)
-{
- pdq_tx_info_t *tx = &pdq->pdq_tx_info;
- pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
- pdq_uint32_t producer = tx->tx_producer;
- pdq_txdesc_t *eop = NULL;
- PDQ_OS_DATABUF_T *pdu0;
- pdq_uint32_t freecnt;
-
- dbp->pdqdb_transmits[producer] = tx->tx_hdrdesc;
- PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits));
-
- for (freecnt = tx->tx_free - 1, pdu0 = pdu; pdu0 != NULL && freecnt > 0;) {
- pdq_uint32_t fraglen, datalen = PDQ_OS_DATABUF_LEN(pdu0);
- const pdq_uint8_t *dataptr = PDQ_OS_DATABUF_PTR(pdu0);
-
- /*
- * The first segment is limited to the space remaining in
- * page. All segments after that can be up to a full page
- * in size.
- */
- fraglen = PDQ_OS_PAGESIZE - ((dataptr - (pdq_uint8_t *) NULL) & (PDQ_OS_PAGESIZE-1));
- while (datalen > 0 && freecnt > 0) {
- pdq_uint32_t seglen = (fraglen < datalen ? fraglen : datalen);
-
- /*
- * Initialize the transmit descriptor
- */
- eop = &dbp->pdqdb_transmits[producer];
- eop->txd_seg_len = seglen;
- eop->txd_pa_lo = PDQ_OS_VA_TO_PA(dataptr);
- eop->txd_sop = eop->txd_eop = eop->txd_pa_hi = 0;
-
- datalen -= seglen;
- dataptr += seglen;
- fraglen = PDQ_OS_PAGESIZE;
- freecnt--;
- PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits));
- }
- pdu0 = PDQ_OS_DATABUF_NEXT(pdu0);
- }
- if (pdu0 != NULL) {
- PDQ_ASSERT(free == 0);
- /*
- * If we still have data to process then the ring was too full
- * to store the PDU. Return FALSE so the caller will requeue
- * the PDU for later.
- */
- return PDQ_FALSE;
- }
- /*
- * Everything went fine. Finish it up.
- */
- tx->tx_descriptor_count[tx->tx_producer] = tx->tx_free - freecnt;
- eop->txd_eop = 1;
- PDQ_OS_DATABUF_ENQUEUE(&tx->tx_txq, pdu);
- tx->tx_producer = producer;
- tx->tx_free = freecnt;
- PDQ_DO_TYPE2_PRODUCER(pdq);
- return PDQ_TRUE;
-}
-
-static void
-pdq_process_transmitted_data(
- pdq_t *pdq)
-{
- pdq_tx_info_t *tx = &pdq->pdq_tx_info;
- volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp;
- pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
- pdq_uint32_t completion = tx->tx_completion;
-
- while (completion != cbp->pdqcb_transmits) {
- PDQ_OS_DATABUF_T *pdu;
- pdq_uint32_t descriptor_count = tx->tx_descriptor_count[completion];
- PDQ_ASSERT(dbp->pdqdb_transmits[tx->tx_completion].txd_sop == 1);
- PDQ_ASSERT(dbp->pdqdb_transmits[(completion + descriptor_count - 1) & PDQ_RING_MASK(dbp->pdqdb_transmits)].txd_eop == 1);
- PDQ_OS_DATABUF_DEQUEUE(&tx->tx_txq, pdu);
- pdq_os_transmit_done(pdq, pdu);
- tx->tx_free += descriptor_count;
-
- PDQ_ADVANCE(completion, descriptor_count, PDQ_RING_MASK(dbp->pdqdb_transmits));
- }
- if (tx->tx_completion != completion) {
- tx->tx_completion = completion;
- pdq_os_restart_transmitter(pdq);
- }
- PDQ_DO_TYPE2_PRODUCER(pdq);
-}
-
-static void
-pdq_flush_transmitter(
- pdq_t *pdq)
-{
- volatile pdq_consumer_block_t *cbp = pdq->pdq_cbp;
- pdq_tx_info_t *tx = &pdq->pdq_tx_info;
-
- for (;;) {
- PDQ_OS_DATABUF_T *pdu;
- PDQ_OS_DATABUF_DEQUEUE(&tx->tx_txq, pdu);
- if (pdu == NULL)
- break;
- /*
- * Don't call transmit done since the packet never made it
- * out on the wire.
- */
- PDQ_OS_DATABUF_FREE(pdu);
- }
-
- tx->tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
- tx->tx_completion = cbp->pdqcb_transmits = tx->tx_producer;
-
- PDQ_DO_TYPE2_PRODUCER(pdq);
-}
-
-/*
- * The following routine brings the PDQ from whatever state it is
- * in to DMA_UNAVAILABLE (ie. like a RESET but without doing a RESET).
- */
-pdq_state_t
-pdq_stop(
- pdq_t *pdq)
-{
- pdq_state_t state;
- const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
- int cnt, pass = 0, idx;
- PDQ_OS_DATABUF_T **buffers;
-
- restart:
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- if (state != PDQS_DMA_UNAVAILABLE) {
- *csrs->csr_port_data_a = (state == PDQS_HALTED) ? 0 : PDQ_PRESET_SKIP_SELFTEST;
- *csrs->csr_port_reset = 1;
- PDQ_OS_USEC_DELAY(100);
- *csrs->csr_port_reset = 0;
- for (cnt = 45000;;cnt--) {
- PDQ_OS_USEC_DELAY(1000);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- if (state == PDQS_DMA_UNAVAILABLE || cnt == 0)
- break;
- }
- PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 45000 - cnt));
- PDQ_OS_USEC_DELAY(10000);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
- PDQ_ASSERT(cnt > 0);
- }
-#if 0
- switch (state) {
- case PDQS_RING_MEMBER:
- case PDQS_LINK_UNAVAILABLE:
- case PDQS_LINK_AVAILABLE: {
- *csrs->csr_port_data_a = PDQ_SUB_CMD_LINK_UNINIT;
- *csrs->csr_port_data_b = 0;
- pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
- /* FALL THROUGH */
- }
- case PDQS_DMA_AVAILABLE: {
- *csrs->csr_port_data_a = 0;
- *csrs->csr_port_data_b = 0;
- pdq_do_port_control(csrs, PDQ_PCTL_DMA_UNINIT);
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
- /* FALL THROUGH */
- }
- case PDQS_DMA_UNAVAILABLE: {
- break;
- }
- }
-#endif
- /*
- * Now we should be in DMA_UNAVAILABLE. So bring the PDQ into
- * DMA_AVAILABLE.
- */
-
- /*
- * Obtain the hardware address and firmware revisions
- * (MLA = my long address which is FDDI speak for hardware address)
- */
- pdq_read_mla(&pdq->pdq_csrs, &pdq->pdq_hwaddr);
- pdq_read_fwrev(&pdq->pdq_csrs, &pdq->pdq_fwrev);
- pdq->pdq_chip_rev = pdq_read_chiprev(&pdq->pdq_csrs);
-
- if (pdq->pdq_type == PDQ_DEFPA) {
- /*
- * Disable interrupts and DMA.
- */
- *pdq->pdq_pci_csrs.csr_pfi_mode_control = 0;
- *pdq->pdq_pci_csrs.csr_pfi_status = 0x10;
- }
-
- /*
- * Flush all the databuf queues.
- */
- pdq_flush_databuf_queue(&pdq->pdq_tx_info.tx_txq);
- buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_rx_info.rx_buffers;
- for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_receives); idx++) {
- if (buffers[idx] != NULL) {
- PDQ_OS_DATABUF_FREE(buffers[idx]);
- buffers[idx] = NULL;
- }
- }
- pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives);
- buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_host_smt_info.rx_buffers;
- for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_host_smt); idx++) {
- if (buffers[idx] != NULL) {
- PDQ_OS_DATABUF_FREE(buffers[idx]);
- buffers[idx] = NULL;
- }
- }
- pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt);
-
- /*
- * Reset the consumer indexes to 0.
- */
- pdq->pdq_cbp->pdqcb_receives = 0;
- pdq->pdq_cbp->pdqcb_transmits = 0;
- pdq->pdq_cbp->pdqcb_host_smt = 0;
- pdq->pdq_cbp->pdqcb_unsolicited_event = 0;
- pdq->pdq_cbp->pdqcb_command_response = 0;
- pdq->pdq_cbp->pdqcb_command_request = 0;
-
- /*
- * Reset the producer and completion indexes to 0.
- */
- pdq->pdq_command_info.ci_request_producer = 0;
- pdq->pdq_command_info.ci_response_producer = 0;
- pdq->pdq_command_info.ci_request_completion = 0;
- pdq->pdq_command_info.ci_response_completion = 0;
- pdq->pdq_unsolicited_info.ui_producer = 0;
- pdq->pdq_unsolicited_info.ui_completion = 0;
- pdq->pdq_rx_info.rx_producer = 0;
- pdq->pdq_rx_info.rx_completion = 0;
- pdq->pdq_tx_info.tx_producer = 0;
- pdq->pdq_tx_info.tx_completion = 0;
- pdq->pdq_host_smt_info.rx_producer = 0;
- pdq->pdq_host_smt_info.rx_completion = 0;
-
- pdq->pdq_command_info.ci_request_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_command_requests);
- pdq->pdq_command_info.ci_response_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_command_responses);
- pdq->pdq_unsolicited_info.ui_free = PDQ_NUM_UNSOLICITED_EVENTS;
- pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
-
- /*
- * Allow the DEFPA to do DMA. Then program the physical
- * addresses of the consumer and descriptor blocks.
- */
- if (pdq->pdq_type == PDQ_DEFPA) {
-#ifdef PDQTEST
- *pdq->pdq_pci_csrs.csr_pfi_mode_control = PDQ_PFI_MODE_DMA_ENABLE;
-#else
- *pdq->pdq_pci_csrs.csr_pfi_mode_control = PDQ_PFI_MODE_DMA_ENABLE
- |PDQ_PFI_MODE_PFI_PCI_INTR|PDQ_PFI_MODE_PDQ_PCI_INTR;
-#endif
- }
-
- /*
- * Make the unsolicited queue has events ...
- */
- pdq_process_unsolicited_events(pdq);
-
- *csrs->csr_port_data_b = PDQ_DMA_BURST_8LW;
- *csrs->csr_port_data_a = PDQ_SUB_CMD_DMA_BURST_SIZE_SET;
- pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
-
- *csrs->csr_port_data_b = 0;
- *csrs->csr_port_data_a = PDQ_OS_VA_TO_PA(pdq->pdq_cbp);
- pdq_do_port_control(csrs, PDQ_PCTL_CONSUMER_BLOCK);
-
- *csrs->csr_port_data_b = 0;
- *csrs->csr_port_data_a = PDQ_OS_VA_TO_PA(pdq->pdq_dbp) | PDQ_DMA_INIT_LW_BSWAP_DATA;
- pdq_do_port_control(csrs, PDQ_PCTL_DMA_INIT);
-
- for (cnt = 0; cnt < 1000; cnt++) {
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- if (state == PDQS_HALTED) {
- if (pass > 0)
- return PDQS_HALTED;
- pass = 1;
- goto restart;
- }
- if (state == PDQS_DMA_AVAILABLE) {
- PDQ_PRINTF(("Transition to DMA Available took %d spins\n", cnt));
- break;
- }
- PDQ_OS_USEC_DELAY(1000);
- }
- PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
-
- *csrs->csr_host_int_type_0 = 0xFF;
- *csrs->csr_host_int_enable = 0 /* PDQ_HOST_INT_STATE_CHANGE
- |PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE
- |PDQ_HOST_INT_UNSOL_ENABLE */;
-
- /*
- * Any other command but START should be valid.
- */
- pdq->pdq_command_info.ci_pending_commands &= ~(PDQ_BITMASK(PDQC_START));
- if (pdq->pdq_flags & PDQ_PRINTCHARS)
- pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
- pdq_queue_commands(pdq);
-
- if (pdq->pdq_flags & PDQ_PRINTCHARS) {
- /*
- * Now wait (up to 100ms) for the command(s) to finish.
- */
- for (cnt = 0; cnt < 1000; cnt++) {
- pdq_process_command_responses(pdq);
- if (pdq->pdq_command_info.ci_response_producer == pdq->pdq_command_info.ci_response_completion)
- break;
- PDQ_OS_USEC_DELAY(1000);
- }
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- }
-
- return state;
-}
-
-void
-pdq_run(
- pdq_t *pdq)
-{
- const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
- pdq_state_t state;
-
- state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- PDQ_ASSERT(state != PDQS_DMA_UNAVAILABLE);
- PDQ_ASSERT(state != PDQS_RESET);
- PDQ_ASSERT(state != PDQS_HALTED);
- PDQ_ASSERT(state != PDQS_UPGRADE);
- PDQ_ASSERT(state != PDQS_RING_MEMBER);
- switch (state) {
- case PDQS_DMA_AVAILABLE: {
- /*
- * The PDQ after being reset screws up some of its state.
- * So we need to clear all the errors/interrupts so the real
- * ones will get through.
- */
- *csrs->csr_host_int_type_0 = 0xFF;
- *csrs->csr_host_int_enable = PDQ_HOST_INT_STATE_CHANGE|PDQ_HOST_INT_XMT_DATA_FLUSH
- |PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE|PDQ_HOST_INT_UNSOL_ENABLE
- |PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_TX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE;
- /*
- * Set the MAC and address filters and start up the PDQ.
- */
- pdq_process_unsolicited_events(pdq);
- pdq_process_received_data(pdq, &pdq->pdq_rx_info,
- pdq->pdq_dbp->pdqdb_receives,
- pdq->pdq_cbp->pdqcb_receives,
- PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives));
- PDQ_DO_TYPE2_PRODUCER(pdq);
- if (pdq->pdq_flags & PDQ_PASS_SMT) {
- pdq_process_received_data(pdq, &pdq->pdq_host_smt_info,
- pdq->pdq_dbp->pdqdb_host_smt,
- pdq->pdq_cbp->pdqcb_host_smt,
- PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
- *csrs->csr_host_smt_producer = pdq->pdq_host_smt_info.rx_producer | (pdq->pdq_host_smt_info.rx_completion << 8);
- }
- pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET)
- | PDQ_BITMASK(PDQC_ADDR_FILTER_SET) | PDQ_BITMASK(PDQC_START);
- if (pdq->pdq_flags & PDQ_PRINTCHARS)
- pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
- pdq_queue_commands(pdq);
- break;
- }
- case PDQS_LINK_UNAVAILABLE:
- case PDQS_LINK_AVAILABLE: {
- pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET)
- | PDQ_BITMASK(PDQC_ADDR_FILTER_SET);
- if (pdq->pdq_flags & PDQ_PRINTCHARS)
- pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
- if (pdq->pdq_flags & PDQ_PASS_SMT) {
- pdq_process_received_data(pdq, &pdq->pdq_host_smt_info,
- pdq->pdq_dbp->pdqdb_host_smt,
- pdq->pdq_cbp->pdqcb_host_smt,
- PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
- *csrs->csr_host_smt_producer = pdq->pdq_host_smt_info.rx_producer | (pdq->pdq_host_smt_info.rx_completion << 8);
- }
- pdq_process_unsolicited_events(pdq);
- pdq_queue_commands(pdq);
- break;
- }
- case PDQS_RING_MEMBER: {
- }
- break;
- default:
- break;
- }
-}
-
-int
-pdq_interrupt(
- pdq_t *pdq)
-{
- const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
- pdq_uint32_t data;
- int progress = 0;
-
- if (pdq->pdq_type == PDQ_DEFPA)
- if (*pdq->pdq_pci_csrs.csr_pfi_status & 0x10)
- *pdq->pdq_pci_csrs.csr_pfi_status = 0x10;
-
- while ((data = *csrs->csr_port_status) & PDQ_PSTS_INTR_PENDING) {
- progress = 1;
- PDQ_PRINTF(("PDQ Interrupt: Status = 0x%08x\n", data));
- if (data & PDQ_PSTS_RCV_DATA_PENDING) {
- pdq_process_received_data(pdq, &pdq->pdq_rx_info,
- pdq->pdq_dbp->pdqdb_receives,
- pdq->pdq_cbp->pdqcb_receives,
- PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives));
- PDQ_DO_TYPE2_PRODUCER(pdq);
- }
- if (data & PDQ_PSTS_HOST_SMT_PENDING) {
- pdq_process_received_data(pdq, &pdq->pdq_host_smt_info,
- pdq->pdq_dbp->pdqdb_host_smt,
- pdq->pdq_cbp->pdqcb_host_smt,
- PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
- *csrs->csr_host_smt_producer = pdq->pdq_host_smt_info.rx_producer | (pdq->pdq_host_smt_info.rx_completion << 8);
- }
- if (data & PDQ_PSTS_XMT_DATA_PENDING)
- pdq_process_transmitted_data(pdq);
- if (data & PDQ_PSTS_UNSOL_PENDING)
- pdq_process_unsolicited_events(pdq);
- if (data & PDQ_PSTS_CMD_RSP_PENDING)
- pdq_process_command_responses(pdq);
- if (data & PDQ_PSTS_TYPE_0_PENDING) {
- data = *csrs->csr_host_int_type_0;
- if (data & PDQ_HOST_INT_STATE_CHANGE) {
- pdq_state_t state = PDQ_PSTS_ADAPTER_STATE(*csrs->csr_port_status);
- printf(PDQ_OS_PREFIX "%s", PDQ_OS_PREFIX_ARGS, pdq_adapter_states[state]);
- if (state == PDQS_LINK_UNAVAILABLE) {
- pdq->pdq_flags &= ~PDQ_TXOK;
- } else if (state == PDQS_LINK_AVAILABLE) {
- pdq->pdq_flags |= PDQ_TXOK;
- pdq_os_restart_transmitter(pdq);
- } else if (state == PDQS_HALTED) {
- pdq_response_error_log_get_t log_entry;
- pdq_halt_code_t halt_code = PDQ_PSTS_HALT_ID(*csrs->csr_port_status);
- printf(": halt code = %d (%s)\n",
- halt_code, pdq_halt_codes[halt_code]);
- if (halt_code == PDQH_DMA_ERROR) {
- PDQ_PRINTF(("\tPFI status = 0x%x, Host 0 Fatal Interrupt = 0x%x\n",
- *pdq->pdq_pci_csrs.csr_pfi_status,
- data & PDQ_HOST_INT_FATAL_ERROR));
- }
- pdq_read_error_log(pdq, &log_entry);
- pdq_stop(pdq);
- if (pdq->pdq_flags & PDQ_RUNNING)
- pdq_run(pdq);
- return 1;
- }
- printf("\n");
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_STATE_CHANGE;
- }
- if (data & PDQ_HOST_INT_FATAL_ERROR) {
- pdq_stop(pdq);
- if (pdq->pdq_flags & PDQ_RUNNING)
- pdq_run(pdq);
- return 1;
- }
- if (data & PDQ_HOST_INT_XMT_DATA_FLUSH) {
- printf(PDQ_OS_PREFIX "Flushing transmit queue\n", PDQ_OS_PREFIX_ARGS);
- pdq->pdq_flags &= ~PDQ_TXOK;
- pdq_flush_transmitter(pdq);
- pdq_do_port_control(csrs, PDQ_PCTL_XMT_DATA_FLUSH_DONE);
- *csrs->csr_host_int_type_0 = PDQ_HOST_INT_XMT_DATA_FLUSH;
- }
- }
- if (pdq->pdq_type == PDQ_DEFPA)
- if (*pdq->pdq_pci_csrs.csr_pfi_status & 0x10)
- *pdq->pdq_pci_csrs.csr_pfi_status = 0x10;
- }
- return progress;
-}
-
-pdq_t *
-pdq_initialize(
- void *csr_va,
- const char *name,
- int unit,
- void *ctx,
- pdq_type_t type)
-{
- pdq_t *pdq;
- pdq_state_t state;
- const pdq_uint32_t contig_bytes = (sizeof(pdq_descriptor_block_t) * 2) - PDQ_OS_PAGESIZE;
- pdq_uint8_t *p;
- int idx;
-
- PDQ_ASSERT(sizeof(pdq_descriptor_block_t) == 8192);
- PDQ_ASSERT(sizeof(pdq_consumer_block_t) == 64);
- PDQ_ASSERT(sizeof(pdq_response_filter_get_t) == PDQ_SIZE_RESPONSE_FILTER_GET);
- PDQ_ASSERT(sizeof(pdq_cmd_addr_filter_set_t) == PDQ_SIZE_CMD_ADDR_FILTER_SET);
- PDQ_ASSERT(sizeof(pdq_response_addr_filter_get_t) == PDQ_SIZE_RESPONSE_ADDR_FILTER_GET);
- PDQ_ASSERT(sizeof(pdq_response_status_chars_get_t) == PDQ_SIZE_RESPONSE_STATUS_CHARS_GET);
- PDQ_ASSERT(sizeof(pdq_response_fddi_mib_get_t) == PDQ_SIZE_RESPONSE_FDDI_MIB_GET);
- PDQ_ASSERT(sizeof(pdq_response_dec_ext_mib_get_t) == PDQ_SIZE_RESPONSE_DEC_EXT_MIB_GET);
- PDQ_ASSERT(sizeof(pdq_unsolicited_event_t) == 512);
-
- pdq = (pdq_t *) PDQ_OS_MEMALLOC(sizeof(pdq_t));
- if (pdq == NULL) {
- PDQ_PRINTF(("malloc(%d) failed\n", sizeof(*pdq)));
- return NULL;
- }
- PDQ_OS_MEMZERO(pdq, sizeof(pdq_t));
- pdq->pdq_type = type;
- pdq->pdq_unit = unit;
- pdq->pdq_os_ctx = (void *) ctx;
- pdq->pdq_os_name = name;
- pdq->pdq_flags = PDQ_PRINTCHARS;
- /*
- * Allocate the additional data structures required by
- * the PDQ driver. Allocate a contiguous region of memory
- * for the descriptor block. We need to allocated enough
- * to guarantee that we will a get 8KB block of memory aligned
- * on a 8KB boundary. This turns to require that we allocate
- * (N*2 - 1 page) pages of memory. On machine with less than
- * a 8KB page size, it mean we will allocate more memory than
- * we need. The extra will be used for the unsolicited event
- * buffers (though on machines with 8KB pages we will to allocate
- * them separately since there will be nothing left overs.)
- */
- p = (pdq_uint8_t *) PDQ_OS_MEMALLOC_CONTIG(contig_bytes);
- if (p != NULL) {
- pdq_physaddr_t physaddr = PDQ_OS_VA_TO_PA(p) & 0x1FFF;
- if (physaddr) {
- pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) p;
- pdq->pdq_dbp = (pdq_descriptor_block_t *) &p[0x2000 - physaddr];
- } else {
- pdq->pdq_dbp = (pdq_descriptor_block_t *) p;
- pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) &p[0x2000];
- }
- }
- if (contig_bytes == sizeof(pdq_descriptor_block_t)) {
- pdq->pdq_unsolicited_info.ui_events =
- (pdq_unsolicited_event_t *) PDQ_OS_MEMALLOC(
- PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t));
- }
-
- /*
- * Make sure everything got allocated. If not, free what did
- * get allocated and return.
- */
- if (pdq->pdq_dbp == NULL || pdq->pdq_unsolicited_info.ui_events == NULL) {
- cleanup_and_return:
- if (pdq->pdq_dbp != NULL)
- PDQ_OS_MEMFREE_CONTIG(pdq->pdq_dbp, contig_bytes);
- if (contig_bytes == sizeof(pdq_descriptor_block_t) && pdq->pdq_unsolicited_info.ui_events != NULL)
- PDQ_OS_MEMFREE(pdq->pdq_unsolicited_info.ui_events,
- PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t));
- PDQ_OS_MEMFREE(pdq, sizeof(pdq_t));
- return NULL;
- }
-
- pdq->pdq_cbp = (volatile pdq_consumer_block_t *) &pdq->pdq_dbp->pdqdb_consumer;
- pdq->pdq_command_info.ci_bufstart = (pdq_uint8_t *) pdq->pdq_dbp->pdqdb_command_pool;
- pdq->pdq_rx_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_receive_buffers;
-
- pdq->pdq_host_smt_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_host_smt_buffers;
-
- PDQ_PRINTF(("PDQ Descriptor Block = %p\n", pdq->pdq_dbp));
- PDQ_PRINTF((" Recieve Queue = %p\n", pdq->pdq_dbp->pdqdb_receives));
- PDQ_PRINTF((" Transmit Queue = %p\n", pdq->pdq_dbp->pdqdb_transmits));
- PDQ_PRINTF((" Host SMT Queue = %p\n", pdq->pdq_dbp->pdqdb_host_smt));
- PDQ_PRINTF((" Command Response Queue = %p\n", pdq->pdq_dbp->pdqdb_command_responses));
- PDQ_PRINTF((" Command Request Queue = %p\n", pdq->pdq_dbp->pdqdb_command_requests));
- PDQ_PRINTF(("PDQ Consumer Block = %p\n", pdq->pdq_cbp));
-
- /*
- * Zero out the descriptor block. Not really required but
- * it pays to be neat. This will also zero out the consumer
- * block, command pool, and buffer pointers for the receive
- * host_smt rings.
- */
- PDQ_OS_MEMZERO(pdq->pdq_dbp, sizeof(*pdq->pdq_dbp));
-
- /*
- * Initialize the CSR references.
- */
- pdq_init_csrs(&pdq->pdq_csrs, csr_va, 1);
- switch (pdq->pdq_type) {
- case PDQ_DEFPA: pdq_init_pci_csrs(&pdq->pdq_pci_csrs, csr_va, 1); break;
-#ifdef PDQ_DO_EISA
- case PDQ_DEFEA: pdq_init_esia_csrs(&pdq->pdq_eisa_csrs, csr_va, 1); break;
-#endif
- default:
- break;
- }
-
- PDQ_PRINTF(("PDQ CSRs:\n"));
- PDQ_PRINTF((" Port Reset = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_port_reset, *pdq->pdq_csrs.csr_port_reset));
- PDQ_PRINTF((" Host Data = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_host_data, *pdq->pdq_csrs.csr_host_data));
- PDQ_PRINTF((" Port Control = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_port_control, *pdq->pdq_csrs.csr_port_control));
- PDQ_PRINTF((" Port Data A = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_port_data_a, *pdq->pdq_csrs.csr_port_data_a));
- PDQ_PRINTF((" Port Data B = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_port_data_b, *pdq->pdq_csrs.csr_port_data_b));
- PDQ_PRINTF((" Port Status = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_port_status, *pdq->pdq_csrs.csr_port_status));
- PDQ_PRINTF((" Host Int Type 0 = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_host_int_type_0, *pdq->pdq_csrs.csr_host_int_type_0));
- PDQ_PRINTF((" Host Int Enable = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_host_int_enable, *pdq->pdq_csrs.csr_host_int_enable));
- PDQ_PRINTF((" Type 2 Producer = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_type_2_producer, *pdq->pdq_csrs.csr_type_2_producer));
- PDQ_PRINTF((" Command Response Producer = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_cmd_response_producer, *pdq->pdq_csrs.csr_cmd_response_producer));
- PDQ_PRINTF((" Command Request Producer = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_cmd_request_producer, *pdq->pdq_csrs.csr_cmd_request_producer));
- PDQ_PRINTF((" Host SMT Producer = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_host_smt_producer, *pdq->pdq_csrs.csr_host_smt_producer));
- PDQ_PRINTF((" Unsolicited Producer = %p [0x%08x]\n",
- pdq->pdq_csrs.csr_unsolicited_producer, *pdq->pdq_csrs.csr_unsolicited_producer));
-
- /*
- * Initialize the command information block
- */
- pdq->pdq_command_info.ci_buffree = sizeof(pdq->pdq_dbp->pdqdb_command_pool);
- pdq->pdq_command_info.ci_bufend = pdq->pdq_command_info.ci_bufstart + pdq->pdq_command_info.ci_buffree;
- pdq->pdq_command_info.ci_bufptr = pdq->pdq_command_info.ci_bufstart;
- pdq->pdq_command_info.ci_pa_bufstart = PDQ_OS_VA_TO_PA(pdq->pdq_command_info.ci_bufstart);
- pdq->pdq_command_info.ci_request_max = pdq->pdq_command_info.ci_request_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_command_requests);
- pdq->pdq_command_info.ci_response_max = pdq->pdq_command_info.ci_response_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_command_responses);
-
- /*
- * Initialize the unsolicited event information block
- */
- pdq->pdq_unsolicited_info.ui_free = PDQ_NUM_UNSOLICITED_EVENTS;
- pdq->pdq_unsolicited_info.ui_pa_bufstart = PDQ_OS_VA_TO_PA(pdq->pdq_unsolicited_info.ui_events);
- for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events)/sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events[0]); idx++) {
- pdq_rxdesc_t *rxd = &pdq->pdq_dbp->pdqdb_unsolicited_events[idx];
- pdq_unsolicited_event_t *event = &pdq->pdq_unsolicited_info.ui_events[idx & (PDQ_NUM_UNSOLICITED_EVENTS-1)];
-
- rxd->rxd_sop = 1;
- rxd->rxd_seg_cnt = 0;
- rxd->rxd_seg_len_hi = sizeof(pdq_unsolicited_event_t) / 16;
- rxd->rxd_pa_lo = pdq->pdq_unsolicited_info.ui_pa_bufstart + (const pdq_uint8_t *) event
- - (const pdq_uint8_t *) pdq->pdq_unsolicited_info.ui_events;
- rxd->rxd_pa_hi = 0;
- }
- /*
- * Initialize the receive information blocks (normal and SMT).
- */
- pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives);
- pdq->pdq_rx_info.rx_target = pdq->pdq_rx_info.rx_free - PDQ_RX_SEGCNT * 8;
-
- pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt);
- pdq->pdq_host_smt_info.rx_target = pdq->pdq_host_smt_info.rx_free - PDQ_RX_SEGCNT * 3;
-
- /*
- * Initialize the transmit information block.
- */
- pdq->pdq_tx_hdr[0] = PDQ_FDDI_PH0;
- pdq->pdq_tx_hdr[1] = PDQ_FDDI_PH1;
- pdq->pdq_tx_hdr[2] = PDQ_FDDI_PH2;
- pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
- pdq->pdq_tx_info.tx_hdrdesc.txd_seg_len = sizeof(pdq->pdq_tx_hdr);
- pdq->pdq_tx_info.tx_hdrdesc.txd_sop = 1;
- pdq->pdq_tx_info.tx_hdrdesc.txd_pa_lo = PDQ_OS_VA_TO_PA(pdq->pdq_tx_hdr);
-
- state = PDQ_PSTS_ADAPTER_STATE(*pdq->pdq_csrs.csr_port_status);
- PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states[state]));
-
- /*
- * Stop the PDQ if it is running and put it into a known state.
- */
- state = pdq_stop(pdq);
-
- /* state = PDQ_PSTS_ADAPTER_STATE(*pdq->pdq_csrs.csr_port_status); */
- PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states[state]));
- PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
- /*
- * If the adapter is not the state we expect, then the initialization
- * failed. Cleanup and exit.
- */
- if (state == PDQS_RESET || state == PDQS_HALTED || state == PDQS_UPGRADE)
- goto cleanup_and_return;
-
- PDQ_PRINTF(("PDQ Hardware Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
- pdq->pdq_hwaddr.lanaddr_bytes[0], pdq->pdq_hwaddr.lanaddr_bytes[1],
- pdq->pdq_hwaddr.lanaddr_bytes[2], pdq->pdq_hwaddr.lanaddr_bytes[3],
- pdq->pdq_hwaddr.lanaddr_bytes[4], pdq->pdq_hwaddr.lanaddr_bytes[5]));
- PDQ_PRINTF(("PDQ Firmware Revision = %c%c%c%c\n",
- pdq->pdq_fwrev.fwrev_bytes[0], pdq->pdq_fwrev.fwrev_bytes[1],
- pdq->pdq_fwrev.fwrev_bytes[2], pdq->pdq_fwrev.fwrev_bytes[3]));
- PDQ_PRINTF(("PDQ Chip Revision = "));
- switch (pdq->pdq_chip_rev) {
- case PDQ_CHIP_REV_A_B_OR_C: PDQ_PRINTF(("Rev C or below")); break;
- case PDQ_CHIP_REV_D: PDQ_PRINTF(("Rev D")); break;
- case PDQ_CHIP_REV_E: PDQ_PRINTF(("Rev E")); break;
- default: PDQ_PRINTF(("Unknown Rev %d", (int) pdq->pdq_chip_rev));
- }
- PDQ_PRINTF(("\n"));
-
- return pdq;
-}
OpenPOWER on IntegriCloud