📄 defxx.c
字号:
* acknowledges the state change interrupt. * * INCORRECT CORRECT * read type 0 int reasons read type 0 int reasons * read adapter state ack type 0 interrupts * ack type 0 interrupts read adapter state * ... process interrupt ... ... process interrupt ... * * Return Codes: * None * * Assumptions: * None * * Side Effects: * An adapter reset may occur if the adapter has any Type 0 error interrupts * or if the port status indicates that the adapter is halted. The driver * is responsible for reinitializing the adapter with the current CAM * contents and adapter filter settings. */void dfx_int_type_0_process( DFX_board_t *bp ) { PI_UINT32 type_0_status; /* Host Interrupt Type 0 register */ PI_UINT32 state; /* current adap state (from port status) */ /* * Read host interrupt Type 0 register to determine which Type 0 * interrupts are pending. Immediately write it back out to clear * those interrupts. */ dfx_port_read_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, &type_0_status); dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, type_0_status); /* Check for Type 0 error interrupts */ if (type_0_status & (PI_TYPE_0_STAT_M_NXM | PI_TYPE_0_STAT_M_PM_PAR_ERR | PI_TYPE_0_STAT_M_BUS_PAR_ERR)) { /* Check for Non-Existent Memory error */ if (type_0_status & PI_TYPE_0_STAT_M_NXM) printk("%s: Non-Existent Memory Access Error\n", bp->dev->name); /* Check for Packet Memory Parity error */ if (type_0_status & PI_TYPE_0_STAT_M_PM_PAR_ERR) printk("%s: Packet Memory Parity Error\n", bp->dev->name); /* Check for Host Bus Parity error */ if (type_0_status & PI_TYPE_0_STAT_M_BUS_PAR_ERR) printk("%s: Host Bus Parity Error\n", bp->dev->name); /* Reset adapter and bring it back on-line */ bp->link_available = PI_K_FALSE; /* link is no longer available */ bp->reset_type = 0; /* rerun on-board diagnostics */ printk("%s: Resetting adapter...\n", bp->dev->name); if (dfx_adap_init(bp) != DFX_K_SUCCESS) { printk("%s: Adapter reset failed! Disabling adapter interrupts.\n", bp->dev->name); dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS); return; } printk("%s: Adapter reset successful!\n", bp->dev->name); return; } /* Check for transmit flush interrupt */ if (type_0_status & PI_TYPE_0_STAT_M_XMT_FLUSH) { /* Flush any pending xmt's and acknowledge the flush interrupt */ bp->link_available = PI_K_FALSE; /* link is no longer available */ dfx_xmt_flush(bp); /* flush any outstanding packets */ (void) dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_XMT_DATA_FLUSH_DONE, 0, 0, NULL); } /* Check for adapter state change */ if (type_0_status & PI_TYPE_0_STAT_M_STATE_CHANGE) { /* Get latest adapter state */ state = dfx_hw_adap_state_rd(bp); /* get adapter state */ if (state == PI_STATE_K_HALTED) { /* * Adapter has transitioned to HALTED state, try to reset * adapter to bring it back on-line. If reset fails, * leave the adapter in the broken state. */ printk("%s: Controller has transitioned to HALTED state!\n", bp->dev->name); dfx_int_pr_halt_id(bp); /* display halt id as string */ /* Reset adapter and bring it back on-line */ bp->link_available = PI_K_FALSE; /* link is no longer available */ bp->reset_type = 0; /* rerun on-board diagnostics */ printk("%s: Resetting adapter...\n", bp->dev->name); if (dfx_adap_init(bp) != DFX_K_SUCCESS) { printk("%s: Adapter reset failed! Disabling adapter interrupts.\n", bp->dev->name); dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS); return; } printk("%s: Adapter reset successful!\n", bp->dev->name); } else if (state == PI_STATE_K_LINK_AVAIL) { bp->link_available = PI_K_TRUE; /* set link available flag */ } } return; }/* * ================== * = dfx_int_common = * ================== * * Overview: * Interrupt service routine (ISR) * * Returns: * None * * Arguments: * bp - pointer to board information * * Functional Description: * This is the ISR which processes incoming adapter interrupts. * * Return Codes: * None * * Assumptions: * This routine assumes PDQ interrupts have not been disabled. * When interrupts are disabled at the PDQ, the Port Status register * is automatically cleared. This routine uses the Port Status * register value to determine whether a Type 0 interrupt occurred, * so it's important that adapter interrupts are not normally * enabled/disabled at the PDQ. * * It's vital that this routine is NOT reentered for the * same board and that the OS is not in another section of * code (eg. dfx_xmt_queue_pkt) for the same board on a * different thread. * * Side Effects: * Pending interrupts are serviced. Depending on the type of * interrupt, acknowledging and clearing the interrupt at the * PDQ involves writing a register to clear the interrupt bit * or updating completion indices. */void dfx_int_common( DFX_board_t *bp ) { PI_UINT32 port_status; /* Port Status register */ /* Process xmt interrupts - frequent case, so always call this routine */ dfx_xmt_done(bp); /* free consumed xmt packets */ /* Process rcv interrupts - frequent case, so always call this routine */ dfx_rcv_queue_process(bp); /* service received LLC frames */ /* * Transmit and receive producer and completion indices are updated on the * adapter by writing to the Type 2 Producer register. Since the frequent * case is that we'll be processing either LLC transmit or receive buffers, * we'll optimize I/O writes by doing a single register write here. */ dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword); /* Read PDQ Port Status register to find out which interrupts need processing */ dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status); /* Process Type 0 interrupts (if any) - infrequent, so only call when needed */ if (port_status & PI_PSTATUS_M_TYPE_0_PENDING) dfx_int_type_0_process(bp); /* process Type 0 interrupts */ return; }/* * ================= * = dfx_interrupt = * ================= * * Overview: * Interrupt processing routine * * Returns: * None * * Arguments: * irq - interrupt vector * dev_id - pointer to device information * regs - pointer to registers structure * * Functional Description: * This routine calls the interrupt processing routine for this adapter. It * disables and reenables adapter interrupts, as appropriate. We can support * shared interrupts since the incoming dev_id pointer provides our device * structure context. * * Return Codes: * None * * Assumptions: * The interrupt acknowledgement at the hardware level (eg. ACKing the PIC * on Intel-based systems) is done by the operating system outside this * routine. * * System interrupts are enabled through this call. * * Side Effects: * Interrupts are disabled, then reenabled at the adapter. */void dfx_interrupt( int irq, void *dev_id, struct pt_regs *regs ) { struct device *dev = (struct device *) dev_id; DFX_board_t *bp; /* private board structure pointer */ u8 tmp; /* used for disabling/enabling ints */ /* Get board pointer only if device structure is valid */ if (dev == NULL) { printk("dfx_interrupt(): irq %d for unknown device!\n", irq); return; } bp = (DFX_board_t *) dev->priv; spin_lock(&bp->lock); /* See if we're already servicing an interrupt */ if (dev->interrupt) printk("%s: Re-entering the interrupt handler!\n", dev->name); dev->interrupt = DFX_MASK_INTERRUPTS; /* ensure non reentrancy */ /* Service adapter interrupts */ if (bp->bus_type == DFX_BUS_TYPE_PCI) { /* Disable PDQ-PFI interrupts at PFI */ dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, PFI_MODE_M_DMA_ENB); /* Call interrupt service routine for this adapter */ dfx_int_common(bp); /* Clear PDQ interrupt status bit and reenable interrupts */ dfx_port_write_long(bp, PFI_K_REG_STATUS, PFI_STATUS_M_PDQ_INT); dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, (PFI_MODE_M_PDQ_INT_ENB + PFI_MODE_M_DMA_ENB)); } else { /* Disable interrupts at the ESIC */ dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp); tmp &= ~PI_CONFIG_STAT_0_M_INT_ENB; dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp); /* Call interrupt service routine for this adapter */ dfx_int_common(bp); /* Reenable interrupts at the ESIC */ dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp); tmp |= PI_CONFIG_STAT_0_M_INT_ENB; dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp); } dev->interrupt = DFX_UNMASK_INTERRUPTS; spin_unlock(&bp->lock); return; }/* * ===================== * = dfx_ctl_get_stats = * ===================== * * Overview: * Get statistics for FDDI adapter * * Returns: * Pointer to FDDI statistics structure * * Arguments: * dev - pointer to device information * * Functional Description: * Gets current MIB objects from adapter, then * returns FDDI statistics structure as defined * in if_fddi.h. * * Note: Since the FDDI statistics structure is * still new and the device structure doesn't * have an FDDI-specific get statistics handler, * we'll return the FDDI statistics structure as * a pointer to an Ethernet statistics structure. * That way, at least the first part of the statistics * structure can be decoded properly, and it allows * "smart" applications to perform a second cast to * decode the FDDI-specific statistics. * * We'll have to pay attention to this routine as the * device structure becomes more mature and LAN media * independent. * * Return Codes: * None * * Assumptions: * None * * Side Effects: * None */struct net_device_stats *dfx_ctl_get_stats( struct device *dev ) { DFX_board_t *bp = (DFX_board_t *)dev->priv; /* Fill the bp->stats structure with driver-maintained counters */ bp->stats.rx_packets = bp->rcv_total_frames; bp->stats.tx_packets = bp->xmt_total_frames; bp->stats.rx_bytes = bp->rcv_total_bytes; bp->stats.tx_bytes = bp->xmt_total_bytes; bp->stats.rx_errors = (u32)(bp->rcv_crc_errors + bp->rcv_frame_status_errors + bp->rcv_length_errors); bp->stats.tx_errors = bp->xmt_length_errors; bp->stats.rx_dropped = bp->rcv_discards; bp->stats.tx_dropped = bp->xmt_discards; bp->stats.multicast = bp->rcv_multicast_frames; bp->stats.transmit_collision = 0; /* always zero (0) for FDDI */ /* Get FDDI SMT MIB objects */ bp->cmd_req_virt->cmd_type = PI_CMD_K_SMT_MIB_GET; if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS) return((struct net_device_stats *) &bp->stats); /* Fill the bp->stats structure with the SMT MIB object values */ memcpy(bp->stats.smt_station_id, &bp->cmd_rsp_virt->smt_mib_get.smt_station_id, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_station_id)); bp->stats.smt_op_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id; bp->stats.smt_hi_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id; bp->stats.smt_lo_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id; memcpy(bp->stats.smt_user_data, &bp->cmd_rsp_virt->smt_mib_get.smt_user_data, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_user_data)); bp->stats.smt_mib_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id; bp->stats.smt_mac_cts = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct; bp->stats.smt_non_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct; bp->stats.smt_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct; bp->stats.smt_available_paths = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths; bp->stats.smt_config_capabilities = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities; bp->stats.smt_config_policy = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy; bp->stats.smt_connection_policy = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy; bp->stats.smt_t_notify = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify; bp->stats.smt_stat_rpt_policy = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy; bp->stats.smt_trace_max_expiration = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration; bp->stats.smt_bypass_present = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present; bp->stats.smt_ecm_state = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state; bp->stats.smt_cf_state = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state; bp->stats.smt_remote_disconnect_flag = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag; bp->stats.smt_station_status = bp->cmd_rsp_virt->smt_mib_get.smt_station_status; bp->stats.smt_peer_wrap_flag = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag; bp->stats.smt_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls; bp->stats.smt_transition_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls; bp->stats.mac_frame_status_functions = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions; bp->stats.mac_t_max_capability = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability; bp->stats.mac_tvx_capability = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability; bp->stats.mac_available_paths = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths; bp->stats.mac_current_path = bp->cmd_rsp_virt->smt_mib_get.mac_current_path; memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_u
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -