| /* |
| * This file is provided under a CDDLv1 license. When using or |
| * redistributing this file, you may do so under this license. |
| * In redistributing this file this license must be included |
| * and no other modification of this header file is permitted. |
| * |
| * CDDL LICENSE SUMMARY |
| * |
| * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved. |
| * |
| * The contents of this file are subject to the terms of Version |
| * 1.0 of the Common Development and Distribution License (the "License"). |
| * |
| * You should have received a copy of the License with this software. |
| * You can obtain a copy of the License at |
| * http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| */ |
| |
| /* |
| * Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms of the CDDLv1. |
| */ |
| |
| /* |
| * ********************************************************************** |
| * * |
| * Module Name: * |
| * e1000g_debug.c * |
| * * |
| * Abstract: * |
| * This module includes the debug routines * |
| * * |
| * ********************************************************************** |
| */ |
| #ifdef GCC |
| #ifdef __STDC__ |
| #include <stdarg.h> |
| #else |
| #include <varargs.h> |
| #endif |
| #define _SYS_VARARGS_H |
| #endif |
| |
| #include "e1000g_debug.h" |
| #include "e1000g_sw.h" |
| #ifdef E1000G_DEBUG |
| #include <sys/pcie.h> |
| #endif |
| |
| #ifdef E1000G_DEBUG |
| #define WPL 8 /* 8 16-bit words per line */ |
| #define NUM_REGS 155 /* must match the array initializer */ |
| typedef struct { |
| char name[10]; |
| uint32_t offset; |
| } Regi_t; |
| |
| int e1000g_debug = E1000G_WARN_LEVEL; |
| #endif /* E1000G_DEBUG */ |
| int e1000g_log_mode = E1000G_LOG_PRINT; |
| |
| void |
| e1000g_log(void *instance, int level, char *fmt, ...) |
| { |
| struct e1000g *Adapter = (struct e1000g *)instance; |
| auto char name[NAMELEN]; |
| auto char buf[BUFSZ]; |
| va_list ap; |
| |
| switch (level) { |
| #ifdef E1000G_DEBUG |
| case E1000G_VERBOSE_LEVEL: /* 16 or 0x010 */ |
| if (e1000g_debug < E1000G_VERBOSE_LEVEL) |
| return; |
| level = CE_CONT; |
| break; |
| |
| case E1000G_TRACE_LEVEL: /* 8 or 0x008 */ |
| if (e1000g_debug < E1000G_TRACE_LEVEL) |
| return; |
| level = CE_CONT; |
| break; |
| |
| case E1000G_INFO_LEVEL: /* 4 or 0x004 */ |
| if (e1000g_debug < E1000G_INFO_LEVEL) |
| return; |
| level = CE_CONT; |
| break; |
| |
| case E1000G_WARN_LEVEL: /* 2 or 0x002 */ |
| if (e1000g_debug < E1000G_WARN_LEVEL) |
| return; |
| level = CE_CONT; |
| break; |
| |
| case E1000G_ERRS_LEVEL: /* 1 or 0x001 */ |
| level = CE_CONT; |
| break; |
| #else |
| case CE_CONT: |
| case CE_NOTE: |
| case CE_WARN: |
| case CE_PANIC: |
| break; |
| #endif |
| default: |
| level = CE_CONT; |
| break; |
| } |
| |
| if (Adapter != NULL) { |
| (void) sprintf(name, "%s - e1000g[%d] ", |
| ddi_get_name(Adapter->dip), ddi_get_instance(Adapter->dip)); |
| } else { |
| (void) sprintf(name, "e1000g"); |
| } |
| /* |
| * va_start uses built in macro __builtin_va_alist from the |
| * compiler libs which requires compiler system to have |
| * __BUILTIN_VA_ARG_INCR defined. |
| */ |
| /* |
| * Many compilation systems depend upon the use of special functions |
| * built into the the compilation system to handle variable argument |
| * lists and stack allocations. The method to obtain this in SunOS |
| * is to define the feature test macro "__BUILTIN_VA_ARG_INCR" which |
| * enables the following special built-in functions: |
| * __builtin_alloca |
| * __builtin_va_alist |
| * __builtin_va_arg_incr |
| * It is intended that the compilation system define this feature test |
| * macro, not the user of the system. |
| * |
| * The tests on the processor type are to provide a transitional period |
| * for existing compilation systems, and may be removed in a future |
| * release. |
| */ |
| /* |
| * Using GNU gcc compiler it doesn't expand to va_start.... |
| */ |
| va_start(ap, fmt); |
| (void) vsprintf(buf, fmt, ap); |
| va_end(ap); |
| |
| if ((e1000g_log_mode & E1000G_LOG_ALL) == E1000G_LOG_ALL) |
| cmn_err(level, "%s: %s", name, buf); |
| else if (e1000g_log_mode & E1000G_LOG_DISPLAY) |
| cmn_err(level, "^%s: %s", name, buf); |
| else if (e1000g_log_mode & E1000G_LOG_PRINT) |
| cmn_err(level, "!%s: %s", name, buf); |
| else /* if they are not set properly then do both */ |
| cmn_err(level, "%s: %s", name, buf); |
| } |
| |
| |
| |
| #ifdef E1000G_DEBUG |
| extern kmutex_t e1000g_nvm_lock; |
| |
| void |
| eeprom_dump(void *instance) |
| { |
| struct e1000g *Adapter = (struct e1000g *)instance; |
| struct e1000_hw *hw = &Adapter->shared; |
| uint16_t eeprom[WPL], size_field; |
| int i, ret, sign, size, lines, offset = 0; |
| int ee_size[] = |
| {128, 256, 512, 1024, 2048, 4096, 16 * 1024, 32 * 1024, 64 * 1024}; |
| |
| mutex_enter(&e1000g_nvm_lock); |
| |
| if (ret = e1000_read_nvm(hw, 0x12, 1, &size_field)) { |
| e1000g_log(Adapter, CE_WARN, |
| "e1000_read_nvm failed to read size: %d", ret); |
| goto eeprom_dump_end; |
| } |
| |
| sign = (size_field & 0xc000) >> 14; |
| if (sign != 1) { |
| e1000g_log(Adapter, CE_WARN, |
| "eeprom_dump invalid signature: %d", sign); |
| } |
| |
| size = (size_field & 0x3c00) >> 10; |
| if (size < 0 || size > 11) { |
| e1000g_log(Adapter, CE_WARN, |
| "eeprom_dump invalid size: %d", size); |
| } |
| |
| e1000g_log(Adapter, CE_CONT, |
| "eeprom_dump size field: %d eeprom bytes: %d\n", |
| size, ee_size[size]); |
| |
| e1000g_log(Adapter, CE_CONT, |
| "e1000_read_nvm hebs: %d\n", ((size_field & 0x000f) >> 10)); |
| |
| lines = ee_size[size] / WPL / 2; |
| e1000g_log(Adapter, CE_CONT, |
| "dump eeprom %d lines of %d words per line\n", lines, WPL); |
| |
| for (i = 0; i < lines; i++) { |
| if (ret = e1000_read_nvm(hw, offset, WPL, eeprom)) { |
| e1000g_log(Adapter, CE_WARN, |
| "e1000_read_nvm failed: %d", ret); |
| goto eeprom_dump_end; |
| } |
| |
| e1000g_log(Adapter, CE_CONT, |
| "0x%04x %04x %04x %04x %04x %04x %04x %04x %04x\n", |
| offset, |
| eeprom[0], eeprom[1], eeprom[2], eeprom[3], |
| eeprom[4], eeprom[5], eeprom[6], eeprom[7]); |
| offset += WPL; |
| } |
| |
| eeprom_dump_end: |
| mutex_exit(&e1000g_nvm_lock); |
| } |
| |
| /* |
| * phy_dump - dump important phy registers |
| */ |
| void |
| phy_dump(void *instance) |
| { |
| struct e1000g *Adapter = (struct e1000g *)instance; |
| struct e1000_hw *hw = &Adapter->shared; |
| /* offset to each phy register */ |
| int32_t offset[] = |
| { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
| 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, |
| 30, 31, 0x1796, 0x187A, 0x1895, 0x1F30, 0x1F35, 0x1F3E, 0x1F54, |
| 0x1F55, 0x1F56, 0x1F72, 0x1F76, 0x1F77, 0x1F78, 0x1F79, 0x1F98, |
| 0x2010, 0x2011, 0x20DC, 0x20DD, 0x20DE, 0x28B4, 0x2F52, 0x2F5B, |
| 0x2F70, 0x2F90, 0x2FB1, 0x2FB2 }; |
| uint16_t value; /* register value */ |
| uint32_t stat; /* status from e1000_read_phy_reg */ |
| int i; |
| |
| e1000g_log(Adapter, CE_CONT, "Begin PHY dump\n"); |
| for (i = 0; i < ((sizeof (offset)) / sizeof (offset[0])); i++) { |
| |
| stat = e1000_read_phy_reg(hw, offset[i], &value); |
| if (stat == 0) { |
| e1000g_log(Adapter, CE_CONT, |
| "phyreg offset: %d value: 0x%x\n", |
| offset[i], value); |
| } else { |
| e1000g_log(Adapter, CE_WARN, |
| "phyreg offset: %d ERROR: 0x%x\n", |
| offset[i], stat); |
| } |
| } |
| } |
| |
| uint32_t |
| e1000_read_reg(struct e1000_hw *hw, uint32_t offset) |
| { |
| return (ddi_get32(((struct e1000g_osdep *)(hw)->back)->reg_handle, |
| (uint32_t *)((uintptr_t)(hw)->hw_addr + offset))); |
| } |
| |
| |
| /* |
| * mac_dump - dump important mac registers |
| */ |
| void |
| mac_dump(void *instance) |
| { |
| struct e1000g *Adapter = (struct e1000g *)instance; |
| struct e1000_hw *hw = &Adapter->shared; |
| int i; |
| |
| /* {name, offset} for each mac register */ |
| Regi_t macreg[NUM_REGS] = { |
| {"CTRL", E1000_CTRL}, {"STATUS", E1000_STATUS}, |
| {"EECD", E1000_EECD}, {"EERD", E1000_EERD}, |
| {"CTRL_EXT", E1000_CTRL_EXT}, {"FLA", E1000_FLA}, |
| {"MDIC", E1000_MDIC}, {"SCTL", E1000_SCTL}, |
| {"FCAL", E1000_FCAL}, {"FCAH", E1000_FCAH}, |
| {"FCT", E1000_FCT}, {"VET", E1000_VET}, |
| {"ICR", E1000_ICR}, {"ITR", E1000_ITR}, |
| {"ICS", E1000_ICS}, {"IMS", E1000_IMS}, |
| {"IMC", E1000_IMC}, {"IAM", E1000_IAM}, |
| {"RCTL", E1000_RCTL}, {"FCTTV", E1000_FCTTV}, |
| {"TXCW", E1000_TXCW}, {"RXCW", E1000_RXCW}, |
| {"TCTL", E1000_TCTL}, {"TIPG", E1000_TIPG}, |
| {"AIT", E1000_AIT}, {"LEDCTL", E1000_LEDCTL}, |
| {"PBA", E1000_PBA}, {"PBS", E1000_PBS}, |
| {"EEMNGCTL", E1000_EEMNGCTL}, {"ERT", E1000_ERT}, |
| {"FCRTL", E1000_FCRTL}, {"FCRTH", E1000_FCRTH}, |
| {"PSRCTL", E1000_PSRCTL}, {"RDBAL(0)", E1000_RDBAL(0)}, |
| {"RDBAH(0)", E1000_RDBAH(0)}, {"RDLEN(0)", E1000_RDLEN(0)}, |
| {"RDH(0)", E1000_RDH(0)}, {"RDT(0)", E1000_RDT(0)}, |
| {"RDTR", E1000_RDTR}, {"RXDCTL(0)", E1000_RXDCTL(0)}, |
| {"RADV", E1000_RADV}, {"RDBAL(1)", E1000_RDBAL(1)}, |
| {"RDBAH(1)", E1000_RDBAH(1)}, {"RDLEN(1)", E1000_RDLEN(1)}, |
| {"RDH(1)", E1000_RDH(1)}, {"RDT(1)", E1000_RDT(1)}, |
| {"RXDCTL(1)", E1000_RXDCTL(1)}, {"RSRPD", E1000_RSRPD}, |
| {"RAID", E1000_RAID}, {"CPUVEC", E1000_CPUVEC}, |
| {"TDFH", E1000_TDFH}, {"TDFT", E1000_TDFT}, |
| {"TDFHS", E1000_TDFHS}, {"TDFTS", E1000_TDFTS}, |
| {"TDFPC", E1000_TDFPC}, {"TDBAL(0)", E1000_TDBAL(0)}, |
| {"TDBAH(0)", E1000_TDBAH(0)}, {"TDLEN(0)", E1000_TDLEN(0)}, |
| {"TDH(0)", E1000_TDH(0)}, {"TDT(0)", E1000_TDT(0)}, |
| {"TIDV", E1000_TIDV}, {"TXDCTL(0)", E1000_TXDCTL(0)}, |
| {"TADV", E1000_TADV}, {"TARC(0)", E1000_TARC(0)}, |
| {"TDBAL(1)", E1000_TDBAL(1)}, {"TDBAH(1)", E1000_TDBAH(1)}, |
| {"TDLEN(1)", E1000_TDLEN(1)}, {"TDH(1)", E1000_TDH(1)}, |
| {"TDT(1)", E1000_TDT(1)}, {"TXDCTL(1)", E1000_TXDCTL(1)}, |
| {"TARC(1)", E1000_TARC(1)}, {"ALGNERRC", E1000_ALGNERRC}, |
| {"RXERRC", E1000_RXERRC}, {"MPC", E1000_MPC}, |
| {"SCC", E1000_SCC}, {"ECOL", E1000_ECOL}, |
| {"MCC", E1000_MCC}, {"LATECOL", E1000_LATECOL}, |
| {"COLC", E1000_COLC}, {"DC", E1000_DC}, |
| {"TNCRS", E1000_TNCRS}, {"SEC", E1000_SEC}, |
| {"CEXTERR", E1000_CEXTERR}, {"RLEC", E1000_RLEC}, |
| {"XONRXC", E1000_XONRXC}, {"XONTXC", E1000_XONTXC}, |
| {"XOFFRXC", E1000_XOFFRXC}, {"XOFFTXC", E1000_XOFFTXC}, |
| {"FCRUC", E1000_FCRUC}, {"PRC64", E1000_PRC64}, |
| {"PRC127", E1000_PRC127}, {"PRC255", E1000_PRC255}, |
| {"PRC511", E1000_PRC511}, {"PRC1023", E1000_PRC1023}, |
| {"PRC1522", E1000_PRC1522}, {"GPRC", E1000_GPRC}, |
| {"BPRC", E1000_BPRC}, {"MPRC", E1000_MPRC}, |
| {"GPTC", E1000_GPTC}, {"GORCL", E1000_GORCL}, |
| {"GORCH", E1000_GORCH}, {"GOTCL", E1000_GOTCL}, |
| {"GOTCH", E1000_GOTCH}, {"RNBC", E1000_RNBC}, |
| {"RUC", E1000_RUC}, {"RFC", E1000_RFC}, |
| {"ROC", E1000_ROC}, {"RJC", E1000_RJC}, |
| {"MGTPRC", E1000_MGTPRC}, {"MGTPDC", E1000_MGTPDC}, |
| {"MGTPTC", E1000_MGTPTC}, {"TORL", E1000_TORL}, |
| {"TORH", E1000_TORH}, {"TOTL", E1000_TOTL}, |
| {"TOTH", E1000_TOTH}, {"TPR", E1000_TPR}, |
| {"TPT", E1000_TPT}, {"PTC64", E1000_PTC64}, |
| {"PTC127", E1000_PTC127}, {"PTC255", E1000_PTC255}, |
| {"PTC511", E1000_PTC511}, {"PTC1023", E1000_PTC1023}, |
| {"PTC1522", E1000_PTC1522}, {"MPTC", E1000_MPTC}, |
| {"BPTC", E1000_BPTC}, {"TSCTC", E1000_TSCTC}, |
| {"TSCTFC", E1000_TSCTFC}, {"IAC", E1000_IAC}, |
| {"ICRXPTC", E1000_ICRXPTC}, {"ICRXATC", E1000_ICRXATC}, |
| {"ICTXPTC", E1000_ICTXPTC}, {"ICTXATC", E1000_ICTXATC}, |
| {"ICTXQEC", E1000_ICTXQEC}, {"ICTXQMTC", E1000_ICTXQMTC}, |
| {"ICRXDMTC", E1000_ICRXDMTC}, {"ICRXOC", E1000_ICRXOC}, |
| {"RXCSUM", E1000_RXCSUM}, {"RFCTL", E1000_RFCTL}, |
| {"WUC", E1000_WUC}, {"WUFC", E1000_WUFC}, |
| {"WUS", E1000_WUS}, {"MRQC", E1000_MRQC}, |
| {"MANC", E1000_MANC}, {"IPAV", E1000_IPAV}, |
| {"MANC2H", E1000_MANC2H}, {"RSSIM", E1000_RSSIM}, |
| {"RSSIR", E1000_RSSIR}, {"WUPL", E1000_WUPL}, |
| {"GCR", E1000_GCR}, {"GSCL_1", E1000_GSCL_1}, |
| {"GSCL_2", E1000_GSCL_2}, {"GSCL_3", E1000_GSCL_3}, |
| {"GSCL_4", E1000_GSCL_4}, {"FACTPS", E1000_FACTPS}, |
| {"FWSM", E1000_FWSM}, |
| }; |
| |
| e1000g_log(Adapter, CE_CONT, "Begin MAC dump\n"); |
| |
| for (i = 0; i < NUM_REGS; i++) { |
| e1000g_log(Adapter, CE_CONT, |
| "macreg %10s offset: 0x%x value: 0x%x\n", |
| macreg[i].name, macreg[i].offset, |
| e1000_read_reg(hw, macreg[i].offset)); |
| } |
| } |
| |
| void |
| pciconfig_dump(void *instance) |
| { |
| struct e1000g *Adapter = (struct e1000g *)instance; |
| ddi_acc_handle_t handle; |
| uint8_t cap_ptr; |
| uint8_t next_ptr; |
| off_t offset; |
| |
| handle = Adapter->osdep.cfg_handle; |
| |
| e1000g_log(Adapter, CE_CONT, "Begin dump PCI config space\n"); |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_VENID:\t0x%x\n", |
| pci_config_get16(handle, PCI_CONF_VENID)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_DEVID:\t0x%x\n", |
| pci_config_get16(handle, PCI_CONF_DEVID)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_COMMAND:\t0x%x\n", |
| pci_config_get16(handle, PCI_CONF_COMM)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_STATUS:\t0x%x\n", |
| pci_config_get16(handle, PCI_CONF_STAT)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_REVID:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_REVID)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_PROG_CLASS:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_PROGCLASS)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_SUB_CLASS:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_SUBCLASS)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_BAS_CLASS:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_BASCLASS)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_CACHE_LINESZ:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_CACHE_LINESZ)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_LATENCY_TIMER:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_LATENCY_TIMER)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_HEADER_TYPE:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_HEADER)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_BIST:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_BIST)); |
| |
| pciconfig_bar(Adapter, PCI_CONF_BASE0, "PCI_CONF_BASE0"); |
| pciconfig_bar(Adapter, PCI_CONF_BASE1, "PCI_CONF_BASE1"); |
| pciconfig_bar(Adapter, PCI_CONF_BASE2, "PCI_CONF_BASE2"); |
| pciconfig_bar(Adapter, PCI_CONF_BASE3, "PCI_CONF_BASE3"); |
| pciconfig_bar(Adapter, PCI_CONF_BASE4, "PCI_CONF_BASE4"); |
| pciconfig_bar(Adapter, PCI_CONF_BASE5, "PCI_CONF_BASE5"); |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_CIS:\t0x%x\n", |
| pci_config_get32(handle, PCI_CONF_CIS)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_SUBVENID:\t0x%x\n", |
| pci_config_get16(handle, PCI_CONF_SUBVENID)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_SUBSYSID:\t0x%x\n", |
| pci_config_get16(handle, PCI_CONF_SUBSYSID)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_ROM:\t0x%x\n", |
| pci_config_get32(handle, PCI_CONF_ROM)); |
| |
| cap_ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR); |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_CAP_PTR:\t0x%x\n", cap_ptr); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_ILINE:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_ILINE)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_IPIN:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_IPIN)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_MIN_G:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_MIN_G)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_CONF_MAX_L:\t0x%x\n", |
| pci_config_get8(handle, PCI_CONF_MAX_L)); |
| |
| /* Power Management */ |
| offset = cap_ptr; |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_PM_CAP_ID:\t0x%x\n", |
| pci_config_get8(handle, offset)); |
| |
| next_ptr = pci_config_get8(handle, offset + 1); |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_PM_NEXT_PTR:\t0x%x\n", next_ptr); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_PM_CAP:\t0x%x\n", |
| pci_config_get16(handle, offset + PCI_PMCAP)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_PM_CSR:\t0x%x\n", |
| pci_config_get16(handle, offset + PCI_PMCSR)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_PM_CSR_BSE:\t0x%x\n", |
| pci_config_get8(handle, offset + PCI_PMCSR_BSE)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_PM_DATA:\t0x%x\n", |
| pci_config_get8(handle, offset + PCI_PMDATA)); |
| |
| /* MSI Configuration */ |
| offset = next_ptr; |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_MSI_CAP_ID:\t0x%x\n", |
| pci_config_get8(handle, offset)); |
| |
| next_ptr = pci_config_get8(handle, offset + 1); |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_MSI_NEXT_PTR:\t0x%x\n", next_ptr); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_MSI_CTRL:\t0x%x\n", |
| pci_config_get16(handle, offset + PCI_MSI_CTRL)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_MSI_ADDR:\t0x%x\n", |
| pci_config_get32(handle, offset + PCI_MSI_ADDR_OFFSET)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_MSI_ADDR_HI:\t0x%x\n", |
| pci_config_get32(handle, offset + 0x8)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCI_MSI_DATA:\t0x%x\n", |
| pci_config_get16(handle, offset + 0xC)); |
| |
| /* PCI Express Configuration */ |
| offset = next_ptr; |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_CAP_ID:\t0x%x\n", |
| pci_config_get8(handle, offset + PCIE_CAP_ID)); |
| |
| next_ptr = pci_config_get8(handle, offset + PCIE_CAP_NEXT_PTR); |
| |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_CAP_NEXT_PTR:\t0x%x\n", next_ptr); |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_PCIECAP:\t0x%x\n", |
| pci_config_get16(handle, offset + PCIE_PCIECAP)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_DEVCAP:\t0x%x\n", |
| pci_config_get32(handle, offset + PCIE_DEVCAP)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_DEVCTL:\t0x%x\n", |
| pci_config_get16(handle, offset + PCIE_DEVCTL)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_DEVSTS:\t0x%x\n", |
| pci_config_get16(handle, offset + PCIE_DEVSTS)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_LINKCAP:\t0x%x\n", |
| pci_config_get32(handle, offset + PCIE_LINKCAP)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_LINKCTL:\t0x%x\n", |
| pci_config_get16(handle, offset + PCIE_LINKCTL)); |
| e1000g_log(Adapter, CE_CONT, |
| "PCIE_LINKSTS:\t0x%x\n", |
| pci_config_get16(handle, offset + PCIE_LINKSTS)); |
| } |
| |
| void |
| pciconfig_bar(void *instance, uint32_t offset, char *name) |
| { |
| struct e1000g *Adapter = (struct e1000g *)instance; |
| ddi_acc_handle_t handle = Adapter->osdep.cfg_handle; |
| uint32_t base = pci_config_get32(handle, offset); |
| uint16_t comm = pci_config_get16(handle, PCI_CONF_COMM); |
| uint32_t size; /* derived size of the region */ |
| uint32_t bits_comm; /* command word bits to disable */ |
| uint32_t size_mask; /* mask for size extraction */ |
| char tag_type[32]; /* tag to show memory vs. i/o */ |
| char tag_mem[32]; /* tag to show memory characteristiccs */ |
| |
| /* base address zero, simple print */ |
| if (base == 0) { |
| e1000g_log(Adapter, CE_CONT, "%s:\t0x%x\n", name, base); |
| |
| /* base address non-zero, get size */ |
| } else { |
| /* i/o factors that decode from the base address */ |
| if (base & PCI_BASE_SPACE_IO) { |
| bits_comm = PCI_COMM_IO; |
| size_mask = PCI_BASE_IO_ADDR_M; |
| (void) strcpy(tag_type, "i/o port size:"); |
| (void) strcpy(tag_mem, ""); |
| /* memory factors that decode from the base address */ |
| } else { |
| bits_comm = PCI_COMM_MAE; |
| size_mask = PCI_BASE_M_ADDR_M; |
| (void) strcpy(tag_type, "memory size:"); |
| if (base & PCI_BASE_TYPE_ALL) |
| (void) strcpy(tag_mem, "64bit "); |
| else |
| (void) strcpy(tag_mem, "32bit "); |
| if (base & PCI_BASE_PREF_M) |
| (void) strcat(tag_mem, "prefetchable"); |
| else |
| (void) strcat(tag_mem, "non-prefetchable"); |
| } |
| |
| /* disable memory decode */ |
| pci_config_put16(handle, PCI_CONF_COMM, (comm & ~bits_comm)); |
| |
| /* write to base register */ |
| pci_config_put32(handle, offset, 0xffffffff); |
| |
| /* read back & compute size */ |
| size = pci_config_get32(handle, offset); |
| size &= size_mask; |
| size = (~size) + 1; |
| |
| /* restore base register */ |
| pci_config_put32(handle, offset, base); |
| |
| /* re-enable memory decode */ |
| pci_config_put16(handle, PCI_CONF_COMM, comm); |
| |
| /* print results */ |
| e1000g_log(Adapter, CE_CONT, "%s:\t0x%x %s 0x%x %s\n", |
| name, base, tag_type, size, tag_mem); |
| } |
| } |
| #endif /* E1000G_DEBUG */ |