13db86aabSstevel /* 23db86aabSstevel * CDDL HEADER START 33db86aabSstevel * 43db86aabSstevel * The contents of this file are subject to the terms of the 53db86aabSstevel * Common Development and Distribution License (the "License"). 63db86aabSstevel * You may not use this file except in compliance with the License. 73db86aabSstevel * 83db86aabSstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93db86aabSstevel * or http://www.opensolaris.org/os/licensing. 103db86aabSstevel * See the License for the specific language governing permissions 113db86aabSstevel * and limitations under the License. 123db86aabSstevel * 133db86aabSstevel * When distributing Covered Code, include this CDDL HEADER in each 143db86aabSstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153db86aabSstevel * If applicable, add the following below this CDDL HEADER, with the 163db86aabSstevel * fields enclosed by brackets "[]" replaced with your own identifying 173db86aabSstevel * information: Portions Copyright [yyyy] [name of copyright owner] 183db86aabSstevel * 193db86aabSstevel * CDDL HEADER END 203db86aabSstevel */ 213db86aabSstevel /* 22*11c2b4c0Srw148561 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233db86aabSstevel * Use is subject to license terms. 243db86aabSstevel */ 253db86aabSstevel /* 263db86aabSstevel * Copyright (c) * Copyright (c) 2001 Tadpole Technology plc 273db86aabSstevel * All rights reserved. 283db86aabSstevel * From "@(#)pcicfg.c 1.31 99/06/18 SMI" 293db86aabSstevel */ 303db86aabSstevel 313db86aabSstevel #pragma ident "%Z%%M% %I% %E% SMI" 323db86aabSstevel 333db86aabSstevel /* 343db86aabSstevel * Cardbus configurator 353db86aabSstevel */ 363db86aabSstevel 373db86aabSstevel #include <sys/ddi.h> 383db86aabSstevel #include <sys/sunndi.h> 393db86aabSstevel #include <sys/ndi_impldefs.h> 403db86aabSstevel 413db86aabSstevel #include <sys/pci.h> 423db86aabSstevel #include <sys/ebus.h> 433db86aabSstevel #include <sys/hotplug/hpctrl.h> 443db86aabSstevel #include <sys/hotplug/pci/pcicfg.h> 453db86aabSstevel 463db86aabSstevel #include <sys/pctypes.h> 473db86aabSstevel #include <sys/pcmcia.h> 488134ee03Srw148561 #include <sys/sservice.h> 493db86aabSstevel 503db86aabSstevel #include <sys/isa_defs.h> 513db86aabSstevel 523db86aabSstevel #include <sys/note.h> 533db86aabSstevel 543db86aabSstevel #include <sys/ethernet.h> 553db86aabSstevel 563db86aabSstevel #include "cardbus.h" 573db86aabSstevel #include "cardbus_parse.h" 583db86aabSstevel #include "cardbus_cfg.h" 593db86aabSstevel 603db86aabSstevel /* 613db86aabSstevel * ************************************************************************ 623db86aabSstevel * *** Implementation specific local data structures/definitions. *** 633db86aabSstevel * ************************************************************************ 643db86aabSstevel */ 653db86aabSstevel 663db86aabSstevel #define PCICFG_MAX_DEVICE 32 673db86aabSstevel #define PCICFG_MAX_FUNCTION 8 683db86aabSstevel 693db86aabSstevel static uint32_t pcicfg_max_device = PCICFG_MAX_DEVICE; 703db86aabSstevel static uint32_t pcicfg_max_function = PCICFG_MAX_FUNCTION; 713db86aabSstevel 723db86aabSstevel #define PCICFG_NODEVICE 42 733db86aabSstevel #define PCICFG_NOMEMORY 43 743db86aabSstevel #define PCICFG_NOMULTI 44 753db86aabSstevel 763db86aabSstevel #define PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32)) 773db86aabSstevel #define PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF)) 783db86aabSstevel #define PCICFG_LADDR(lo, hi) (((uint64_t)(hi) << 32) | (uint32_t)(lo)) 793db86aabSstevel 803db86aabSstevel #define PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16)) 813db86aabSstevel #define PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF)) 823db86aabSstevel #define PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8)) 833db86aabSstevel #define PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF)) 843db86aabSstevel 853db86aabSstevel #define PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1)))) 863db86aabSstevel #define PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1))) 873db86aabSstevel 883db86aabSstevel #define PCICFG_MEMGRAN 0x100000 893db86aabSstevel #define PCICFG_IOGRAN 0x1000 903db86aabSstevel #define PCICFG_4GIG_LIMIT 0xFFFFFFFFUL 913db86aabSstevel #define CBCFG_MEMGRAN 0x1000 923db86aabSstevel #define CBCFG_IOGRAN 0x4 933db86aabSstevel 943db86aabSstevel #define PCICFG_MEM_MULT 4 953db86aabSstevel #define PCICFG_IO_MULT 4 963db86aabSstevel #define PCICFG_RANGE_LEN 2 /* Number of range entries */ 973db86aabSstevel 983db86aabSstevel /* 993db86aabSstevel * ISA node declaration structure. 1003db86aabSstevel */ 1013db86aabSstevel struct isa_node { 1023db86aabSstevel char *name; 1033db86aabSstevel char *compatible[5]; 1043db86aabSstevel char *type; 1053db86aabSstevel char *model; 1063db86aabSstevel uint16_t reg; 1073db86aabSstevel uint16_t span; 1083db86aabSstevel }; 1093db86aabSstevel 1103db86aabSstevel struct cardbus_name_entry { 1113db86aabSstevel uint32_t class_code; 1123db86aabSstevel char *name; 1133db86aabSstevel int pil; 1143db86aabSstevel }; 1153db86aabSstevel 1163db86aabSstevel struct cardbus_find_ctrl { 1173db86aabSstevel uint_t bus; 1183db86aabSstevel uint_t device; 1193db86aabSstevel uint_t function; 1203db86aabSstevel dev_info_t *dip; 1213db86aabSstevel }; 1223db86aabSstevel 1233db86aabSstevel #define PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\ 1243db86aabSstevel (\ 1253db86aabSstevel ((ulong_t)(busnum & 0xff) << 16) |\ 1263db86aabSstevel ((ulong_t)(devnum & 0x1f) << 11) |\ 1273db86aabSstevel ((ulong_t)(funcnum & 0x7) << 8) |\ 1283db86aabSstevel ((ulong_t)(register & 0x3f))) 1293db86aabSstevel 1303db86aabSstevel typedef struct cardbus_phdl cardbus_phdl_t; 1313db86aabSstevel 1323db86aabSstevel struct cardbus_phdl { 1333db86aabSstevel 1343db86aabSstevel dev_info_t *dip; /* Associated with the attach point */ 1358134ee03Srw148561 dev_info_t *res_dip; /* dip from which io/mem is allocated */ 1363db86aabSstevel cardbus_phdl_t *next; 1373db86aabSstevel 1383db86aabSstevel uint64_t memory_base; /* Memory base for this attach point */ 1393db86aabSstevel uint64_t memory_last; 1403db86aabSstevel uint64_t memory_len; 1413db86aabSstevel uint32_t memory_gran; 1423db86aabSstevel uint32_t io_base; /* I/O base for this attach point */ 1433db86aabSstevel uint32_t io_last; 1443db86aabSstevel uint32_t io_len; 1453db86aabSstevel uint32_t io_gran; 1463db86aabSstevel 1473db86aabSstevel int error; 1483db86aabSstevel uint_t highest_bus; /* Highest bus seen on the probe */ 1493db86aabSstevel ndi_ra_request_t mem_req; /* allocator request for memory */ 1503db86aabSstevel ndi_ra_request_t io_req; /* allocator request for I/O */ 1513db86aabSstevel }; 1523db86aabSstevel 1533db86aabSstevel typedef struct { 1543db86aabSstevel dev_info_t *dip; /* Associated with the attach point */ 1553db86aabSstevel ddi_acc_handle_t handle; /* open handle on parent PCI config space */ 1563db86aabSstevel uint32_t io_base; /* I/O base for this attach point */ 1573db86aabSstevel int io_decode_reg; 1583db86aabSstevel } isa_phdl_t; 1593db86aabSstevel 1603db86aabSstevel 1613db86aabSstevel /* 1623db86aabSstevel * forward declarations for routines defined in this module (called here) 1633db86aabSstevel */ 1643db86aabSstevel static cardbus_phdl_t *cardbus_find_phdl(dev_info_t *dip); 1653db86aabSstevel static cardbus_phdl_t *cardbus_create_phdl(dev_info_t *dip); 1663db86aabSstevel static int cardbus_destroy_phdl(dev_info_t *dip); 1673db86aabSstevel static int cardbus_program_ap(dev_info_t *); 1683db86aabSstevel static void cardbus_topbridge_assign(dev_info_t *, cardbus_phdl_t *); 1693db86aabSstevel static int cardbus_bridge_ranges(dev_info_t *, cardbus_phdl_t *, 1703db86aabSstevel ddi_acc_handle_t); 1713db86aabSstevel static int cardbus_bridge_assign(dev_info_t *, void *); 1723db86aabSstevel static int cardbus_isa_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry, 1733db86aabSstevel ddi_acc_handle_t handle); 1743db86aabSstevel static int cardbus_add_isa_reg(dev_info_t *, void *); 1753db86aabSstevel static int cardbus_allocate_chunk(dev_info_t *, uint8_t, uint8_t); 1763db86aabSstevel static int cardbus_free_chunk(dev_info_t *); 1773db86aabSstevel static void cardbus_setup_bridge(dev_info_t *, cardbus_phdl_t *, 1783db86aabSstevel ddi_acc_handle_t); 1793db86aabSstevel static void cardbus_update_bridge(dev_info_t *, cardbus_phdl_t *, 1803db86aabSstevel ddi_acc_handle_t); 1813db86aabSstevel static void cardbus_get_mem(dev_info_t *, cardbus_phdl_t *, uint32_t, 1823db86aabSstevel uint64_t *); 1833db86aabSstevel static void cardbus_get_io(dev_info_t *, cardbus_phdl_t *, uint32_t, 1843db86aabSstevel uint32_t *); 1853db86aabSstevel static int cardbus_sum_resources(dev_info_t *, void *); 1863db86aabSstevel static int cardbus_free_bridge_resources(dev_info_t *); 1873db86aabSstevel static int cardbus_free_device_resources(dev_info_t *); 1883db86aabSstevel static int cardbus_free_resources(dev_info_t *); 1893db86aabSstevel static int cardbus_probe_bridge(cbus_t *, dev_info_t *, uint_t, 1903db86aabSstevel uint_t, uint_t); 1913db86aabSstevel static int cardbus_probe_children(cbus_t *, dev_info_t *, uint_t, uint_t, 1923db86aabSstevel uint_t, uint8_t *); 1933db86aabSstevel static int cardbus_add_config_reg(dev_info_t *, uint_t, uint_t, uint_t); 1943db86aabSstevel static int cardbus_add_isa_node(cbus_t *, dev_info_t *, struct isa_node *); 1953db86aabSstevel static int cardbus_config_setup(dev_info_t *, ddi_acc_handle_t *); 1963db86aabSstevel static void cardbus_config_teardown(ddi_acc_handle_t *); 1973db86aabSstevel static void cardbus_reparent_children(dev_info_t *, dev_info_t *); 1983db86aabSstevel static int cardbus_update_assigned_prop(dev_info_t *, pci_regspec_t *); 1993db86aabSstevel static int cardbus_update_available_prop(dev_info_t *, uint32_t, 2003db86aabSstevel uint64_t, uint64_t); 2013db86aabSstevel static int cardbus_update_ranges_prop(dev_info_t *, cardbus_range_t *); 2023db86aabSstevel static int cardbus_update_reg_prop(dev_info_t *dip, uint32_t regvalue, 2033db86aabSstevel uint_t reg_offset); 2043db86aabSstevel static int cardbus_set_standard_props(dev_info_t *parent, dev_info_t *dip, 2053db86aabSstevel ddi_acc_handle_t config_handle); 2063db86aabSstevel static int cardbus_set_isa_props(dev_info_t *parent, dev_info_t *dip, 2073db86aabSstevel char *name, char *compat[]); 2083db86aabSstevel static int cardbus_set_busnode_props(dev_info_t *); 2093db86aabSstevel static int cardbus_set_busnode_isaprops(dev_info_t *); 2103db86aabSstevel static int cardbus_set_childnode_props(dev_info_t *dip, 2113db86aabSstevel ddi_acc_handle_t config_handle); 2123db86aabSstevel static void cardbus_set_bus_numbers(ddi_acc_handle_t config_handle, 2133db86aabSstevel uint_t primary, uint_t secondary); 2143db86aabSstevel static void enable_pci_isa_bridge(dev_info_t *dip, 2153db86aabSstevel ddi_acc_handle_t config_handle); 2163db86aabSstevel static void enable_pci_pci_bridge(dev_info_t *dip, 2173db86aabSstevel ddi_acc_handle_t config_handle); 2183db86aabSstevel static void enable_cardbus_bridge(dev_info_t *dip, 2193db86aabSstevel ddi_acc_handle_t config_handle); 2203db86aabSstevel static void disable_pci_pci_bridge(dev_info_t *dip, 2213db86aabSstevel ddi_acc_handle_t config_handle); 2223db86aabSstevel static void disable_cardbus_bridge(dev_info_t *dip, 2233db86aabSstevel ddi_acc_handle_t config_handle); 2243db86aabSstevel static void enable_cardbus_device(dev_info_t *, ddi_acc_handle_t); 2253db86aabSstevel static void disable_cardbus_device(ddi_acc_handle_t config_handle); 2263db86aabSstevel static void cardbus_force_boolprop(dev_info_t *dip, char *pname); 2273db86aabSstevel static void cardbus_force_intprop(dev_info_t *dip, char *pname, 2283db86aabSstevel int *pval, int len); 2293db86aabSstevel static void cardbus_force_stringprop(dev_info_t *dip, char *pname, 2303db86aabSstevel char *pval); 2313db86aabSstevel static void split_addr(char *, int *, int *); 2323db86aabSstevel #ifdef DEBUG 2333db86aabSstevel static void cardbus_dump_common_config(ddi_acc_handle_t config_handle); 2343db86aabSstevel static void cardbus_dump_device_config(ddi_acc_handle_t config_handle); 2353db86aabSstevel static void cardbus_dump_bridge_config(ddi_acc_handle_t config_handle, 2363db86aabSstevel uint8_t header_type); 2373db86aabSstevel static void cardbus_dump_config(ddi_acc_handle_t config_handle); 2383db86aabSstevel static void cardbus_dump_reg(dev_info_t *dip, const pci_regspec_t *regspec, 2393db86aabSstevel int nelems); 2403db86aabSstevel #endif 2413db86aabSstevel 2423db86aabSstevel static cardbus_phdl_t *cardbus_phdl_list = NULL; 2433db86aabSstevel 2443db86aabSstevel static struct cardbus_name_entry cardbus_class_lookup [] = { 2453db86aabSstevel { 0x001, "display", 9 }, 2463db86aabSstevel { 0x100, "scsi", 4 }, 2473db86aabSstevel { 0x101, "ide", 4 }, 2483db86aabSstevel { 0x102, "fdc", 4 }, 2493db86aabSstevel { 0x103, "ipi", 4 }, 2503db86aabSstevel { 0x104, "raid", 4 }, 2513db86aabSstevel { 0x200, "ethernet", 6 }, 2523db86aabSstevel { 0x201, "token-ring", 6 }, 2533db86aabSstevel { 0x202, "fddi", 6 }, 2543db86aabSstevel { 0x203, "atm", 6 }, 2553db86aabSstevel { 0x300, "display", 9 }, /* VGA card */ 2563db86aabSstevel { 0x380, "display", 9 }, /* other - for the Raptor Card */ 2573db86aabSstevel { 0x400, "video", 11 }, 2583db86aabSstevel { 0x401, "sound", 11 }, 2593db86aabSstevel { 0x500, "memory", 11 }, 2603db86aabSstevel { 0x501, "flash", 11 }, 2613db86aabSstevel { 0x600, "host", 11 }, 2623db86aabSstevel { 0x601, "isa", 11 }, 2633db86aabSstevel { 0x602, "eisa", 11 }, 2643db86aabSstevel { 0x603, "mca", 11 }, 2653db86aabSstevel { 0x604, "pci", 11 }, 2663db86aabSstevel { 0x605, "pcmcia", 11 }, 2673db86aabSstevel { 0x606, "nubus", 11 }, 2683db86aabSstevel { 0x607, "cardbus", 11 }, 2693db86aabSstevel { 0x680, NULL, 8 }, 2703db86aabSstevel { 0x700, "serial", 11 }, 2713db86aabSstevel { 0x701, "parallel", 6 }, 2723db86aabSstevel { 0x800, "interrupt-controller", 3 }, 2733db86aabSstevel { 0x801, "dma-controller", 3 }, 2743db86aabSstevel { 0x802, "timer", 3 }, 2753db86aabSstevel { 0x803, "rtc", 3 }, 2763db86aabSstevel { 0x900, "keyboard", 8 }, 2773db86aabSstevel { 0x901, "pen", 8 }, 2783db86aabSstevel { 0x902, "mouse", 8 }, 2793db86aabSstevel { 0xa00, "dock", 1 }, 2803db86aabSstevel { 0xb00, "cpu", 1 }, 2813db86aabSstevel { 0xc00, "firewire", 9 }, 2823db86aabSstevel { 0xc01, "access-bus", 4 }, 2833db86aabSstevel { 0xc02, "ssa", 4 }, 2843db86aabSstevel { 0xc03, "usb", 9 }, 2853db86aabSstevel { 0xc04, "fibre-channel", 6 }, 2863db86aabSstevel { 0, 0 } 2873db86aabSstevel }; 2883db86aabSstevel 2893db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES 2903db86aabSstevel static char *cardbus_get_class_name(uint32_t classcode); 2913db86aabSstevel #endif /* _DONT_USE_1275_GENERIC_NAMES */ 2923db86aabSstevel 2933db86aabSstevel /* 2943db86aabSstevel * Reprogram ILINE with default value only if BIOS doesn't program it 2953db86aabSstevel */ 2963db86aabSstevel int 2973db86aabSstevel cardbus_validate_iline(dev_info_t *dip, ddi_acc_handle_t handle) 2983db86aabSstevel { 2993db86aabSstevel uint8_t intline = 0xff; 3003db86aabSstevel 3013db86aabSstevel if (pci_config_get8(handle, PCI_CONF_IPIN)) { 3023db86aabSstevel intline = pci_config_get8(handle, PCI_CONF_ILINE); 3033db86aabSstevel if ((intline == 0) || (intline == 0xff)) { 3043db86aabSstevel intline = ddi_getprop(DDI_DEV_T_ANY, dip, 3053db86aabSstevel DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS, 3063db86aabSstevel "interrupt-line", 0xff); 3073db86aabSstevel if (intline == (uint8_t)0xff) { 3083db86aabSstevel intline = ddi_getprop(DDI_DEV_T_ANY, 3093db86aabSstevel ddi_get_parent(dip), 3103db86aabSstevel DDI_PROP_CANSLEEP /* |DDI_PROP_DONTPASS */, 3113db86aabSstevel "interrupt-line", 0xb); 3123db86aabSstevel } 3133db86aabSstevel 3143db86aabSstevel pci_config_put8(handle, PCI_CONF_ILINE, intline); 3153db86aabSstevel } 3163db86aabSstevel (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, 3173db86aabSstevel "interrupt-line", intline); 3183db86aabSstevel } 3193db86aabSstevel return (intline); 3203db86aabSstevel } 3213db86aabSstevel 3223db86aabSstevel /* 3233db86aabSstevel * This entry point is called to configure a device (and 3243db86aabSstevel * all its children) on the given bus. It is called when 3253db86aabSstevel * a new device is added to the PCI domain. This routine 3263db86aabSstevel * will create the device tree and program the devices 3273db86aabSstevel * registers. 3283db86aabSstevel */ 3293db86aabSstevel int 3303db86aabSstevel cardbus_configure(cbus_t *cbp) 3313db86aabSstevel { 3323db86aabSstevel uint_t bus; 3333db86aabSstevel int cardbus_dev, func; 3343db86aabSstevel dev_info_t *attach_point; 3353db86aabSstevel 3363db86aabSstevel cardbus_err(cbp->cb_dip, 6, "cardbus_configure ()\n"); 3373db86aabSstevel 3383db86aabSstevel bus = cardbus_primary_busno(cbp->cb_dip); 3393db86aabSstevel 3403db86aabSstevel if (ndi_devi_alloc(cbp->cb_dip, DEVI_PSEUDO_NEXNAME, 3413db86aabSstevel (pnode_t)DEVI_SID_NODEID, 3423db86aabSstevel &attach_point) != NDI_SUCCESS) { 3433db86aabSstevel cardbus_err(cbp->cb_dip, 1, 3443db86aabSstevel "cardbus_configure(): Failed to alloc probe node\n"); 3453db86aabSstevel return (PCICFG_FAILURE); 3463db86aabSstevel } 3473db86aabSstevel 3483db86aabSstevel /* 3493db86aabSstevel * Node name marks this node as the "attachment point". 3503db86aabSstevel */ 3513db86aabSstevel if (ndi_devi_set_nodename(attach_point, 3523db86aabSstevel "hp_attachment", 0) != NDI_SUCCESS) { 3533db86aabSstevel cardbus_err(cbp->cb_dip, 1, 3543db86aabSstevel "Failed to set nodename for attachment node\n"); 3553db86aabSstevel (void) ndi_devi_free(attach_point); 3563db86aabSstevel return (PCICFG_FAILURE); 3573db86aabSstevel } 3583db86aabSstevel 3593db86aabSstevel cardbus_err(ddi_get_parent(attach_point), 8, 3603db86aabSstevel "Set bus type to cardbus\n"); 3613db86aabSstevel (void) ddi_prop_update_string(DDI_DEV_T_NONE, 3623db86aabSstevel ddi_get_parent(attach_point), PCM_DEVICETYPE, 3633db86aabSstevel "cardbus"); 3643db86aabSstevel 3653db86aabSstevel split_addr(ddi_get_name_addr(cbp->cb_dip), &cardbus_dev, &func); 3663db86aabSstevel 3673db86aabSstevel cardbus_err(attach_point, 8, 3683db86aabSstevel "Configuring [0x%x][0x%x][0x%x]\n", bus, cardbus_dev, func); 3693db86aabSstevel 3703db86aabSstevel switch (cardbus_probe_bridge(cbp, attach_point, 3713db86aabSstevel bus, cardbus_dev, func)) { 3723db86aabSstevel case PCICFG_FAILURE: 3733db86aabSstevel cardbus_err(cbp->cb_dip, 4, 3743db86aabSstevel "configure failed: bus [0x%x] slot [0x%x] func [0x%x]\n", 3753db86aabSstevel bus, cardbus_dev, func); 3763db86aabSstevel goto cleanup; 3773db86aabSstevel case PCICFG_NODEVICE: 3783db86aabSstevel cardbus_err(cbp->cb_dip, 4, 3793db86aabSstevel "no device: bus [0x%x] slot [0x%x] func [0x%x]\n", 3803db86aabSstevel bus, cardbus_dev, func); 3813db86aabSstevel goto cleanup; 3823db86aabSstevel default: 3833db86aabSstevel cardbus_err(cbp->cb_dip, 9, 3843db86aabSstevel "configure: bus => [%d] slot => [%d] func => [%d]\n", 3853db86aabSstevel bus, cardbus_dev, func); 3863db86aabSstevel break; 3873db86aabSstevel } 3883db86aabSstevel 3893db86aabSstevel if (cardbus_program_ap(cbp->cb_dip) == PCICFG_SUCCESS) { 3903db86aabSstevel (void) cardbus_reparent_children(attach_point, cbp->cb_dip); 3913db86aabSstevel (void) ndi_devi_free(attach_point); 3923db86aabSstevel cbp->cb_nex_ops->enable_intr(cbp->cb_dip); 3933db86aabSstevel return (PCICFG_SUCCESS); 3943db86aabSstevel } 3953db86aabSstevel 3963db86aabSstevel cardbus_err(cbp->cb_dip, 1, "Failed to program devices\n"); 3973db86aabSstevel 3983db86aabSstevel cleanup: 3993db86aabSstevel /* 4003db86aabSstevel * Clean up a partially created "probe state" tree. 4013db86aabSstevel * There are no resources allocated to the in the 4023db86aabSstevel * probe state. 4033db86aabSstevel */ 4043db86aabSstevel 4053db86aabSstevel cardbus_err(cbp->cb_dip, 6, 4063db86aabSstevel "Look up device [0x%x] function [0x%x] to clean up\n", 4073db86aabSstevel cardbus_dev, func); 4083db86aabSstevel 4093db86aabSstevel cardbus_err(cbp->cb_dip, 6, 4103db86aabSstevel "Cleaning up device [0x%x] function [0x%x]\n", 4113db86aabSstevel cardbus_dev, func); 4123db86aabSstevel 4133db86aabSstevel /* 4143db86aabSstevel * If this was a bridge device it will have a 4153db86aabSstevel * probe handle - if not, no harm in calling this. 4163db86aabSstevel */ 4173db86aabSstevel (void) cardbus_destroy_phdl(cbp->cb_dip); 4183db86aabSstevel 4193db86aabSstevel if (ddi_get_child(attach_point)) { 4203db86aabSstevel /* 4213db86aabSstevel * This will free up the node 4223db86aabSstevel */ 4233db86aabSstevel (void) ndi_devi_offline(ddi_get_child(attach_point), 4243db86aabSstevel NDI_UNCONFIG|NDI_DEVI_REMOVE); 4253db86aabSstevel } 4263db86aabSstevel (void) ndi_devi_free(attach_point); 4273db86aabSstevel 4283db86aabSstevel return (PCICFG_FAILURE); 4293db86aabSstevel } 4303db86aabSstevel 4313db86aabSstevel int 4323db86aabSstevel cardbus_unconfigure(cbus_t *cbp) 4333db86aabSstevel { 4343db86aabSstevel ddi_acc_handle_t config_handle; 4353db86aabSstevel dev_info_t *dip = cbp->cb_dip; 4363db86aabSstevel 4373db86aabSstevel cbp->cb_nex_ops->disable_intr(dip); 4383db86aabSstevel if (pci_config_setup(dip, &config_handle) == DDI_SUCCESS) { 4393db86aabSstevel disable_cardbus_bridge(dip, config_handle); 4403db86aabSstevel (void) pci_config_teardown(&config_handle); 4413db86aabSstevel } else { 4423db86aabSstevel cardbus_err(dip, 1, 4433db86aabSstevel "cardbus_unconfigure(): Failed to setup config space\n"); 4443db86aabSstevel } 4453db86aabSstevel 4463db86aabSstevel (void) cardbus_free_chunk(dip); 4473db86aabSstevel cardbus_err(dip, 6, 4483db86aabSstevel "cardbus_unconfigure: calling cardbus_free_bridge_resources\n"); 4493db86aabSstevel (void) cardbus_free_bridge_resources(dip); 4503db86aabSstevel 4513db86aabSstevel return (PCICFG_SUCCESS); 4523db86aabSstevel } 4533db86aabSstevel 4543db86aabSstevel int 4553db86aabSstevel cardbus_teardown_device(dev_info_t *dip) 4563db86aabSstevel { 4573db86aabSstevel /* 4583db86aabSstevel * Free up resources associated with 'dip' 4593db86aabSstevel */ 4603db86aabSstevel 4613db86aabSstevel if (cardbus_free_resources(dip) != PCICFG_SUCCESS) { 4623db86aabSstevel cardbus_err(dip, 1, 4633db86aabSstevel "cardbus_teardown_device: Failed to free resources\n"); 4643db86aabSstevel return (PCICFG_FAILURE); 4653db86aabSstevel } 4663db86aabSstevel 4673db86aabSstevel if (ndi_devi_offline(dip, NDI_DEVI_REMOVE) != NDI_SUCCESS) { 4683db86aabSstevel cardbus_err(dip, 1, 4693db86aabSstevel "cardbus_teardown_device: " 4703db86aabSstevel "Failed to offline and remove node\n"); 4713db86aabSstevel return (PCICFG_FAILURE); 4723db86aabSstevel } 4733db86aabSstevel 4743db86aabSstevel return (PCICFG_SUCCESS); 4753db86aabSstevel } 4763db86aabSstevel 4773db86aabSstevel /* 4783db86aabSstevel * Get the primary pci bus number. This should be the lowest number 4793db86aabSstevel * in the bus-range property of our parent. 4803db86aabSstevel */ 4813db86aabSstevel int 4823db86aabSstevel cardbus_primary_busno(dev_info_t *dip) 4833db86aabSstevel { 4843db86aabSstevel int len, rval; 4853db86aabSstevel char bus_type[16] = "(unknown)"; 4863db86aabSstevel dev_info_t *par = ddi_get_parent(dip); 4873db86aabSstevel cardbus_bus_range_t *bus_range; 4883db86aabSstevel 4893db86aabSstevel ASSERT(strcmp(ddi_driver_name(dip), "pcic") == 0); 4903db86aabSstevel len = sizeof (bus_type); 4913db86aabSstevel if ((ddi_prop_op(DDI_DEV_T_ANY, par, PROP_LEN_AND_VAL_BUF, 4923db86aabSstevel DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, 4933db86aabSstevel "device_type", 4943db86aabSstevel (caddr_t)&bus_type, &len) == DDI_SUCCESS)) { 4953db86aabSstevel ASSERT((strcmp(bus_type, "pci") == 0) || 4963db86aabSstevel (strcmp(bus_type, "cardbus") == 0)); 4973db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, par, 0, "bus-range", 4983db86aabSstevel (caddr_t)&bus_range, &len) == DDI_PROP_SUCCESS) { 4993db86aabSstevel cardbus_err(dip, 9, 5003db86aabSstevel "cardbus_primary_busno: bus range is %d to %d\n", 5013db86aabSstevel bus_range->lo, bus_range->hi); 5023db86aabSstevel rval = (int)bus_range->lo; 5033db86aabSstevel kmem_free((caddr_t)bus_range, len); 5043db86aabSstevel return (rval); 5053db86aabSstevel } 5063db86aabSstevel } 5073db86aabSstevel 5083db86aabSstevel cardbus_err(dip, 2, 5093db86aabSstevel "cardbus_primary_busno: Not a pci device or no bus-range\n"); 5103db86aabSstevel return (-1); 5113db86aabSstevel } 5123db86aabSstevel 5133db86aabSstevel static cardbus_phdl_t * 5143db86aabSstevel cardbus_find_phdl(dev_info_t *dip) 5153db86aabSstevel { 5163db86aabSstevel cardbus_phdl_t *entry; 5173db86aabSstevel 5183db86aabSstevel mutex_enter(&cardbus_list_mutex); 5193db86aabSstevel for (entry = cardbus_phdl_list; entry != NULL; entry = entry->next) { 5203db86aabSstevel if (entry->dip == dip) { 5213db86aabSstevel mutex_exit(&cardbus_list_mutex); 5223db86aabSstevel return (entry); 5233db86aabSstevel } 5243db86aabSstevel } 5253db86aabSstevel mutex_exit(&cardbus_list_mutex); 5263db86aabSstevel 5273db86aabSstevel /* 5283db86aabSstevel * Did'nt find entry - create one 5293db86aabSstevel */ 5303db86aabSstevel return (cardbus_create_phdl(dip)); 5313db86aabSstevel } 5323db86aabSstevel 5333db86aabSstevel static cardbus_phdl_t * 5343db86aabSstevel cardbus_create_phdl(dev_info_t *dip) 5353db86aabSstevel { 5363db86aabSstevel cardbus_phdl_t *new; 5373db86aabSstevel 5383db86aabSstevel new = (cardbus_phdl_t *)kmem_zalloc(sizeof (cardbus_phdl_t), KM_SLEEP); 5393db86aabSstevel 5403db86aabSstevel new->dip = dip; 5413db86aabSstevel new->io_gran = CBCFG_IOGRAN; 5423db86aabSstevel new->memory_gran = CBCFG_MEMGRAN; 5433db86aabSstevel mutex_enter(&cardbus_list_mutex); 5443db86aabSstevel new->next = cardbus_phdl_list; 5453db86aabSstevel cardbus_phdl_list = new; 5463db86aabSstevel mutex_exit(&cardbus_list_mutex); 5473db86aabSstevel 5483db86aabSstevel return (new); 5493db86aabSstevel } 5503db86aabSstevel 5513db86aabSstevel static int 5523db86aabSstevel cardbus_destroy_phdl(dev_info_t *dip) 5533db86aabSstevel { 5543db86aabSstevel cardbus_phdl_t *entry; 5553db86aabSstevel cardbus_phdl_t *follow = NULL; 5568134ee03Srw148561 ra_return_t res; 5573db86aabSstevel 5583db86aabSstevel mutex_enter(&cardbus_list_mutex); 5593db86aabSstevel for (entry = cardbus_phdl_list; entry != NULL; follow = entry, 5603db86aabSstevel entry = entry->next) { 5613db86aabSstevel if (entry->dip == dip) { 5623db86aabSstevel if (entry == cardbus_phdl_list) { 5633db86aabSstevel cardbus_phdl_list = entry->next; 5643db86aabSstevel } else { 5653db86aabSstevel follow->next = entry->next; 5663db86aabSstevel } 5673db86aabSstevel /* 5683db86aabSstevel * If this entry has any allocated memory 5693db86aabSstevel * or IO space associated with it, that 5703db86aabSstevel * must be freed up. 5713db86aabSstevel */ 5723db86aabSstevel if (entry->memory_len > 0) { 5738134ee03Srw148561 res.ra_addr_lo = entry->memory_base; 5748134ee03Srw148561 res.ra_len = entry->memory_len; 5758134ee03Srw148561 (void) pcmcia_free_mem(entry->res_dip, &res); 5763db86aabSstevel #ifdef _LP64 5773db86aabSstevel cardbus_err(dip, 8, 5783db86aabSstevel "cardbus_destroy_phdl: " 5793db86aabSstevel "MEMORY BASE = [0x%lx] length [0x%lx]\n", 5803db86aabSstevel entry->memory_base, entry->memory_len); 5813db86aabSstevel #else 5823db86aabSstevel cardbus_err(dip, 8, 5833db86aabSstevel "cardbus_destroy_phdl: " 5843db86aabSstevel "MEMORY BASE = [0x%llx] length [0x%llx]\n", 5853db86aabSstevel entry->memory_base, entry->memory_len); 5863db86aabSstevel #endif 5873db86aabSstevel } 5883db86aabSstevel if (entry->io_len > 0) { 5898134ee03Srw148561 res.ra_addr_lo = entry->io_base; 5908134ee03Srw148561 res.ra_len = entry->io_len; 5918134ee03Srw148561 (void) pcmcia_free_io(entry->res_dip, &res); 5923db86aabSstevel cardbus_err(dip, 8, 5933db86aabSstevel "cardbus_destroy_phdl: " 5943db86aabSstevel "IO BASE = [0x%x] length [0x%x]\n", 5953db86aabSstevel entry->io_base, entry->io_len); 5963db86aabSstevel } 5973db86aabSstevel /* 5983db86aabSstevel * Destroy this entry 5993db86aabSstevel */ 6003db86aabSstevel kmem_free((caddr_t)entry, sizeof (cardbus_phdl_t)); 6013db86aabSstevel mutex_exit(&cardbus_list_mutex); 6023db86aabSstevel return (PCICFG_SUCCESS); 6033db86aabSstevel } 6043db86aabSstevel } 6053db86aabSstevel 6063db86aabSstevel mutex_exit(&cardbus_list_mutex); 6073db86aabSstevel 6083db86aabSstevel /* 6093db86aabSstevel * Didn't find the entry 6103db86aabSstevel */ 6113db86aabSstevel return (PCICFG_FAILURE); 6123db86aabSstevel } 6133db86aabSstevel 6143db86aabSstevel static int 6153db86aabSstevel cardbus_program_ap(dev_info_t *dip) 6163db86aabSstevel { 6173db86aabSstevel cardbus_phdl_t *phdl; 6183db86aabSstevel uint8_t header_type, sec_bus; 6193db86aabSstevel ddi_acc_handle_t handle; 6203db86aabSstevel 6213db86aabSstevel if (pci_config_setup(dip, &handle) != DDI_SUCCESS) { 6223db86aabSstevel cardbus_err(dip, 1, 6233db86aabSstevel "cardbus_program_ap: Failed to map config space!\n"); 6243db86aabSstevel return (PCICFG_FAILURE); 6253db86aabSstevel } 6263db86aabSstevel 6273db86aabSstevel header_type = pci_config_get8(handle, PCI_CONF_HEADER); 6283db86aabSstevel sec_bus = pci_config_get8(handle, PCI_BCNF_SECBUS); 6293db86aabSstevel 6303db86aabSstevel cardbus_err(dip, 6, 6313db86aabSstevel "cardbus_program_ap (header_type=0x%x)\n", header_type); 6323db86aabSstevel (void) pci_config_teardown(&handle); 6333db86aabSstevel 6343db86aabSstevel /* 6353db86aabSstevel * Header type two is PCI to Cardbus bridge, see page 43 of the 6363db86aabSstevel * CL-PD6832 data sheet 6373db86aabSstevel */ 6383db86aabSstevel switch (header_type & PCI_HEADER_TYPE_M) { 6393db86aabSstevel case PCI_HEADER_CARDBUS: 6403db86aabSstevel cardbus_err(dip, 8, 6413db86aabSstevel "cardbus_program_ap calling cardbus_allocate_chunk\n"); 6423db86aabSstevel if (cardbus_allocate_chunk(dip, 6433db86aabSstevel header_type & PCI_HEADER_TYPE_M, 6443db86aabSstevel sec_bus) != PCICFG_SUCCESS) { 6453db86aabSstevel cardbus_err(dip, 1, 6463db86aabSstevel "cardbus_program_ap: " 6473db86aabSstevel "Not enough memory to hotplug\n"); 6483db86aabSstevel (void) cardbus_destroy_phdl(dip); 6493db86aabSstevel return (PCICFG_FAILURE); 6503db86aabSstevel } 6513db86aabSstevel 6523db86aabSstevel cardbus_err(dip, 8, 6533db86aabSstevel "cardbus_program_ap calling cardbus_find_phdl\n"); 6543db86aabSstevel phdl = cardbus_find_phdl(dip); 6553db86aabSstevel ASSERT(phdl); 6563db86aabSstevel 6573db86aabSstevel if (phdl == NULL) { 6583db86aabSstevel cardbus_err(dip, 1, "cardbus_find_phdl failed\n"); 6593db86aabSstevel return (PCICFG_FAILURE); 6603db86aabSstevel } 6613db86aabSstevel phdl->error = PCICFG_SUCCESS; 6623db86aabSstevel cardbus_err(dip, 8, 6633db86aabSstevel "cardbus_program_ap calling cardbus_topbridge_assign\n"); 6643db86aabSstevel cardbus_topbridge_assign(dip, phdl); 6653db86aabSstevel 6663db86aabSstevel if (phdl->error != PCICFG_SUCCESS) { 6673db86aabSstevel cardbus_err(dip, 1, "Problem assigning bridge\n"); 6683db86aabSstevel (void) cardbus_destroy_phdl(dip); 6693db86aabSstevel return (phdl->error); 6703db86aabSstevel } 6713db86aabSstevel break; 6723db86aabSstevel 6733db86aabSstevel default: 6743db86aabSstevel return (PCICFG_FAILURE); 6753db86aabSstevel } 6763db86aabSstevel 6773db86aabSstevel return (PCICFG_SUCCESS); 6783db86aabSstevel } 6793db86aabSstevel 6803db86aabSstevel static void 6813db86aabSstevel cardbus_topbridge_assign(dev_info_t *dip, cardbus_phdl_t *entry) 6823db86aabSstevel { 6833db86aabSstevel ddi_acc_handle_t handle; 6843db86aabSstevel uint8_t header_type; 6853db86aabSstevel 6863db86aabSstevel cardbus_err(dip, 6, "cardbus_topbridge_assign\n"); 6873db86aabSstevel 6883db86aabSstevel if (pci_config_setup(dip, &handle) != DDI_SUCCESS) { 6893db86aabSstevel cardbus_err(dip, 1, 6903db86aabSstevel "cardbus_topbridge_bridge_assign: " 6913db86aabSstevel "Failed to map config space!\n"); 6923db86aabSstevel return; 6933db86aabSstevel } 6943db86aabSstevel 6953db86aabSstevel header_type = pci_config_get8(handle, 6963db86aabSstevel PCI_CONF_HEADER) & PCI_HEADER_TYPE_M; 6973db86aabSstevel 6983db86aabSstevel /* cardbus bridge is the same as PCI-PCI bridge */ 6993db86aabSstevel ASSERT((header_type == PCI_HEADER_PPB) || 7003db86aabSstevel (header_type == PCI_HEADER_CARDBUS)); 7013db86aabSstevel 7023db86aabSstevel (void) cardbus_bridge_ranges(dip, entry, handle); 7033db86aabSstevel 7043db86aabSstevel (void) pci_config_teardown(&handle); 7053db86aabSstevel } 7063db86aabSstevel 7073db86aabSstevel static int 7083db86aabSstevel cardbus_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry, 7093db86aabSstevel ddi_acc_handle_t handle) 7103db86aabSstevel { 7113db86aabSstevel cardbus_range_t range[PCICFG_RANGE_LEN]; 7123db86aabSstevel int bus_range[2]; 7133db86aabSstevel int count; 7143db86aabSstevel int i; 7153db86aabSstevel 7163db86aabSstevel cardbus_err(dip, 8, "cardbus_bridge_ranges\n"); 7173db86aabSstevel 7183db86aabSstevel bzero((caddr_t)range, sizeof (cardbus_range_t) * PCICFG_RANGE_LEN); 7193db86aabSstevel 7203db86aabSstevel (void) cardbus_setup_bridge(dip, entry, handle); 7213db86aabSstevel 7223db86aabSstevel range[0].child_hi = range[0].parent_hi |= (PCI_REG_REL_M | PCI_ADDR_IO); 7233db86aabSstevel range[0].child_lo = range[0].parent_lo = entry->io_last; 7243db86aabSstevel range[1].child_hi = range[1].parent_hi |= (PCI_REG_REL_M | 7253db86aabSstevel PCI_ADDR_MEM32); 7263db86aabSstevel range[1].child_lo = range[1].parent_lo = entry->memory_last; 7273db86aabSstevel 7283db86aabSstevel ndi_devi_enter(dip, &count); 7293db86aabSstevel ddi_walk_devs(ddi_get_child(dip), cardbus_bridge_assign, (void *)entry); 7303db86aabSstevel ndi_devi_exit(dip, count); 7313db86aabSstevel 7323db86aabSstevel (void) cardbus_update_bridge(dip, entry, handle); 7333db86aabSstevel 7343db86aabSstevel bus_range[0] = pci_config_get8(handle, PCI_BCNF_SECBUS); 7353db86aabSstevel bus_range[1] = pci_config_get8(handle, PCI_BCNF_SUBBUS); 7363db86aabSstevel 7373db86aabSstevel cardbus_err(dip, 8, 7383db86aabSstevel "Set up bus-range property to %u->%u\n", 7393db86aabSstevel bus_range[0], bus_range[1]); 7403db86aabSstevel 7413db86aabSstevel if ((i = ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 7423db86aabSstevel "bus-range", 7433db86aabSstevel bus_range, 2)) != DDI_SUCCESS) { 7443db86aabSstevel 7453db86aabSstevel if (i == DDI_PROP_NOT_FOUND) { 7463db86aabSstevel cardbus_err(dip, 8, 7473db86aabSstevel "Create bus-range property, %u->%u\n", 7483db86aabSstevel bus_range[0], bus_range[1]); 7493db86aabSstevel i = ddi_prop_create(DDI_DEV_T_NONE, dip, 7503db86aabSstevel DDI_PROP_CANSLEEP, 7513db86aabSstevel "bus-range", (caddr_t)bus_range, 7523db86aabSstevel sizeof (bus_range)); 7533db86aabSstevel } 7543db86aabSstevel 7553db86aabSstevel if (i != DDI_PROP_SUCCESS) { 7563db86aabSstevel cardbus_err(dip, 1, 7573db86aabSstevel "Failed to set bus-range property, %u->%u (%d)\n", 7583db86aabSstevel bus_range[0], bus_range[1], i); 7593db86aabSstevel entry->error = PCICFG_FAILURE; 7603db86aabSstevel return (DDI_WALK_TERMINATE); 7613db86aabSstevel } 7623db86aabSstevel } 7633db86aabSstevel 7643db86aabSstevel if (entry->io_len > 0) { 7653db86aabSstevel range[0].size_lo = entry->io_last - entry->io_base; 7663db86aabSstevel if (cardbus_update_ranges_prop(dip, &range[0])) { 7673db86aabSstevel cardbus_err(dip, 1, "Failed to update ranges (i/o)\n"); 7683db86aabSstevel entry->error = PCICFG_FAILURE; 7693db86aabSstevel return (DDI_WALK_TERMINATE); 7703db86aabSstevel } 7713db86aabSstevel } 7723db86aabSstevel if (entry->memory_len > 0) { 7733db86aabSstevel range[1].size_lo = entry->memory_last - entry->memory_base; 7743db86aabSstevel if (cardbus_update_ranges_prop(dip, &range[1])) { 7753db86aabSstevel cardbus_err(dip, 1, 7763db86aabSstevel "Failed to update ranges (memory)\n"); 7773db86aabSstevel entry->error = PCICFG_FAILURE; 7783db86aabSstevel return (DDI_WALK_TERMINATE); 7793db86aabSstevel } 7803db86aabSstevel } 7813db86aabSstevel 7823db86aabSstevel return (DDI_WALK_PRUNECHILD); 7833db86aabSstevel } 7843db86aabSstevel static int 7853db86aabSstevel cardbus_bridge_assign(dev_info_t *dip, void *hdl) 7863db86aabSstevel { 7873db86aabSstevel ddi_acc_handle_t handle; 7883db86aabSstevel pci_regspec_t *reg; 7893db86aabSstevel int length; 7903db86aabSstevel int rcount; 7913db86aabSstevel int i; 7923db86aabSstevel int offset; 7933db86aabSstevel uint64_t mem_answer; 7943db86aabSstevel uint32_t io_answer, request; 7953db86aabSstevel uint8_t header_type, base_class; 7963db86aabSstevel cardbus_phdl_t *entry = (cardbus_phdl_t *)hdl; 7973db86aabSstevel 7983db86aabSstevel /* 7993db86aabSstevel * Ignore the attachment point and pcs. 8003db86aabSstevel */ 8013db86aabSstevel if (strcmp(ddi_binding_name(dip), "hp_attachment") == 0 || 8023db86aabSstevel strcmp(ddi_binding_name(dip), "pcs") == 0) { 8033db86aabSstevel cardbus_err(dip, 8, "cardbus_bridge_assign: Ignoring\n"); 8043db86aabSstevel return (DDI_WALK_CONTINUE); 8053db86aabSstevel } 8063db86aabSstevel 8073db86aabSstevel 8083db86aabSstevel cardbus_err(dip, 6, "cardbus_bridge_assign\n"); 8093db86aabSstevel 8103db86aabSstevel if (entry == NULL) { 8113db86aabSstevel cardbus_err(dip, 1, "Failed to get entry\n"); 8123db86aabSstevel return (DDI_WALK_TERMINATE); 8133db86aabSstevel } 8143db86aabSstevel if (cardbus_config_setup(dip, &handle) != DDI_SUCCESS) { 8153db86aabSstevel cardbus_err(dip, 1, 8163db86aabSstevel "cardbus_bridge_assign: Failed to map config space!\n"); 8173db86aabSstevel entry->error = PCICFG_FAILURE; 8183db86aabSstevel return (DDI_WALK_TERMINATE); 8193db86aabSstevel } 8203db86aabSstevel 8213db86aabSstevel header_type = pci_config_get8(handle, PCI_CONF_HEADER) & 8223db86aabSstevel PCI_HEADER_TYPE_M; 8233db86aabSstevel base_class = pci_config_get8(handle, PCI_CONF_BASCLASS); 8243db86aabSstevel 8253db86aabSstevel /* 8263db86aabSstevel * This function is not called for the top bridge and we are 8273db86aabSstevel * not enumerating down a further cardbus interface yet! 8283db86aabSstevel */ 8293db86aabSstevel if (base_class == PCI_CLASS_BRIDGE) { 8303db86aabSstevel uint8_t sub_class; 8313db86aabSstevel 8323db86aabSstevel sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS); 8333db86aabSstevel 8343db86aabSstevel switch (sub_class) { 8353db86aabSstevel case PCI_BRIDGE_PCI: 8363db86aabSstevel if (header_type == PCI_HEADER_PPB) { 8373db86aabSstevel i = cardbus_bridge_ranges(dip, entry, handle); 8383db86aabSstevel (void) cardbus_config_teardown(&handle); 8393db86aabSstevel return (i); 8403db86aabSstevel } 8413db86aabSstevel goto bad_device; 8423db86aabSstevel 8433db86aabSstevel case PCI_BRIDGE_ISA: 8443db86aabSstevel i = cardbus_isa_bridge_ranges(dip, entry, handle); 8453db86aabSstevel (void) cardbus_config_teardown(&handle); 8463db86aabSstevel return (i); 8473db86aabSstevel 8483db86aabSstevel case PCI_BRIDGE_CARDBUS: 8493db86aabSstevel /* 8503db86aabSstevel * Fall through, there should be at least one register 8513db86aabSstevel * set for this. 8523db86aabSstevel */ 8533db86aabSstevel break; 8543db86aabSstevel 8553db86aabSstevel case PCI_BRIDGE_OTHER: 8563db86aabSstevel default: 8573db86aabSstevel break; 8583db86aabSstevel } 8593db86aabSstevel } 8603db86aabSstevel 8613db86aabSstevel #ifdef sparc 8623db86aabSstevel /* 8633db86aabSstevel * If there is an interrupt pin set program 8643db86aabSstevel * interrupt line with default values. 8653db86aabSstevel */ 8663db86aabSstevel if (pci_config_get8(handle, PCI_CONF_IPIN)) { 8673db86aabSstevel pci_config_put8(handle, PCI_CONF_ILINE, 0xf); 8683db86aabSstevel } 8693db86aabSstevel #else 8703db86aabSstevel (void) cardbus_validate_iline(dip, handle); 8713db86aabSstevel #endif 8723db86aabSstevel 8733db86aabSstevel /* 8743db86aabSstevel * A single device (under a bridge). 8753db86aabSstevel * For each "reg" property with a length, allocate memory 8763db86aabSstevel * and program the base registers. 8773db86aabSstevel */ 8783db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 8793db86aabSstevel DDI_PROP_DONTPASS, "reg", (caddr_t)®, 8803db86aabSstevel &length) != DDI_PROP_SUCCESS) { 8813db86aabSstevel cardbus_err(dip, 1, "Failed to read reg property\n"); 8823db86aabSstevel entry->error = PCICFG_FAILURE; 8833db86aabSstevel (void) cardbus_config_teardown(&handle); 8843db86aabSstevel return (DDI_WALK_TERMINATE); 8853db86aabSstevel } 8863db86aabSstevel 8873db86aabSstevel rcount = length / sizeof (pci_regspec_t); 8883db86aabSstevel cardbus_err(dip, 9, "rcount = %d\n", rcount); 8893db86aabSstevel 8903db86aabSstevel for (i = 0; i < rcount; i++) { 8913db86aabSstevel if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) { 8923db86aabSstevel offset = PCI_REG_REG_G(reg[i].pci_phys_hi); 8933db86aabSstevel switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) { 8943db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_MEM64): 8953db86aabSstevel 8963db86aabSstevel (void) cardbus_get_mem(ddi_get_parent(dip), 8973db86aabSstevel entry, reg[i].pci_size_low, &mem_answer); 8983db86aabSstevel ASSERT(!PCICFG_HIADDR(mem_answer)); 8993db86aabSstevel pci_config_put32(handle, offset, 9003db86aabSstevel PCICFG_LOADDR(mem_answer)); 9013db86aabSstevel pci_config_put32(handle, offset + 4, 9023db86aabSstevel PCICFG_HIADDR(mem_answer)); 9033db86aabSstevel cardbus_err(dip, 8, 9043db86aabSstevel "REGISTER (64)LO [0x%x] ----> [0x%02x]\n", 9053db86aabSstevel pci_config_get32(handle, offset), offset); 9063db86aabSstevel cardbus_err(dip, 8, 9073db86aabSstevel "REGISTER (64)HI [0x%x] ----> [0x%02x]\n", 9083db86aabSstevel pci_config_get32(handle, offset+4), 9093db86aabSstevel offset+4); 9103db86aabSstevel reg[i].pci_phys_low = PCICFG_HIADDR(mem_answer); 9113db86aabSstevel reg[i].pci_phys_mid = PCICFG_LOADDR(mem_answer); 9123db86aabSstevel break; 9133db86aabSstevel 9143db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_MEM32): 9153db86aabSstevel /* allocate memory space from the allocator */ 9163db86aabSstevel 9173db86aabSstevel (void) cardbus_get_mem(ddi_get_parent(dip), 9183db86aabSstevel entry, reg[i].pci_size_low, &mem_answer); 9193db86aabSstevel pci_config_put32(handle, offset, 0xffffffff); 9203db86aabSstevel request = pci_config_get32(handle, offset); 9213db86aabSstevel 9223db86aabSstevel pci_config_put32(handle, offset, 9233db86aabSstevel (uint32_t)mem_answer); 9243db86aabSstevel reg[i].pci_phys_low = (uint32_t)mem_answer; 9253db86aabSstevel reg[i].pci_phys_mid = 0; 9263db86aabSstevel if (((PCI_BASE_TYPE_M & request) == 9273db86aabSstevel PCI_BASE_TYPE_ALL) && 9283db86aabSstevel ((PCI_BASE_SPACE_M & request) == 9293db86aabSstevel PCI_BASE_SPACE_MEM)) { 9303db86aabSstevel cardbus_err(dip, 8, 9313db86aabSstevel "REGISTER (64)LO [0x%x] ----> " 9323db86aabSstevel "[0x%02x]\n", 9333db86aabSstevel pci_config_get32(handle, offset), 9343db86aabSstevel offset); 9353db86aabSstevel pci_config_put32(handle, 9363db86aabSstevel offset + 4, 0); 9373db86aabSstevel cardbus_err(dip, 8, 9383db86aabSstevel "REGISTER (64)HI [0x%x] ----> " 9393db86aabSstevel "[0x%02x]\n", 9403db86aabSstevel pci_config_get32(handle, offset+4), 9413db86aabSstevel offset+4); 9423db86aabSstevel } else { 9433db86aabSstevel cardbus_err(dip, 8, 9443db86aabSstevel "REGISTER (32)LO [0x%x] ----> " 9453db86aabSstevel "[0x%02x]\n", 9463db86aabSstevel pci_config_get32(handle, offset), 9473db86aabSstevel offset); 9483db86aabSstevel } 9493db86aabSstevel break; 9503db86aabSstevel 9513db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_IO): 9523db86aabSstevel /* allocate I/O space from the allocator */ 9533db86aabSstevel 9543db86aabSstevel (void) cardbus_get_io(ddi_get_parent(dip), 9553db86aabSstevel entry, reg[i].pci_size_low, &io_answer); 9563db86aabSstevel pci_config_put32(handle, offset, io_answer); 9573db86aabSstevel cardbus_err(dip, 8, 9583db86aabSstevel "REGISTER (I/O)LO [0x%x] ----> [0x%02x]\n", 9593db86aabSstevel pci_config_get32(handle, offset), offset); 9603db86aabSstevel reg[i].pci_phys_low = io_answer; 9613db86aabSstevel break; 9623db86aabSstevel 9633db86aabSstevel default: 9643db86aabSstevel cardbus_err(dip, 1, "Unknown register type\n"); 9653db86aabSstevel kmem_free(reg, length); 9663db86aabSstevel (void) cardbus_config_teardown(&handle); 9673db86aabSstevel entry->error = PCICFG_FAILURE; 9683db86aabSstevel return (DDI_WALK_TERMINATE); 9693db86aabSstevel } /* switch */ 9703db86aabSstevel 9713db86aabSstevel /* 9723db86aabSstevel * Now that memory locations are assigned, 9733db86aabSstevel * update the assigned address property. 9743db86aabSstevel */ 9753db86aabSstevel if (cardbus_update_assigned_prop(dip, 9763db86aabSstevel ®[i]) != PCICFG_SUCCESS) { 9773db86aabSstevel kmem_free(reg, length); 9783db86aabSstevel (void) cardbus_config_teardown(&handle); 9793db86aabSstevel entry->error = PCICFG_FAILURE; 9803db86aabSstevel return (DDI_WALK_TERMINATE); 9813db86aabSstevel } 9823db86aabSstevel } 9833db86aabSstevel } 9843db86aabSstevel kmem_free(reg, length); 9853db86aabSstevel enable_cardbus_device(dip, handle); 9863db86aabSstevel #ifdef CARDBUS_DEBUG 9873db86aabSstevel if (cardbus_debug >= 9) { 9883db86aabSstevel cardbus_dump_config(handle); 9893db86aabSstevel } 9903db86aabSstevel #endif 9913db86aabSstevel bad_device: 9923db86aabSstevel (void) cardbus_config_teardown(&handle); 9933db86aabSstevel return (DDI_WALK_CONTINUE); 9943db86aabSstevel } 9953db86aabSstevel 9963db86aabSstevel static int 9973db86aabSstevel cardbus_isa_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry, 9983db86aabSstevel ddi_acc_handle_t handle) 9993db86aabSstevel { 10003db86aabSstevel struct ebus_pci_rangespec range; 10013db86aabSstevel int count; 10023db86aabSstevel pci_regspec_t *reg; 10033db86aabSstevel int length; 10043db86aabSstevel int rcount; 10053db86aabSstevel uint32_t io_answer = 0xffffffff; 10063db86aabSstevel isa_phdl_t isa_phdl; 10073db86aabSstevel int i; 10083db86aabSstevel 10093db86aabSstevel cardbus_err(dip, 8, "cardbus_isa_bridge_ranges\n"); 10103db86aabSstevel 10113db86aabSstevel bzero((caddr_t)&range, sizeof (range)); 10123db86aabSstevel 10133db86aabSstevel #ifdef sparc 10143db86aabSstevel /* 10153db86aabSstevel * If there is an interrupt pin set program 10163db86aabSstevel * interrupt line with default values. 10173db86aabSstevel */ 10183db86aabSstevel if (pci_config_get8(handle, PCI_CONF_IPIN)) { 10193db86aabSstevel pci_config_put8(handle, PCI_CONF_ILINE, 0xf); 10203db86aabSstevel } 10213db86aabSstevel #else 10223db86aabSstevel (void) cardbus_validate_iline(dip, handle); 10233db86aabSstevel #endif 10243db86aabSstevel 10253db86aabSstevel /* 10263db86aabSstevel * For each "reg" property with a length, allocate memory. 10273db86aabSstevel */ 10283db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 10293db86aabSstevel DDI_PROP_DONTPASS, "reg", (caddr_t)®, 10303db86aabSstevel &length) != DDI_PROP_SUCCESS) { 10313db86aabSstevel cardbus_err(dip, 1, "Failed to read reg property\n"); 10323db86aabSstevel entry->error = PCICFG_FAILURE; 10333db86aabSstevel return (DDI_WALK_TERMINATE); 10343db86aabSstevel } 10353db86aabSstevel 10363db86aabSstevel rcount = length / sizeof (pci_regspec_t); 10373db86aabSstevel 10383db86aabSstevel for (i = 0; i < rcount; i++) { 10393db86aabSstevel if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) { 10403db86aabSstevel switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) { 10413db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_IO): 10423db86aabSstevel /* allocate I/O space from the allocator */ 10433db86aabSstevel 10443db86aabSstevel (void) cardbus_get_io(ddi_get_parent(dip), 10453db86aabSstevel entry, reg[i].pci_size_low, &io_answer); 10463db86aabSstevel cardbus_err(dip, 8, 10473db86aabSstevel "ISA (I/O)LO ----> [0x%x]\n", io_answer); 10483db86aabSstevel reg[i].pci_phys_low = io_answer; 10493db86aabSstevel range.phys_hi = 0; 10503db86aabSstevel range.phys_low = io_answer; 10513db86aabSstevel range.par_phys_hi = reg[i].pci_phys_hi | 10523db86aabSstevel PCI_REG_REL_M; 10533db86aabSstevel range.par_phys_low = reg[i].pci_phys_low; 10543db86aabSstevel range.par_phys_mid = reg[i].pci_phys_mid; 10553db86aabSstevel range.rng_size = reg[i].pci_size_low; 10563db86aabSstevel i = rcount; 10573db86aabSstevel break; 10583db86aabSstevel 10593db86aabSstevel default: 10603db86aabSstevel cardbus_err(dip, 1, "Unknown register type\n"); 10613db86aabSstevel kmem_free(reg, length); 10623db86aabSstevel (void) cardbus_config_teardown(&handle); 10633db86aabSstevel entry->error = PCICFG_FAILURE; 10643db86aabSstevel return (DDI_WALK_TERMINATE); 10653db86aabSstevel } /* switch */ 10663db86aabSstevel } 10673db86aabSstevel } 10683db86aabSstevel kmem_free(reg, length); 10693db86aabSstevel 10703db86aabSstevel (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 10713db86aabSstevel dip, "ranges", (int *)&range, 10723db86aabSstevel sizeof (range)/sizeof (int)); 10733db86aabSstevel if (io_answer != 0xffffffff) { 10743db86aabSstevel isa_phdl.dip = dip; 10753db86aabSstevel isa_phdl.handle = handle; 10763db86aabSstevel isa_phdl.io_base = io_answer; 10773db86aabSstevel isa_phdl.io_decode_reg = 0x58; /* Pos decoded IO space 0 reg */ 10783db86aabSstevel /* i_ndi_block_device_tree_changes(&count); */ 10793db86aabSstevel ndi_devi_enter(dip, &count); 10803db86aabSstevel ddi_walk_devs(ddi_get_child(dip), 10813db86aabSstevel cardbus_add_isa_reg, (void *)&isa_phdl); 10823db86aabSstevel /* i_ndi_allow_device_tree_changes(count); */ 10833db86aabSstevel ndi_devi_exit(dip, count); 10843db86aabSstevel } 10853db86aabSstevel return (DDI_WALK_PRUNECHILD); 10863db86aabSstevel } 10873db86aabSstevel 10883db86aabSstevel /* 10893db86aabSstevel * This is specific to ITE8888 chip. 10903db86aabSstevel */ 10913db86aabSstevel static int 10923db86aabSstevel cardbus_add_isa_reg(dev_info_t *dip, void *arg) 10933db86aabSstevel { 10943db86aabSstevel uint32_t io_reg = 0; 10953db86aabSstevel int length; 10963db86aabSstevel uint32_t reg[3], *breg; 10973db86aabSstevel isa_phdl_t *phdl; 10983db86aabSstevel uint8_t sz; 10993db86aabSstevel 11003db86aabSstevel phdl = (isa_phdl_t *)arg; 11013db86aabSstevel cardbus_err(dip, 6, 11023db86aabSstevel "cardbus_add_isa_reg, base 0x%x\n", phdl->io_base); 11033db86aabSstevel 11043db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 11053db86aabSstevel DDI_PROP_DONTPASS, "basereg", (caddr_t)&breg, 11063db86aabSstevel &length) != DDI_PROP_SUCCESS) { 11073db86aabSstevel return (DDI_WALK_CONTINUE); 11083db86aabSstevel } 11093db86aabSstevel 11103db86aabSstevel if ((length / sizeof (reg)) < 1) { 11113db86aabSstevel kmem_free(breg, length); 11123db86aabSstevel return (DDI_WALK_CONTINUE); 11133db86aabSstevel } 11143db86aabSstevel 11153db86aabSstevel /* 11163db86aabSstevel * Add the "reg" property. 11173db86aabSstevel */ 11183db86aabSstevel reg[0] = 0; 11193db86aabSstevel reg[1] = breg[1] + phdl->io_base; 11203db86aabSstevel reg[2] = breg[2]; 11213db86aabSstevel 11223db86aabSstevel /* 11233db86aabSstevel * Generate the postive IO decode register setting. 11243db86aabSstevel */ 11253db86aabSstevel for (sz = 0; sz < 8; sz++) 11263db86aabSstevel if ((1<<sz) >= breg[2]) { 11273db86aabSstevel io_reg = breg[1] 11283db86aabSstevel | (1uL <<31) /* Enable */ 11293db86aabSstevel | (2uL <<29) /* Medium speed */ 11303db86aabSstevel | (1uL <<28) /* Aliase enable, */ 11313db86aabSstevel /* Don't care A[15:10] */ 11323db86aabSstevel | (sz<<24); /* Size code */ 11333db86aabSstevel break; 11343db86aabSstevel } 11353db86aabSstevel 11363db86aabSstevel (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 11373db86aabSstevel "reg", (int *)reg, 3); 11383db86aabSstevel (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "basereg"); 11393db86aabSstevel 11403db86aabSstevel if (io_reg) { 11413db86aabSstevel pci_config_put32(phdl->handle, phdl->io_decode_reg, io_reg); 11423db86aabSstevel cardbus_err(dip, 6, 11433db86aabSstevel "cardbus_add_isa_reg: I/O decode reg (0x%x) set to 0x%x\n", 11443db86aabSstevel phdl->io_decode_reg, 11453db86aabSstevel pci_config_get32(phdl->handle, phdl->io_decode_reg)); 11463db86aabSstevel phdl->io_decode_reg += sizeof (io_reg); 11473db86aabSstevel } else 11483db86aabSstevel cardbus_err(dip, 1, 11493db86aabSstevel "cardbus_add_isa_reg: register size (0x%x) too large\n", 11503db86aabSstevel breg[2]); 11513db86aabSstevel kmem_free(breg, length); 11523db86aabSstevel return (DDI_WALK_CONTINUE); 11533db86aabSstevel } 11543db86aabSstevel 11553db86aabSstevel /* 11563db86aabSstevel * In case we want to ensure that some space is allocated to the 11573db86aabSstevel * device tree below the cardbus bridge. 11583db86aabSstevel * This is only necessary if there is a device that needs to allocate 11593db86aabSstevel * resource below us. This can happen if there is another cardbus/PCMCIA 11603db86aabSstevel * bridge downstream. 11613db86aabSstevel */ 11623db86aabSstevel static uint32_t cardbus_min_spare_mem = 0; 11633db86aabSstevel static uint32_t cardbus_min_spare_io = 0; 11643db86aabSstevel 11653db86aabSstevel /* 11663db86aabSstevel * The "dip" passed to this routine is assumed to be 11673db86aabSstevel * the device at the attachment point. Currently it is 11683db86aabSstevel * assumed to be a bridge. 11693db86aabSstevel */ 11703db86aabSstevel static int 11713db86aabSstevel cardbus_allocate_chunk(dev_info_t *dip, uint8_t type, uint8_t sec_bus) 11723db86aabSstevel { 11733db86aabSstevel cardbus_phdl_t *phdl; 11743db86aabSstevel ndi_ra_request_t *mem_request; 11753db86aabSstevel ndi_ra_request_t *io_request; 11768134ee03Srw148561 ra_return_t res; 11773db86aabSstevel int count; 11783db86aabSstevel 11793db86aabSstevel /* 11803db86aabSstevel * This should not find an existing entry - so 11813db86aabSstevel * it will create a new one. 11823db86aabSstevel */ 11833db86aabSstevel phdl = cardbus_find_phdl(dip); 11843db86aabSstevel ASSERT(phdl); 11853db86aabSstevel 11863db86aabSstevel mem_request = &phdl->mem_req; 11873db86aabSstevel io_request = &phdl->io_req; 11883db86aabSstevel 11893db86aabSstevel /* 11903db86aabSstevel * Set highest_bus here. 11913db86aabSstevel * Otherwise if we don't find another bridge 11923db86aabSstevel * this never gets set. 11933db86aabSstevel */ 11943db86aabSstevel phdl->highest_bus = sec_bus; 11953db86aabSstevel 11963db86aabSstevel /* 11973db86aabSstevel * From this point in the tree - walk the devices, 11983db86aabSstevel * The function passed in will read and "sum" up 11993db86aabSstevel * the memory and I/O requirements and put them in 12003db86aabSstevel * structure "phdl". 12013db86aabSstevel */ 12023db86aabSstevel phdl->error = PCICFG_SUCCESS; 12033db86aabSstevel ndi_devi_enter(dip, &count); 12043db86aabSstevel ddi_walk_devs(ddi_get_child(dip), cardbus_sum_resources, (void *)phdl); 12053db86aabSstevel ndi_devi_exit(dip, count); 12063db86aabSstevel 12073db86aabSstevel if (phdl->error != PCICFG_SUCCESS) { 12080d282d13Srw148561 cmn_err(CE_WARN, "Failure summing resources\n"); 12093db86aabSstevel return (phdl->error); 12103db86aabSstevel } 12113db86aabSstevel 12123db86aabSstevel /* 12133db86aabSstevel * Call into the memory allocator with the request. 12143db86aabSstevel * Record the addresses returned in the phdl 12153db86aabSstevel */ 12163db86aabSstevel #ifdef _LP64 12173db86aabSstevel cardbus_err(dip, 8, 12183db86aabSstevel "AP requires [0x%lx] bytes of memory space, alligned 0x%x\n", 12193db86aabSstevel mem_request->ra_len, phdl->memory_gran); 12203db86aabSstevel cardbus_err(dip, 8, 12213db86aabSstevel "AP requires [0x%lx] bytes of I/O space, alligned 0x%x\n", 12223db86aabSstevel io_request->ra_len, phdl->io_gran); 12233db86aabSstevel #else 12243db86aabSstevel cardbus_err(dip, 8, 12253db86aabSstevel "AP requires [0x%llx] bytes of memory space, alligned 0x%x\n", 12263db86aabSstevel mem_request->ra_len, phdl->memory_gran); 12273db86aabSstevel cardbus_err(dip, 8, 12283db86aabSstevel "AP requires [0x%llx] bytes of I/O space, alligned 0x%x\n", 12293db86aabSstevel io_request->ra_len, phdl->io_gran); 12303db86aabSstevel #endif 12313db86aabSstevel 12323db86aabSstevel ASSERT(type == PCI_HEADER_CARDBUS); 12333db86aabSstevel 12343db86aabSstevel mem_request->ra_align_mask = phdl->memory_gran - 1; 12353db86aabSstevel io_request->ra_align_mask = phdl->io_gran - 1; 123681ea8c75Srw148561 phdl->res_dip = (dev_info_t *)-1; 12373db86aabSstevel 12383db86aabSstevel mem_request->ra_len += cardbus_min_spare_mem; 12393db86aabSstevel if (mem_request->ra_len) { 12403db86aabSstevel mem_request->ra_len = PCICFG_ROUND_UP( 12413db86aabSstevel mem_request->ra_len, 12423db86aabSstevel phdl->memory_gran); 12433db86aabSstevel #ifdef _LP64 12443db86aabSstevel cardbus_err(dip, 8, 12453db86aabSstevel "cardbus_allocate_chunk: ndi_ra_alloc 0x%lx bytes\n", 12463db86aabSstevel mem_request->ra_len); 12473db86aabSstevel #else 12483db86aabSstevel cardbus_err(dip, 8, 12493db86aabSstevel "cardbus_allocate_chunk: ndi_ra_alloc 0x%llx bytes\n", 12503db86aabSstevel mem_request->ra_len); 12513db86aabSstevel #endif 12523db86aabSstevel 12538134ee03Srw148561 if (pcmcia_alloc_mem(dip, mem_request, &res, 12548134ee03Srw148561 &phdl->res_dip) != NDI_SUCCESS) { 12550d282d13Srw148561 cmn_err(CE_WARN, "Failed to allocate memory for %s\n", 12560d282d13Srw148561 ddi_driver_name(dip)); 12573db86aabSstevel return (PCICFG_FAILURE); 12583db86aabSstevel } 12593db86aabSstevel 12608134ee03Srw148561 phdl->memory_base = phdl->memory_last = res.ra_addr_lo; 12618134ee03Srw148561 phdl->memory_len = res.ra_len; 12623db86aabSstevel } 12633db86aabSstevel 12643db86aabSstevel io_request->ra_len += cardbus_min_spare_io; 12653db86aabSstevel if (io_request->ra_len) { 12663db86aabSstevel 12670d282d13Srw148561 #if defined(__x86) || defined(__amd64) 12680d282d13Srw148561 io_request->ra_boundbase = 0x1000; 12690d282d13Srw148561 io_request->ra_boundlen = 0xefff; 12700d282d13Srw148561 #else 12713db86aabSstevel io_request->ra_boundbase = 0; 12723db86aabSstevel io_request->ra_boundlen = PCICFG_4GIG_LIMIT; 12730d282d13Srw148561 #endif 12743db86aabSstevel io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED; 12753db86aabSstevel io_request->ra_len = PCICFG_ROUND_UP(io_request->ra_len, 12763db86aabSstevel phdl->io_gran); 12778134ee03Srw148561 io_request->ra_align_mask = max(PCICFG_IOGRAN, 12788134ee03Srw148561 phdl->io_gran) - 1; 12793db86aabSstevel 12808134ee03Srw148561 if (pcmcia_alloc_io(dip, io_request, &res, 12818134ee03Srw148561 &phdl->res_dip) != NDI_SUCCESS) { 12820d282d13Srw148561 cmn_err(CE_WARN, "Failed to allocate I/O space " 12830d282d13Srw148561 "for %s\n", ddi_driver_name(dip)); 12843db86aabSstevel if (mem_request->ra_len) { 12858134ee03Srw148561 res.ra_addr_lo = phdl->memory_base; 12868134ee03Srw148561 res.ra_len = phdl->memory_len; 12878134ee03Srw148561 (void) pcmcia_free_mem(phdl->res_dip, &res); 12883db86aabSstevel phdl->memory_len = phdl->io_len = 0; 12893db86aabSstevel } 12903db86aabSstevel return (PCICFG_FAILURE); 12913db86aabSstevel } 12923db86aabSstevel 12938134ee03Srw148561 phdl->io_base = phdl->io_last = (uint32_t)res.ra_addr_lo; 12948134ee03Srw148561 phdl->io_len = (uint32_t)res.ra_len; 12953db86aabSstevel } 12963db86aabSstevel 12973db86aabSstevel #ifdef _LP64 12983db86aabSstevel cardbus_err(dip, 6, 12993db86aabSstevel "MEMORY BASE = [0x%lx] length [0x%lx]\n", 13003db86aabSstevel phdl->memory_base, phdl->memory_len); 13013db86aabSstevel #else 13023db86aabSstevel cardbus_err(dip, 6, 13033db86aabSstevel "MEMORY BASE = [0x%llx] length [0x%llx]\n", 13043db86aabSstevel phdl->memory_base, phdl->memory_len); 13053db86aabSstevel #endif 13063db86aabSstevel cardbus_err(dip, 6, 13073db86aabSstevel "IO BASE = [0x%x] length [0x%x]\n", 13083db86aabSstevel phdl->io_base, phdl->io_len); 13093db86aabSstevel 13103db86aabSstevel return (PCICFG_SUCCESS); 13113db86aabSstevel } 13123db86aabSstevel 13133db86aabSstevel static int 13143db86aabSstevel cardbus_free_chunk(dev_info_t *dip) 13153db86aabSstevel { 13163db86aabSstevel uint_t *bus; 13173db86aabSstevel int k; 13183db86aabSstevel 13193db86aabSstevel cardbus_err(dip, 6, "cardbus_free_chunk\n"); 13203db86aabSstevel 13213db86aabSstevel (void) cardbus_destroy_phdl(dip); 13223db86aabSstevel 13233db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 13243db86aabSstevel DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus, 13253db86aabSstevel &k) != DDI_PROP_SUCCESS) { 13263db86aabSstevel cardbus_err(dip, 1, 13273db86aabSstevel "cardbus_free_chunk: Failed to read bus-range property\n"); 13283db86aabSstevel return (PCICFG_FAILURE); 13293db86aabSstevel } 13303db86aabSstevel 13313db86aabSstevel cardbus_err(dip, 6, 13323db86aabSstevel "cardbus_free_chunk: Freeing bus [%d] range [%d]\n", 13333db86aabSstevel bus[0], bus[1] - bus[0] + 1); 13343db86aabSstevel 13353db86aabSstevel if (ndi_ra_free(dip, 13363db86aabSstevel (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1), 13373db86aabSstevel NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) { 13383db86aabSstevel cardbus_err(dip, 1, 13393db86aabSstevel "cardbus_free_chunk: Failed to free bus numbers\n"); 13403db86aabSstevel 13413db86aabSstevel kmem_free(bus, k); 13423db86aabSstevel return (PCICFG_FAILURE); 13433db86aabSstevel } 13443db86aabSstevel 13453db86aabSstevel kmem_free(bus, k); 13463db86aabSstevel return (PCICFG_SUCCESS); 13473db86aabSstevel } 13483db86aabSstevel 13493db86aabSstevel /* 13503db86aabSstevel * Put bridge registers into initial state 13513db86aabSstevel */ 13523db86aabSstevel static void 13533db86aabSstevel cardbus_setup_bridge(dev_info_t *dip, cardbus_phdl_t *entry, 13543db86aabSstevel ddi_acc_handle_t handle) 13553db86aabSstevel { 13563db86aabSstevel uint8_t header_type = pci_config_get8(handle, PCI_CONF_HEADER); 13573db86aabSstevel 13583db86aabSstevel #ifdef _LP64 13593db86aabSstevel cardbus_err(NULL, 6, 13603db86aabSstevel "cardbus_setup_bridge: " 13613db86aabSstevel "highest bus %d, mem_last 0x%lx, io_last 0x%x\n", 13623db86aabSstevel entry->highest_bus, entry->memory_last, entry->io_last); 13633db86aabSstevel #else 13643db86aabSstevel cardbus_err(NULL, 6, 13653db86aabSstevel "cardbus_setup_bridge: " 13663db86aabSstevel "highest bus %d, mem_last 0x%llx, io_last 0x%x\n", 13673db86aabSstevel entry->highest_bus, entry->memory_last, entry->io_last); 13683db86aabSstevel #endif 13693db86aabSstevel 13703db86aabSstevel if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) { 13713db86aabSstevel uint32_t uval; 13723db86aabSstevel 13733db86aabSstevel /* 13743db86aabSstevel * The highest bus seen during probing is 13753db86aabSstevel * the max-subordinate bus 13763db86aabSstevel */ 13773db86aabSstevel pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus); 13783db86aabSstevel 13793db86aabSstevel uval = PCICFG_ROUND_UP(entry->memory_last, PCICFG_MEMGRAN); 13803db86aabSstevel if (uval != entry->memory_last) { 13813db86aabSstevel #ifdef _LP64 13823db86aabSstevel cardbus_err(dip, 8, 13833db86aabSstevel "Adding [0x%lx] before bridge (mem)\n", 13843db86aabSstevel uval - entry->memory_last); 13853db86aabSstevel #else 13863db86aabSstevel cardbus_err(dip, 8, 13873db86aabSstevel "Adding [0x%llx] before bridge (mem)\n", 13883db86aabSstevel uval - entry->memory_last); 13893db86aabSstevel #endif 13903db86aabSstevel (void) cardbus_get_mem(ddi_get_parent(dip), entry, 13913db86aabSstevel uval - entry->memory_last, NULL); 13923db86aabSstevel } 13933db86aabSstevel 13943db86aabSstevel /* 13953db86aabSstevel * Program the memory base register with the 13963db86aabSstevel * start of the memory range 13973db86aabSstevel */ 13983db86aabSstevel #ifdef _LP64 13993db86aabSstevel cardbus_err(NULL, 8, 14003db86aabSstevel "store 0x%x(0x%lx) in pci bridge memory base register\n", 14013db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(uval)), 14023db86aabSstevel entry->memory_last); 14033db86aabSstevel #else 14043db86aabSstevel cardbus_err(NULL, 8, 14053db86aabSstevel "store 0x%x(0x%llx) in pci bridge memory base register\n", 14063db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(uval)), 14073db86aabSstevel entry->memory_last); 14083db86aabSstevel #endif 14093db86aabSstevel pci_config_put16(handle, PCI_BCNF_MEM_BASE, 14103db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(uval))); 14113db86aabSstevel 14123db86aabSstevel uval = PCICFG_ROUND_UP(entry->io_last, PCICFG_IOGRAN); 14133db86aabSstevel if (uval != entry->io_last) { 14143db86aabSstevel cardbus_err(dip, 8, 14153db86aabSstevel "Adding [0x%x] before bridge (I/O)\n", 14163db86aabSstevel uval - entry->io_last); 14173db86aabSstevel (void) cardbus_get_io(ddi_get_parent(dip), entry, 14183db86aabSstevel uval - entry->io_last, NULL); 14193db86aabSstevel } 14203db86aabSstevel cardbus_err(NULL, 8, 14213db86aabSstevel "store 0x%02x/0x%04x(0x%x) in " 14223db86aabSstevel "pci bridge I/O hi/low base register\n", 14233db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(uval)), 14243db86aabSstevel PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(uval))), 14253db86aabSstevel entry->io_last); 14263db86aabSstevel /* 14273db86aabSstevel * Program the I/O base register with the start of the I/O range 14283db86aabSstevel */ 14293db86aabSstevel pci_config_put8(handle, PCI_BCNF_IO_BASE_LOW, 14303db86aabSstevel PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(uval)))); 14313db86aabSstevel 14323db86aabSstevel pci_config_put16(handle, PCI_BCNF_IO_BASE_HI, 14333db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(uval))); 14343db86aabSstevel 14353db86aabSstevel /* 14363db86aabSstevel * Clear status bits 14373db86aabSstevel */ 14383db86aabSstevel pci_config_put16(handle, PCI_BCNF_SEC_STATUS, 0xffff); 14393db86aabSstevel 14403db86aabSstevel /* 14413db86aabSstevel * Turn off prefetchable range 14423db86aabSstevel */ 14433db86aabSstevel pci_config_put32(handle, PCI_BCNF_PF_BASE_LOW, 0x0000ffff); 14443db86aabSstevel pci_config_put32(handle, PCI_BCNF_PF_BASE_HIGH, 0xffffffff); 14453db86aabSstevel 14463db86aabSstevel pci_config_put32(handle, PCI_BCNF_PF_LIMIT_HIGH, 0x0); 14473db86aabSstevel 14483db86aabSstevel #ifdef sparc 14493db86aabSstevel /* 14503db86aabSstevel * If there is an interrupt pin set program 14513db86aabSstevel * interrupt line with default values. 14523db86aabSstevel */ 14533db86aabSstevel if (pci_config_get8(handle, PCI_CONF_IPIN)) { 14543db86aabSstevel pci_config_put8(handle, PCI_CONF_ILINE, 0xf); 14553db86aabSstevel } 14563db86aabSstevel #else 14573db86aabSstevel (void) cardbus_validate_iline(dip, handle); 14583db86aabSstevel #endif 14593db86aabSstevel 14603db86aabSstevel 14613db86aabSstevel } else if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_CARDBUS) { 14623db86aabSstevel 14633db86aabSstevel /* 14643db86aabSstevel * The highest bus seen during probing is 14653db86aabSstevel * the max-subordinate bus 14663db86aabSstevel */ 14673db86aabSstevel pci_config_put8(handle, PCI_CBUS_SUB_BUS_NO, 14683db86aabSstevel entry->highest_bus); 14693db86aabSstevel 14703db86aabSstevel /* 14713db86aabSstevel * Program the memory base register with the 14723db86aabSstevel * start of the memory range 14733db86aabSstevel */ 14743db86aabSstevel #ifdef _LP64 14753db86aabSstevel cardbus_err(NULL, 8, 14763db86aabSstevel "store 0x%x(0x%lx) in " 14773db86aabSstevel "cardbus memory base register 0, len 0x%lx\n", 14783db86aabSstevel PCICFG_LOADDR(entry->memory_last), entry->memory_last, 14793db86aabSstevel entry->memory_len); 14803db86aabSstevel #else 14813db86aabSstevel cardbus_err(NULL, 8, 14823db86aabSstevel "store 0x%x(0x%llx) in " 14833db86aabSstevel "cardbus memory base register 0, len 0x%llx\n", 14843db86aabSstevel PCICFG_LOADDR(entry->memory_last), entry->memory_last, 14853db86aabSstevel entry->memory_len); 14863db86aabSstevel #endif 14873db86aabSstevel 14883db86aabSstevel pci_config_put32(handle, PCI_CBUS_MEM_BASE0, 14893db86aabSstevel PCICFG_LOADDR(entry->memory_last)); 14903db86aabSstevel 14913db86aabSstevel /* 14923db86aabSstevel * Program the I/O base register with the start of the I/O range 14933db86aabSstevel */ 14943db86aabSstevel cardbus_err(NULL, 8, 14953db86aabSstevel "store 0x%x in cb IO base register 0 len 0x%x\n", 14963db86aabSstevel PCICFG_LOADDR(entry->io_last), 14973db86aabSstevel entry->io_len); 14983db86aabSstevel 14993db86aabSstevel pci_config_put32(handle, PCI_CBUS_IO_BASE0, 15003db86aabSstevel PCICFG_LOADDR(entry->io_last)); 15013db86aabSstevel 15023db86aabSstevel /* 15033db86aabSstevel * Clear status bits 15043db86aabSstevel */ 15053db86aabSstevel pci_config_put16(handle, PCI_CBUS_SEC_STATUS, 0xffff); 15063db86aabSstevel 15073db86aabSstevel #ifdef sparc 15083db86aabSstevel /* 15093db86aabSstevel * If there is an interrupt pin set program 15103db86aabSstevel * interrupt line with default values. 15113db86aabSstevel */ 15123db86aabSstevel if (pci_config_get8(handle, PCI_CONF_IPIN)) { 15133db86aabSstevel pci_config_put8(handle, PCI_CONF_ILINE, 0xf); 15143db86aabSstevel } 15153db86aabSstevel #else 15163db86aabSstevel (void) cardbus_validate_iline(dip, handle); 15173db86aabSstevel #endif 15183db86aabSstevel 15193db86aabSstevel 15203db86aabSstevel /* 15213db86aabSstevel * LATER: use these registers 15223db86aabSstevel */ 15233db86aabSstevel pci_config_put32(handle, PCI_CBUS_MEM_BASE1, 0); 15243db86aabSstevel pci_config_put32(handle, PCI_CBUS_MEM_LIMIT1, 0); 15253db86aabSstevel pci_config_put32(handle, PCI_CBUS_IO_BASE1, 0); 15263db86aabSstevel pci_config_put32(handle, PCI_CBUS_IO_LIMIT1, 0); 15273db86aabSstevel } else { 15283db86aabSstevel cmn_err(CE_WARN, "header type 0x%x, probably unknown bridge\n", 15293db86aabSstevel header_type & PCI_HEADER_TYPE_M); 15303db86aabSstevel } 15313db86aabSstevel 15323db86aabSstevel cardbus_err(NULL, 7, "cardbus_setup_bridge complete\n"); 15333db86aabSstevel } 15343db86aabSstevel 15353db86aabSstevel static void 15363db86aabSstevel cardbus_update_bridge(dev_info_t *dip, cardbus_phdl_t *entry, 15373db86aabSstevel ddi_acc_handle_t handle) 15383db86aabSstevel { 15393db86aabSstevel uint_t length; 15403db86aabSstevel uint16_t word16 = pci_config_get16(handle, PCI_CONF_COMM); 15413db86aabSstevel const uint8_t header_type = pci_config_get8(handle, PCI_CONF_HEADER) 15423db86aabSstevel & PCI_HEADER_TYPE_M; 15433db86aabSstevel uint32_t bridge_gran; 15443db86aabSstevel uint64_t rlval; 15453db86aabSstevel 15463db86aabSstevel if (header_type == PCI_HEADER_CARDBUS) 15473db86aabSstevel bridge_gran = CBCFG_MEMGRAN; 15483db86aabSstevel else 15493db86aabSstevel bridge_gran = PCICFG_MEMGRAN; 15503db86aabSstevel 15513db86aabSstevel /* 15523db86aabSstevel * Program the memory limit register with the end of the memory range 15533db86aabSstevel */ 15543db86aabSstevel #ifdef _LP64 15553db86aabSstevel cardbus_err(dip, 6, 15563db86aabSstevel "cardbus_update_bridge: Mem base 0x%lx len 0x%lx " 15573db86aabSstevel "last 0x%lx gran 0x%x gran end 0x%lx\n", 15583db86aabSstevel entry->memory_base, entry->memory_len, 15593db86aabSstevel entry->memory_last, entry->memory_gran, 15603db86aabSstevel PCICFG_ROUND_UP(entry->memory_last, entry->memory_gran)); 15613db86aabSstevel #else 15623db86aabSstevel cardbus_err(dip, 6, 15633db86aabSstevel "cardbus_update_bridge: Mem base 0x%llx len 0x%llx " 15643db86aabSstevel "last 0x%llx gran 0x%x gran end 0x%lx\n", 15653db86aabSstevel entry->memory_base, entry->memory_len, 15663db86aabSstevel entry->memory_last, entry->memory_gran, 15673db86aabSstevel PCICFG_ROUND_UP(entry->memory_last, entry->memory_gran)); 15683db86aabSstevel #endif 15693db86aabSstevel /* 15703db86aabSstevel * Since this is a bridge, the rest of this range will 15713db86aabSstevel * be responded to by the bridge. We have to round up 15723db86aabSstevel * so no other device claims it. 15733db86aabSstevel */ 15743db86aabSstevel length = PCICFG_ROUND_UP(entry->memory_last + cardbus_min_spare_mem, 15753db86aabSstevel bridge_gran) - entry->memory_last; 15763db86aabSstevel 15773db86aabSstevel if (length > 0) { 15783db86aabSstevel /* 15793db86aabSstevel * This is to allow space that isn't actually being used by 15803db86aabSstevel * anything to be allocated by devices such as a downstream 15813db86aabSstevel * PCMCIA controller. 15823db86aabSstevel */ 15833db86aabSstevel (void) cardbus_get_mem(dip, entry, length, NULL); 15843db86aabSstevel cardbus_err(dip, 8, 15853db86aabSstevel "Added [0x%x] at the top of the bridge (mem)\n", length); 15863db86aabSstevel } 15873db86aabSstevel 15883db86aabSstevel if (entry->memory_len) { 15893db86aabSstevel if (header_type == PCI_HEADER_CARDBUS) { 15903db86aabSstevel rlval = PCICFG_ROUND_DOWN(entry->memory_last - 1, 15913db86aabSstevel CBCFG_MEMGRAN); 15923db86aabSstevel #ifdef _LP64 15933db86aabSstevel cardbus_err(dip, 8, 15943db86aabSstevel "store 0x%x(0x%lx) in memory limit register 0\n", 15953db86aabSstevel PCICFG_LOADDR(rlval), rlval); 15963db86aabSstevel #else 15973db86aabSstevel cardbus_err(dip, 8, 15983db86aabSstevel "store 0x%x(0x%llx) in memory limit register 0\n", 15993db86aabSstevel PCICFG_LOADDR(rlval), rlval); 16003db86aabSstevel #endif 16013db86aabSstevel pci_config_put32(handle, PCI_CBUS_MEM_LIMIT0, 16023db86aabSstevel PCICFG_LOADDR(rlval)); 16033db86aabSstevel } else { 16043db86aabSstevel rlval = PCICFG_ROUND_DOWN(entry->memory_last - 1, 16053db86aabSstevel PCICFG_MEMGRAN); 16063db86aabSstevel #ifdef _LP64 16073db86aabSstevel cardbus_err(dip, 8, 16083db86aabSstevel "store 0x%x(0x%lx) in memory limit register\n", 16093db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(rlval)), 16103db86aabSstevel rlval); 16113db86aabSstevel #else 16123db86aabSstevel cardbus_err(dip, 8, 16133db86aabSstevel "store 0x%x(0x%llx) in memory limit register\n", 16143db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(rlval)), 16153db86aabSstevel rlval); 16163db86aabSstevel #endif 16173db86aabSstevel pci_config_put16(handle, PCI_BCNF_MEM_LIMIT, 16183db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(rlval))); 16193db86aabSstevel } 16203db86aabSstevel word16 |= PCI_COMM_MAE; 16213db86aabSstevel } 16223db86aabSstevel 16233db86aabSstevel cardbus_err(dip, 6, 16243db86aabSstevel "cardbus_update_bridge: I/O base 0x%x len 0x%x last 0x%x " 16253db86aabSstevel "gran 0x%x gran_end 0x%lx\n", 16263db86aabSstevel entry->io_base, entry->io_len, entry->io_last, entry->io_gran, 16273db86aabSstevel PCICFG_ROUND_UP(entry->io_last, entry->io_gran)); 16283db86aabSstevel 16293db86aabSstevel if (header_type == PCI_HEADER_CARDBUS) 16303db86aabSstevel bridge_gran = CBCFG_IOGRAN; 16313db86aabSstevel else 16323db86aabSstevel bridge_gran = PCICFG_IOGRAN; 16333db86aabSstevel 16343db86aabSstevel /* 16353db86aabSstevel * Same as above for I/O space. Since this is a 16363db86aabSstevel * bridge, the rest of this range will be responded 16373db86aabSstevel * to by the bridge. We have to round up so no 16383db86aabSstevel * other device claims it. 16393db86aabSstevel */ 16403db86aabSstevel length = PCICFG_ROUND_UP(entry->io_last + cardbus_min_spare_io, 16413db86aabSstevel bridge_gran) - entry->io_last; 16423db86aabSstevel if (length > 0) { 16433db86aabSstevel (void) cardbus_get_io(dip, entry, length, NULL); 16443db86aabSstevel cardbus_err(dip, 8, 16453db86aabSstevel "Added [0x%x] at the top of the bridge (I/O)\n", length); 16463db86aabSstevel } 16473db86aabSstevel 16483db86aabSstevel /* 16493db86aabSstevel * Program the I/O limit register with the end of the I/O range 16503db86aabSstevel */ 16513db86aabSstevel if (entry->io_len) { 16523db86aabSstevel if (header_type == PCI_HEADER_CARDBUS) { 16533db86aabSstevel rlval = PCICFG_ROUND_DOWN(entry->io_last - 1, 16543db86aabSstevel CBCFG_IOGRAN); 16553db86aabSstevel #ifdef _LP64 16563db86aabSstevel cardbus_err(dip, 8, 16573db86aabSstevel "store 0x%lx in IO limit register 0\n", rlval); 16583db86aabSstevel #else 16593db86aabSstevel cardbus_err(dip, 8, 16603db86aabSstevel "store 0x%llx in IO limit register 0\n", rlval); 16613db86aabSstevel #endif 16623db86aabSstevel pci_config_put32(handle, PCI_CBUS_IO_LIMIT0, rlval); 16633db86aabSstevel } else { 16643db86aabSstevel rlval = PCICFG_ROUND_DOWN(entry->io_last - 1, 16653db86aabSstevel PCICFG_IOGRAN); 16663db86aabSstevel #ifdef _LP64 16673db86aabSstevel cardbus_err(dip, 8, 16683db86aabSstevel "store 0x%x/0x%x(0x%lx) in " 16693db86aabSstevel "IO limit low/hi register\n", 16703db86aabSstevel PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))), 16713db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(rlval)), 16723db86aabSstevel rlval); 16733db86aabSstevel #else 16743db86aabSstevel cardbus_err(dip, 8, 16753db86aabSstevel "store 0x%x/0x%x(0x%llx) in " 16763db86aabSstevel "IO limit low/hi register\n", 16773db86aabSstevel PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))), 16783db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(rlval)), 16793db86aabSstevel rlval); 16803db86aabSstevel #endif 16813db86aabSstevel 16823db86aabSstevel pci_config_put8(handle, PCI_BCNF_IO_LIMIT_LOW, 16833db86aabSstevel PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval)))); 16843db86aabSstevel pci_config_put16(handle, PCI_BCNF_IO_LIMIT_HI, 16853db86aabSstevel PCICFG_HIWORD(PCICFG_LOADDR(rlval))); 16863db86aabSstevel } 16873db86aabSstevel word16 |= PCI_COMM_IO; 16883db86aabSstevel } 16893db86aabSstevel 16903db86aabSstevel pci_config_put16(handle, PCI_CONF_COMM, word16); 16913db86aabSstevel } 16923db86aabSstevel 16933db86aabSstevel static void 16943db86aabSstevel cardbus_get_mem(dev_info_t *dip, cardbus_phdl_t *entry, 16953db86aabSstevel uint32_t length, uint64_t *ans) 16963db86aabSstevel { 16973db86aabSstevel uint32_t hole; 16983db86aabSstevel 16993db86aabSstevel #ifdef _LP64 17003db86aabSstevel cardbus_err(NULL, 6, 17013db86aabSstevel "cardbus_get_mem: memory_last 0x%lx, length 0x%x, " 17023db86aabSstevel "memory_base 0x%lx, memory_len 0x%lx ans=0x%p\n", 17033db86aabSstevel entry->memory_last, length, 17043db86aabSstevel entry->memory_base, entry->memory_len, (void *) ans); 17053db86aabSstevel #else 17063db86aabSstevel cardbus_err(NULL, 6, 17073db86aabSstevel "cardbus_get_mem: memory_last 0x%llx, length 0x%x, " 17083db86aabSstevel "memory_base 0x%llx, memory_len 0x%llx ans=0x%p\n", 17093db86aabSstevel entry->memory_last, length, 17103db86aabSstevel entry->memory_base, entry->memory_len, (void *) ans); 17113db86aabSstevel #endif 17123db86aabSstevel 17133db86aabSstevel if (ans) { 17143db86aabSstevel /* 17153db86aabSstevel * Round up the request to the "size" boundary 17163db86aabSstevel */ 17173db86aabSstevel hole = PCICFG_ROUND_UP(entry->memory_last, length) 17183db86aabSstevel - entry->memory_last; 17193db86aabSstevel if (hole != 0) { 17203db86aabSstevel (void) cardbus_update_available_prop(dip, 17213db86aabSstevel PCI_ADDR_MEM32, 17223db86aabSstevel entry->memory_last, 17233db86aabSstevel (uint64_t)hole); 17243db86aabSstevel entry->memory_last += hole; 17253db86aabSstevel 17263db86aabSstevel #ifdef _LP64 17273db86aabSstevel cardbus_err(NULL, 6, 17283db86aabSstevel "cardbus_get_mem: " 17293db86aabSstevel "rounded memory_last up by 0x%x to 0x%lx, ", 17303db86aabSstevel hole, entry->memory_last); 17313db86aabSstevel #else 17323db86aabSstevel cardbus_err(NULL, 6, 17333db86aabSstevel "cardbus_get_mem: " 17343db86aabSstevel "rounded memory_last up by 0x%x to 0x%llx, ", 17353db86aabSstevel hole, entry->memory_last); 17363db86aabSstevel #endif 17373db86aabSstevel } 17383db86aabSstevel } else 17393db86aabSstevel (void) cardbus_update_available_prop(dip, PCI_ADDR_MEM32, 17403db86aabSstevel entry->memory_last, 17413db86aabSstevel (uint64_t)length); 17423db86aabSstevel 17433db86aabSstevel /* 17443db86aabSstevel * These routines should parcel out the memory 17453db86aabSstevel * completely. There should never be a case of 17463db86aabSstevel * over running the bounds. 17473db86aabSstevel */ 17483db86aabSstevel if ((entry->memory_last + length) > 17493db86aabSstevel (entry->memory_base + entry->memory_len)) 17503db86aabSstevel #ifdef _LP64 17513db86aabSstevel cardbus_err(NULL, 1, 17523db86aabSstevel "cardbus_get_mem: assert will fail %ld <= %ld," 17533db86aabSstevel "(0x%lx + 0x%x) <= (0x%lx + 0x%lx)\n", 17543db86aabSstevel #else 17553db86aabSstevel cardbus_err(NULL, 1, 17563db86aabSstevel "cardbus_get_mem: assert will fail %lld <= %lld, " 17573db86aabSstevel "(0x%llx + 0x%x) <= (0x%llx + 0x%llx)\n", 17583db86aabSstevel #endif 17593db86aabSstevel entry->memory_last + length, 17603db86aabSstevel entry->memory_base + entry->memory_len, 17613db86aabSstevel entry->memory_last, 17623db86aabSstevel length, 17633db86aabSstevel entry->memory_base, 17643db86aabSstevel entry->memory_len); 17653db86aabSstevel 17663db86aabSstevel ASSERT((entry->memory_last + length) <= 17673db86aabSstevel (entry->memory_base + entry->memory_len)); 17683db86aabSstevel /* 17693db86aabSstevel * If ans is NULL don't return anything, 17703db86aabSstevel * they are just asking to reserve the memory. 17713db86aabSstevel */ 17723db86aabSstevel if (ans != NULL) 17733db86aabSstevel *ans = entry->memory_last; 17743db86aabSstevel 17753db86aabSstevel /* 17763db86aabSstevel * Increment to the next location 17773db86aabSstevel */ 17783db86aabSstevel entry->memory_last += length; 17793db86aabSstevel } 17803db86aabSstevel 17813db86aabSstevel static void 17823db86aabSstevel cardbus_get_io(dev_info_t *dip, cardbus_phdl_t *entry, 17833db86aabSstevel uint32_t length, uint32_t *ans) 17843db86aabSstevel { 17853db86aabSstevel uint32_t hole; 17863db86aabSstevel 17873db86aabSstevel cardbus_err(NULL, 6, 17883db86aabSstevel "cardbus_get_io: io_last 0x%x, length 0x%x, " 17893db86aabSstevel "io_base 0x%x, io_len 0x%x ans=0x%p\n", 17903db86aabSstevel entry->io_last, length, 17913db86aabSstevel entry->io_base, entry->io_len, (void *) ans); 17923db86aabSstevel 17933db86aabSstevel if (ans) { 17943db86aabSstevel /* 17953db86aabSstevel * Round up the request to the "size" boundary 17963db86aabSstevel */ 17973db86aabSstevel hole = PCICFG_ROUND_UP(entry->io_last, length) - entry->io_last; 17983db86aabSstevel if (hole != 0) { 17993db86aabSstevel (void) cardbus_update_available_prop(dip, PCI_ADDR_IO, 18003db86aabSstevel (uint64_t)entry->io_last, 18013db86aabSstevel (uint64_t)hole); 18023db86aabSstevel entry->io_last += hole; 18033db86aabSstevel 18043db86aabSstevel cardbus_err(NULL, 6, 18053db86aabSstevel "cardbus_get_io: " 18063db86aabSstevel "rounded io_last up by 0x%x to 0x%x, ", 18073db86aabSstevel hole, entry->io_last); 18083db86aabSstevel } 18093db86aabSstevel } else 18103db86aabSstevel (void) cardbus_update_available_prop(dip, PCI_ADDR_IO, 18113db86aabSstevel (uint64_t)entry->io_last, 18123db86aabSstevel (uint64_t)length); 18133db86aabSstevel /* 18143db86aabSstevel * These routines should parcel out the memory 18153db86aabSstevel * completely. There should never be a case of 18163db86aabSstevel * over running the bounds. 18173db86aabSstevel */ 18183db86aabSstevel ASSERT((entry->io_last + length) <= 18193db86aabSstevel (entry->io_base + entry->io_len)); 18203db86aabSstevel 18213db86aabSstevel /* 18223db86aabSstevel * If ans is NULL don't return anything, 18233db86aabSstevel * they are just asking to reserve the memory. 18243db86aabSstevel */ 18253db86aabSstevel if (ans != NULL) 18263db86aabSstevel *ans = entry->io_last; 18273db86aabSstevel 18283db86aabSstevel /* 18293db86aabSstevel * Increment to the next location 18303db86aabSstevel */ 18313db86aabSstevel entry->io_last += length; 18323db86aabSstevel } 18333db86aabSstevel 18343db86aabSstevel static int 18353db86aabSstevel cardbus_sum_resources(dev_info_t *dip, void *hdl) 18363db86aabSstevel { 18373db86aabSstevel cardbus_phdl_t *entry = (cardbus_phdl_t *)hdl; 18383db86aabSstevel pci_regspec_t *pci_rp; 18393db86aabSstevel int length; 18403db86aabSstevel int rcount; 18413db86aabSstevel int i, ret; 18423db86aabSstevel ndi_ra_request_t *mem_request; 18433db86aabSstevel ndi_ra_request_t *io_request; 18443db86aabSstevel uint8_t header_type, base_class; 18453db86aabSstevel ddi_acc_handle_t handle; 18463db86aabSstevel 18473db86aabSstevel /* 18483db86aabSstevel * Ignore the attachment point and pcs. 18493db86aabSstevel */ 18503db86aabSstevel if (strcmp(ddi_binding_name(dip), "hp_attachment") == 0 || 18513db86aabSstevel strcmp(ddi_binding_name(dip), "pcs") == 0) { 18523db86aabSstevel cardbus_err(dip, 8, "cardbus_sum_resources: Ignoring\n"); 18533db86aabSstevel return (DDI_WALK_CONTINUE); 18543db86aabSstevel } 18553db86aabSstevel 18563db86aabSstevel mem_request = &entry->mem_req; 18573db86aabSstevel io_request = &entry->io_req; 18583db86aabSstevel 18593db86aabSstevel if (cardbus_config_setup(dip, &handle) != DDI_SUCCESS) { 18603db86aabSstevel cardbus_err(dip, 1, 18613db86aabSstevel "cardbus_sum_resources: Failed to map config space!\n"); 18623db86aabSstevel entry->error = PCICFG_FAILURE; 18633db86aabSstevel return (DDI_WALK_TERMINATE); 18643db86aabSstevel } 18653db86aabSstevel 18663db86aabSstevel ret = DDI_WALK_CONTINUE; 18673db86aabSstevel header_type = pci_config_get8(handle, PCI_CONF_HEADER); 18683db86aabSstevel base_class = pci_config_get8(handle, PCI_CONF_BASCLASS); 18693db86aabSstevel 18703db86aabSstevel /* 18713db86aabSstevel * If its a bridge - just record the highest bus seen 18723db86aabSstevel */ 18733db86aabSstevel if (base_class == PCI_CLASS_BRIDGE) { 18743db86aabSstevel uint8_t sub_class; 18753db86aabSstevel 18763db86aabSstevel sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS); 18773db86aabSstevel 18783db86aabSstevel switch (sub_class) { 18793db86aabSstevel case PCI_BRIDGE_PCI: 18803db86aabSstevel if ((header_type & PCI_HEADER_TYPE_M) 18813db86aabSstevel == PCI_HEADER_PPB) { 18823db86aabSstevel 18833db86aabSstevel if (entry->highest_bus < pci_config_get8(handle, 18843db86aabSstevel PCI_BCNF_SECBUS)) { 18853db86aabSstevel entry->highest_bus = pci_config_get8( 18863db86aabSstevel handle, PCI_BCNF_SECBUS); 18873db86aabSstevel } 18883db86aabSstevel 18893db86aabSstevel (void) cardbus_config_teardown(&handle); 18903db86aabSstevel #if defined(CARDBUS_DEBUG) 18913db86aabSstevel if (mem_request->ra_len != 18923db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len, 18933db86aabSstevel PCICFG_MEMGRAN)) { 18943db86aabSstevel 18953db86aabSstevel #ifdef _LP64 18963db86aabSstevel cardbus_err(dip, 8, 18973db86aabSstevel "Pre-align [0x%lx] to PCI bridge " 18983db86aabSstevel "memory gran " 18993db86aabSstevel "[0x%lx] -> [0x%lx]\n", 19003db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len, 19013db86aabSstevel PCICFG_MEMGRAN) - 19023db86aabSstevel mem_request->ra_len, 19033db86aabSstevel mem_request->ra_len, 19043db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len, 19053db86aabSstevel PCICFG_MEMGRAN)); 19063db86aabSstevel #else 19073db86aabSstevel cardbus_err(dip, 8, 19083db86aabSstevel "Pre-align [0x%llx] to PCI bridge " 19093db86aabSstevel "memory gran " 19103db86aabSstevel "[0x%llx] -> [0x%lx]\n", 19113db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len, 19123db86aabSstevel PCICFG_MEMGRAN) - 19133db86aabSstevel mem_request->ra_len, 19143db86aabSstevel mem_request->ra_len, 19153db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len, 19163db86aabSstevel PCICFG_MEMGRAN)); 19173db86aabSstevel #endif 19183db86aabSstevel } 19193db86aabSstevel 19203db86aabSstevel if (io_request->ra_len != 19213db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len, 19223db86aabSstevel PCICFG_IOGRAN)) { 19233db86aabSstevel 19243db86aabSstevel #ifdef _LP64 19253db86aabSstevel cardbus_err(dip, 8, 19263db86aabSstevel "Pre-align [0x%lx] to PCI bridge " 19273db86aabSstevel "I/O gran " 19283db86aabSstevel "[0x%lx] -> [0x%lx]\n", 19293db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len, 19303db86aabSstevel PCICFG_IOGRAN) - 19313db86aabSstevel io_request->ra_len, 19323db86aabSstevel io_request->ra_len, 19333db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len, 19343db86aabSstevel PCICFG_IOGRAN)); 19353db86aabSstevel #else 19363db86aabSstevel cardbus_err(dip, 8, 19373db86aabSstevel "Pre-align [0x%llx] to PCI bridge " 19383db86aabSstevel "I/O gran " 19393db86aabSstevel "[0x%llx] -> [0x%lx]\n", 19403db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len, 19413db86aabSstevel PCICFG_IOGRAN) - 19423db86aabSstevel io_request->ra_len, 19433db86aabSstevel io_request->ra_len, 19443db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len, 19453db86aabSstevel PCICFG_IOGRAN)); 19463db86aabSstevel #endif 19473db86aabSstevel } 19483db86aabSstevel 19493db86aabSstevel #endif 19503db86aabSstevel mem_request->ra_len = PCICFG_ROUND_UP( 19513db86aabSstevel mem_request->ra_len, 19523db86aabSstevel PCICFG_MEMGRAN); 19533db86aabSstevel io_request->ra_len = PCICFG_ROUND_UP( 19543db86aabSstevel io_request->ra_len, 19553db86aabSstevel PCICFG_IOGRAN); 19563db86aabSstevel if (entry->memory_gran < PCICFG_MEMGRAN) 19573db86aabSstevel entry->memory_gran = PCICFG_MEMGRAN; 19583db86aabSstevel if (entry->io_gran < PCICFG_IOGRAN) 19593db86aabSstevel entry->io_gran = PCICFG_IOGRAN; 19603db86aabSstevel ddi_walk_devs(ddi_get_child(dip), 19613db86aabSstevel cardbus_sum_resources, 19623db86aabSstevel (void *)entry); 19633db86aabSstevel #if defined(CARDBUS_DEBUG) 19643db86aabSstevel if (mem_request->ra_len != 19653db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len + 19663db86aabSstevel cardbus_min_spare_mem, PCICFG_MEMGRAN)) { 19673db86aabSstevel 19683db86aabSstevel #ifdef _LP64 19693db86aabSstevel cardbus_err(dip, 8, 19703db86aabSstevel "Post-align [0x%lx] to PCI bridge " 19713db86aabSstevel "memory gran " 19723db86aabSstevel "[0x%lx] -> [0x%lx]\n", 19733db86aabSstevel PCICFG_ROUND_UP( 19743db86aabSstevel mem_request->ra_len + 19753db86aabSstevel cardbus_min_spare_mem, 19763db86aabSstevel PCICFG_MEMGRAN) - 19773db86aabSstevel mem_request->ra_len, 19783db86aabSstevel mem_request->ra_len, 19793db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len 19803db86aabSstevel + cardbus_min_spare_mem, 19813db86aabSstevel PCICFG_MEMGRAN)); 19823db86aabSstevel #else 19833db86aabSstevel cardbus_err(dip, 8, 19843db86aabSstevel "Post-align [0x%llx] to PCI bridge " 19853db86aabSstevel "memory gran " 19863db86aabSstevel "[0x%llx] -> [0x%lx]\n", 19873db86aabSstevel PCICFG_ROUND_UP( 19883db86aabSstevel mem_request->ra_len + 19893db86aabSstevel cardbus_min_spare_mem, 19903db86aabSstevel PCICFG_MEMGRAN) - 19913db86aabSstevel mem_request->ra_len, 19923db86aabSstevel mem_request->ra_len, 19933db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len 19943db86aabSstevel + cardbus_min_spare_mem, 19953db86aabSstevel PCICFG_MEMGRAN)); 19963db86aabSstevel #endif 19973db86aabSstevel } 19983db86aabSstevel 19993db86aabSstevel if (io_request->ra_len != 20003db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len + 20013db86aabSstevel cardbus_min_spare_io, 20023db86aabSstevel PCICFG_IOGRAN)) { 20033db86aabSstevel 20043db86aabSstevel #ifdef _LP64 20053db86aabSstevel cardbus_err(dip, 8, 20063db86aabSstevel "Post-align [0x%lx] to PCI bridge " 20073db86aabSstevel "I/O gran " 20083db86aabSstevel "[0x%lx] -> [0x%lx]\n", 20093db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len + 20103db86aabSstevel cardbus_min_spare_io, 20113db86aabSstevel PCICFG_IOGRAN) - 20123db86aabSstevel io_request->ra_len, 20133db86aabSstevel io_request->ra_len, 20143db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len + 20153db86aabSstevel cardbus_min_spare_io, 20163db86aabSstevel PCICFG_IOGRAN)); 20173db86aabSstevel #else 20183db86aabSstevel cardbus_err(dip, 8, 20193db86aabSstevel "Post-align [0x%llx] to PCI bridge " 20203db86aabSstevel "I/O gran " 20213db86aabSstevel "[0x%llx] -> [0x%lx]\n", 20223db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len + 20233db86aabSstevel cardbus_min_spare_io, 20243db86aabSstevel PCICFG_IOGRAN) - 20253db86aabSstevel io_request->ra_len, 20263db86aabSstevel io_request->ra_len, 20273db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len + 20283db86aabSstevel cardbus_min_spare_io, 20293db86aabSstevel PCICFG_IOGRAN)); 20303db86aabSstevel #endif 20313db86aabSstevel } 20323db86aabSstevel #endif 20333db86aabSstevel mem_request->ra_len = PCICFG_ROUND_UP( 20343db86aabSstevel mem_request->ra_len + 20353db86aabSstevel cardbus_min_spare_mem, 20363db86aabSstevel PCICFG_MEMGRAN); 20373db86aabSstevel io_request->ra_len = PCICFG_ROUND_UP( 20383db86aabSstevel io_request->ra_len + 20393db86aabSstevel cardbus_min_spare_io, 20403db86aabSstevel PCICFG_IOGRAN); 20413db86aabSstevel } 20423db86aabSstevel return (DDI_WALK_PRUNECHILD); 20433db86aabSstevel 20443db86aabSstevel case PCI_BRIDGE_CARDBUS: 20453db86aabSstevel /* 20463db86aabSstevel * Cardbus has I/O registers. 20473db86aabSstevel */ 20483db86aabSstevel break; 20493db86aabSstevel 20503db86aabSstevel case PCI_BRIDGE_ISA: 20513db86aabSstevel /* 20523db86aabSstevel * All the registers requirements for ISA 20533db86aabSstevel * are stored in the reg structure of the bridge. 20543db86aabSstevel * Children of ISA are not of type PCI 20553db86aabSstevel * so must not come through here because 20563db86aabSstevel * cardbus_config_setup() will fail. 20573db86aabSstevel */ 20583db86aabSstevel ret = DDI_WALK_PRUNECHILD; 20593db86aabSstevel break; 20603db86aabSstevel 20613db86aabSstevel default: 20623db86aabSstevel /* 20633db86aabSstevel * Treat other bridges as leaf nodes. 20643db86aabSstevel */ 20653db86aabSstevel break; 20663db86aabSstevel } 20673db86aabSstevel } 20683db86aabSstevel 20693db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 20703db86aabSstevel DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp, 20713db86aabSstevel &length) != DDI_PROP_SUCCESS) { 20723db86aabSstevel /* 20733db86aabSstevel * If one node in (the subtree of nodes) 20743db86aabSstevel * does'nt have a "reg" property fail the 20753db86aabSstevel * allocation. 20763db86aabSstevel */ 20773db86aabSstevel entry->memory_len = 0; 20783db86aabSstevel entry->io_len = 0; 20793db86aabSstevel entry->error = PCICFG_FAILURE; 20803db86aabSstevel (void) cardbus_config_teardown(&handle); 20813db86aabSstevel return (DDI_WALK_TERMINATE); 20823db86aabSstevel } 20833db86aabSstevel 20843db86aabSstevel /* 20853db86aabSstevel * For each "reg" property with a length, add that to the 20863db86aabSstevel * total memory (or I/O) to allocate. 20873db86aabSstevel */ 20883db86aabSstevel rcount = length / sizeof (pci_regspec_t); 20893db86aabSstevel 20903db86aabSstevel for (i = 0; i < rcount; i++) { 20913db86aabSstevel 20923db86aabSstevel switch (PCI_REG_ADDR_G(pci_rp[i].pci_phys_hi)) { 20933db86aabSstevel 20943db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_MEM32): 20953db86aabSstevel mem_request->ra_len = 20963db86aabSstevel pci_rp[i].pci_size_low + 20973db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len, 20983db86aabSstevel pci_rp[i].pci_size_low); 20993db86aabSstevel 21003db86aabSstevel cardbus_err(dip, 8, 21013db86aabSstevel "ADDING 32 --->0x%x for BAR@0x%x\n", 21023db86aabSstevel pci_rp[i].pci_size_low, 21033db86aabSstevel PCI_REG_REG_G(pci_rp[i].pci_phys_hi)); 21043db86aabSstevel /* 21053db86aabSstevel * the granualarity needs to be the larger of 21063db86aabSstevel * the maximum amount of memory that we're going to 21073db86aabSstevel * ask for, and the PCI-PCI bridge granularity (1M) 21083db86aabSstevel */ 21093db86aabSstevel if (pci_rp[i].pci_size_low > entry->memory_gran) 21103db86aabSstevel entry->memory_gran = pci_rp[i].pci_size_low; 21113db86aabSstevel break; 21123db86aabSstevel 21133db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_MEM64): 21143db86aabSstevel mem_request->ra_len = 21153db86aabSstevel pci_rp[i].pci_size_low + 21163db86aabSstevel PCICFG_ROUND_UP(mem_request->ra_len, 21173db86aabSstevel pci_rp[i].pci_size_low); 21183db86aabSstevel cardbus_err(dip, 8, 21193db86aabSstevel "ADDING 64 --->0x%x for BAR@0x%x\n", 21203db86aabSstevel pci_rp[i].pci_size_low, 21213db86aabSstevel PCI_REG_REG_G(pci_rp[i].pci_phys_hi)); 21223db86aabSstevel 21233db86aabSstevel if (pci_rp[i].pci_size_low > entry->memory_gran) 21243db86aabSstevel entry->memory_gran = pci_rp[i].pci_size_low; 21253db86aabSstevel break; 21263db86aabSstevel 21273db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_IO): 21283db86aabSstevel io_request->ra_len = 21293db86aabSstevel pci_rp[i].pci_size_low + 21303db86aabSstevel PCICFG_ROUND_UP(io_request->ra_len, 21313db86aabSstevel pci_rp[i].pci_size_low); 21323db86aabSstevel cardbus_err(dip, 8, 21333db86aabSstevel "ADDING I/O --->0x%x for BAR@0x%x\n", 21343db86aabSstevel pci_rp[i].pci_size_low, 21353db86aabSstevel PCI_REG_REG_G(pci_rp[i].pci_phys_hi)); 21363db86aabSstevel 21373db86aabSstevel if (pci_rp[i].pci_size_low > entry->io_gran) 21383db86aabSstevel entry->io_gran = pci_rp[i].pci_size_low; 21393db86aabSstevel break; 21403db86aabSstevel 21413db86aabSstevel default: 21423db86aabSstevel /* Config space register - not included */ 21433db86aabSstevel break; 21443db86aabSstevel } 21453db86aabSstevel } 21463db86aabSstevel 21473db86aabSstevel /* 21483db86aabSstevel * free the memory allocated by ddi_getlongprop 21493db86aabSstevel */ 21503db86aabSstevel kmem_free(pci_rp, length); 21513db86aabSstevel 21523db86aabSstevel /* 21533db86aabSstevel * continue the walk to the next sibling to sum memory 21543db86aabSstevel */ 21553db86aabSstevel 21563db86aabSstevel (void) cardbus_config_teardown(&handle); 21573db86aabSstevel 21583db86aabSstevel #ifdef _LP64 21593db86aabSstevel cardbus_err(dip, 8, 21603db86aabSstevel "Memory 0x%lx bytes, I/O 0x%lx bytes, " 21613db86aabSstevel "Memgran 0x%x, IOgran 0x%x\n", 21623db86aabSstevel mem_request->ra_len, io_request->ra_len, 21633db86aabSstevel entry->memory_gran, entry->io_gran); 21643db86aabSstevel #else 21653db86aabSstevel cardbus_err(dip, 8, 21663db86aabSstevel "Memory 0x%llx bytes, I/O 0x%llx bytes, " 21673db86aabSstevel "Memgran 0x%x, IOgran 0x%x\n", 21683db86aabSstevel mem_request->ra_len, io_request->ra_len, 21693db86aabSstevel entry->memory_gran, entry->io_gran); 21703db86aabSstevel #endif 21713db86aabSstevel 21723db86aabSstevel return (ret); 21733db86aabSstevel } 21743db86aabSstevel 21753db86aabSstevel /* 21763db86aabSstevel * Free resources allocated to a bridge. 21773db86aabSstevel * Note that this routine does not call ndi_ra_free() to actually 21783db86aabSstevel * free memory/IO/Bus. This is done as a single chunk for the entire 21793db86aabSstevel * device tree in cardbus_free_chunk(). 21803db86aabSstevel */ 21813db86aabSstevel static int 21823db86aabSstevel cardbus_free_bridge_resources(dev_info_t *dip) 21833db86aabSstevel { 21843db86aabSstevel cardbus_range_t *ranges; 21853db86aabSstevel uint_t *bus; 21863db86aabSstevel int k; 21873db86aabSstevel int length; 21883db86aabSstevel int i; 21893db86aabSstevel 21903db86aabSstevel cardbus_err(dip, 6, "cardbus_free_bridge_resources\n"); 21913db86aabSstevel 21923db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 21933db86aabSstevel DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges, 21943db86aabSstevel &length) == DDI_PROP_SUCCESS) { 21953db86aabSstevel for (i = 0; i < length / sizeof (cardbus_range_t); i++) { 21963db86aabSstevel if (ranges[i].size_lo != 0 || ranges[i].size_hi != 0) { 21973db86aabSstevel switch (ranges[i].parent_hi & PCI_REG_ADDR_M) { 21983db86aabSstevel case PCI_ADDR_IO: 21993db86aabSstevel cardbus_err(dip, 6, 22003db86aabSstevel "Need to Free I/O " 22013db86aabSstevel "base/length = [0x%x]/[0x%x]\n", 22023db86aabSstevel ranges[i].child_lo, 22033db86aabSstevel ranges[i].size_lo); 22043db86aabSstevel break; 22053db86aabSstevel 22063db86aabSstevel case PCI_ADDR_MEM32: 22073db86aabSstevel case PCI_ADDR_MEM64: 22083db86aabSstevel cardbus_err(dip, 6, 22093db86aabSstevel "Need to Free Memory base/length = " 22103db86aabSstevel "[0x%x.%x]/[0x%x]\n", 22113db86aabSstevel ranges[i].child_mid, 22123db86aabSstevel ranges[i].child_lo, 22133db86aabSstevel ranges[i].size_lo); 22143db86aabSstevel break; 22153db86aabSstevel 22163db86aabSstevel default: 22173db86aabSstevel cardbus_err(dip, 6, 22183db86aabSstevel "Unknown memory space\n"); 22193db86aabSstevel break; 22203db86aabSstevel } 22213db86aabSstevel } 22223db86aabSstevel } 22233db86aabSstevel 22243db86aabSstevel kmem_free(ranges, length); 22253db86aabSstevel (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "ranges"); 22263db86aabSstevel } else { 22273db86aabSstevel cardbus_err(dip, 8, 22283db86aabSstevel "cardbus_free_bridge_resources: Failed" 22293db86aabSstevel "to read ranges property\n"); 22303db86aabSstevel } 22313db86aabSstevel 22323db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 22333db86aabSstevel DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus, 22343db86aabSstevel &k) != DDI_PROP_SUCCESS) { 22353db86aabSstevel cardbus_err(dip, 6, "Failed to read bus-range property\n"); 22363db86aabSstevel return (PCICFG_FAILURE); 22373db86aabSstevel } 22383db86aabSstevel 22393db86aabSstevel cardbus_err(dip, 6, 22403db86aabSstevel "Need to free bus [%d] range [%d]\n", 22413db86aabSstevel bus[0], bus[1] - bus[0] + 1); 2242d577a050Syx209050 kmem_free(bus, k); 22433db86aabSstevel (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "available"); 22443db86aabSstevel (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "bus-range"); 22453db86aabSstevel 22463db86aabSstevel return (PCICFG_SUCCESS); 22473db86aabSstevel } 22483db86aabSstevel 22493db86aabSstevel static int 22503db86aabSstevel cardbus_free_device_resources(dev_info_t *dip) 22513db86aabSstevel { 22523db86aabSstevel pci_regspec_t *assigned; 22533db86aabSstevel 22543db86aabSstevel int length; 22553db86aabSstevel int acount; 22563db86aabSstevel int i; 22573db86aabSstevel 22583db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 22593db86aabSstevel DDI_PROP_DONTPASS, "assigned-addresses", 22603db86aabSstevel (caddr_t)&assigned, 22613db86aabSstevel &length) != DDI_PROP_SUCCESS) { 22623db86aabSstevel cardbus_err(dip, 1, 22633db86aabSstevel "Failed to read assigned-addresses property\n"); 22643db86aabSstevel return (PCICFG_FAILURE); 22653db86aabSstevel } 22663db86aabSstevel 22673db86aabSstevel /* 22683db86aabSstevel * For each "assigned-addresses" property entry with a length, 22693db86aabSstevel * call the memory allocation routines to return the 22703db86aabSstevel * resource. 22713db86aabSstevel */ 22723db86aabSstevel acount = length / sizeof (pci_regspec_t); 22733db86aabSstevel for (i = 0; i < acount; i++) { 22743db86aabSstevel 22753db86aabSstevel /* 22763db86aabSstevel * Free the resource if the size of it is not zero. 22773db86aabSstevel */ 22783db86aabSstevel if ((assigned[i].pci_size_low != 0)|| 22793db86aabSstevel (assigned[i].pci_size_hi != 0)) { 22803db86aabSstevel switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) { 22813db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_MEM32): 22823db86aabSstevel cardbus_err(dip, 6, 22833db86aabSstevel "Need to return 0x%x of 32 bit MEM space" 22843db86aabSstevel " @ 0x%x from register 0x%x\n", 22853db86aabSstevel assigned[i].pci_size_low, 22863db86aabSstevel assigned[i].pci_phys_low, 22873db86aabSstevel PCI_REG_REG_G(assigned[i].pci_phys_hi)); 22883db86aabSstevel 22893db86aabSstevel break; 22903db86aabSstevel 22913db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_MEM64): 22923db86aabSstevel cardbus_err(dip, 6, 22933db86aabSstevel "Need to return 0x%x of 64 bit MEM space" 22943db86aabSstevel " @ 0x%x.%x from register 0x%x\n", 22953db86aabSstevel assigned[i].pci_size_low, 22963db86aabSstevel assigned[i].pci_phys_mid, 22973db86aabSstevel assigned[i].pci_phys_low, 22983db86aabSstevel PCI_REG_REG_G(assigned[i].pci_phys_hi)); 22993db86aabSstevel 23003db86aabSstevel break; 23013db86aabSstevel 23023db86aabSstevel case PCI_REG_ADDR_G(PCI_ADDR_IO): 23033db86aabSstevel cardbus_err(dip, 6, 23043db86aabSstevel "Need to return 0x%x of IO space @ 0x%x" 23053db86aabSstevel " from register 0x%x\n", 23063db86aabSstevel assigned[i].pci_size_low, 23073db86aabSstevel assigned[i].pci_phys_low, 23083db86aabSstevel PCI_REG_REG_G(assigned[i].pci_phys_hi)); 23093db86aabSstevel break; 23103db86aabSstevel 23113db86aabSstevel default: 23123db86aabSstevel cardbus_err(dip, 1, "Unknown register type\n"); 23133db86aabSstevel kmem_free(assigned, length); 23143db86aabSstevel return (PCICFG_FAILURE); 23153db86aabSstevel } /* switch */ 23163db86aabSstevel } 23173db86aabSstevel } 23183db86aabSstevel kmem_free(assigned, length); 23193db86aabSstevel return (PCICFG_SUCCESS); 23203db86aabSstevel } 23213db86aabSstevel 23223db86aabSstevel static int 23233db86aabSstevel cardbus_free_resources(dev_info_t *dip) 23243db86aabSstevel { 23253db86aabSstevel uint32_t classcode; 23263db86aabSstevel 23273db86aabSstevel classcode = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 23283db86aabSstevel "class-code", -1); 23293db86aabSstevel /* 23303db86aabSstevel * A different algorithim is used for bridges and leaf devices. 23313db86aabSstevel */ 23323db86aabSstevel if (classcode != -1) { 23333db86aabSstevel classcode = ((uint_t)classcode & 0xffff00) >> 8; 23343db86aabSstevel if (classcode == 0x604 || classcode == 0x607) { 23353db86aabSstevel if (cardbus_free_bridge_resources(dip) 23363db86aabSstevel != PCICFG_SUCCESS) { 23373db86aabSstevel cardbus_err(dip, 1, 23383db86aabSstevel "Failed freeing up bridge resources\n"); 23393db86aabSstevel return (PCICFG_FAILURE); 23403db86aabSstevel } 23413db86aabSstevel return (PCICFG_SUCCESS); 23423db86aabSstevel } 23433db86aabSstevel } 23443db86aabSstevel 23453db86aabSstevel if (cardbus_free_device_resources(dip) != PCICFG_SUCCESS) { 23463db86aabSstevel cardbus_err(dip, 1, "Failed freeing up device resources\n"); 23473db86aabSstevel return (PCICFG_FAILURE); 23483db86aabSstevel } 23493db86aabSstevel return (PCICFG_SUCCESS); 23503db86aabSstevel } 23513db86aabSstevel 23523db86aabSstevel static int 23533db86aabSstevel cardbus_probe_bridge(cbus_t *cbp, dev_info_t *attpt, uint_t bus, 23543db86aabSstevel uint_t device, uint_t func) 23553db86aabSstevel { 23563db86aabSstevel /* Declairations */ 23573db86aabSstevel cardbus_bus_range_t *bus_range; 23583db86aabSstevel int i, j; 23593db86aabSstevel uint8_t header_type; 23603db86aabSstevel ddi_acc_handle_t config_handle; 23613db86aabSstevel ndi_ra_request_t req; 23623db86aabSstevel uint_t new_bus; 23633db86aabSstevel uint64_t blen; 23643db86aabSstevel uint64_t next_bus; 23653db86aabSstevel int circ; 23663db86aabSstevel 23673db86aabSstevel cardbus_err(cbp->cb_dip, 6, 23683db86aabSstevel "cardbus_probe_bridge bus %d device %d func %d\n", 23693db86aabSstevel bus, device, func); 23703db86aabSstevel 23713db86aabSstevel ndi_devi_enter(cbp->cb_dip, &circ); 23723db86aabSstevel if (pci_config_setup(cbp->cb_dip, &config_handle) != DDI_SUCCESS) { 23733db86aabSstevel 23743db86aabSstevel cardbus_err(cbp->cb_dip, 1, 23753db86aabSstevel "cardbus_probe_bridge(): Failed to setup config space\n"); 23763db86aabSstevel 23773db86aabSstevel ndi_devi_exit(cbp->cb_dip, circ); 23783db86aabSstevel return (PCICFG_FAILURE); 23793db86aabSstevel } 23803db86aabSstevel 23813db86aabSstevel header_type = pci_config_get8(config_handle, PCI_CONF_HEADER); 23823db86aabSstevel 23833db86aabSstevel /* 23843db86aabSstevel * As soon as we have access to config space, check device 23853db86aabSstevel * is a bridge. 23863db86aabSstevel */ 23873db86aabSstevel if ((header_type & PCI_HEADER_TYPE_M) != PCI_HEADER_CARDBUS) 23883db86aabSstevel goto failed; 23893db86aabSstevel 23903db86aabSstevel cardbus_err(cbp->cb_dip, 8, 23913db86aabSstevel "---Vendor ID = [0x%04x]\n", 23923db86aabSstevel pci_config_get16(config_handle, PCI_CONF_VENID)); 23933db86aabSstevel cardbus_err(cbp->cb_dip, 8, 23943db86aabSstevel "---Device ID = [0x%04x]\n", 23953db86aabSstevel pci_config_get16(config_handle, PCI_CONF_DEVID)); 23963db86aabSstevel 23973db86aabSstevel /* say what type of header */ 23983db86aabSstevel cardbus_err(cbp->cb_dip, 8, 23993db86aabSstevel "--%s bridge found root bus [0x%x] device [0x%x] func [0x%x]\n", 24003db86aabSstevel ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) ? 24013db86aabSstevel "PCI-PCI" : "Cardbus", 24023db86aabSstevel bus, device, func); 24033db86aabSstevel 24043db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, cbp->cb_dip, 0, "bus-range", 24053db86aabSstevel (caddr_t)&bus_range, &i) != DDI_PROP_SUCCESS) 24063db86aabSstevel cardbus_err(cbp->cb_dip, 1, 24073db86aabSstevel "No bus-range property seems to have been set up\n"); 24083db86aabSstevel else { 24093db86aabSstevel cardbus_err(cbp->cb_dip, 8, 24103db86aabSstevel "allowable bus range is %u->%u\n", 24113db86aabSstevel bus_range->lo, bus_range->hi); 24123db86aabSstevel kmem_free((caddr_t)bus_range, i); 24133db86aabSstevel } 24143db86aabSstevel 24153db86aabSstevel /* 24163db86aabSstevel * Get next bus in sequence and program device. 24173db86aabSstevel */ 24183db86aabSstevel bzero((caddr_t)&req, sizeof (ndi_ra_request_t)); 24193db86aabSstevel req.ra_len = 1; 24203db86aabSstevel 24213db86aabSstevel if (ndi_ra_alloc(cbp->cb_dip, &req, 24223db86aabSstevel &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM, 24233db86aabSstevel NDI_RA_PASS) != NDI_SUCCESS) { 24240d282d13Srw148561 cmn_err(CE_WARN, "Failed to get a bus number\n"); 24253db86aabSstevel goto failed; 24263db86aabSstevel } 24273db86aabSstevel 24283db86aabSstevel new_bus = next_bus; 24293db86aabSstevel cardbus_err(cbp->cb_dip, 8, 24303db86aabSstevel "NEW bus found [%u]->[%u]\n", bus, new_bus); 24313db86aabSstevel 24323db86aabSstevel (void) cardbus_set_bus_numbers(config_handle, bus, new_bus); 24333db86aabSstevel 24343db86aabSstevel /* Enable it all */ 24353db86aabSstevel enable_cardbus_bridge(cbp->cb_dip, config_handle); 24363db86aabSstevel 24373db86aabSstevel /* 24383db86aabSstevel * Probe all children devices 24393db86aabSstevel */ 24403db86aabSstevel for (i = 0; i < pcicfg_max_device; i++) 24413db86aabSstevel for (j = 0; j < pcicfg_max_function; j++) 24423db86aabSstevel switch (cardbus_probe_children(cbp, attpt, new_bus, i, 24433db86aabSstevel j, &header_type)) { 24443db86aabSstevel 24453db86aabSstevel case PCICFG_FAILURE: 24463db86aabSstevel cardbus_err(cbp->cb_dip, 1, 24473db86aabSstevel "Failed to configure bus " 24483db86aabSstevel "[0x%x] device [0x%x] func [0x%x]\n", 24493db86aabSstevel new_bus, i, j); 24503db86aabSstevel disable_cardbus_bridge(cbp->cb_dip, 24513db86aabSstevel config_handle); 24523db86aabSstevel goto failed; 24533db86aabSstevel 24543db86aabSstevel case PCICFG_NODEVICE: 24553db86aabSstevel /* 24563db86aabSstevel * if there's no function 0 24573db86aabSstevel * there's no point in probing other 24583db86aabSstevel * functions 24593db86aabSstevel */ 24603db86aabSstevel if (j != 0) 24613db86aabSstevel break; 24623db86aabSstevel /* FALLTHROUGH */ 24633db86aabSstevel case PCICFG_NOMULTI: 24643db86aabSstevel j = pcicfg_max_function; 24653db86aabSstevel break; 24663db86aabSstevel 24673db86aabSstevel default: 24683db86aabSstevel break; 24693db86aabSstevel } 24703db86aabSstevel 24713db86aabSstevel (void) pci_config_teardown(&config_handle); 24723db86aabSstevel (void) i_ndi_config_node(attpt, DS_LINKED, 0); 24733db86aabSstevel ndi_devi_exit(cbp->cb_dip, circ); 24743db86aabSstevel 24753db86aabSstevel return (PCICFG_SUCCESS); 24763db86aabSstevel 24773db86aabSstevel failed: 24783db86aabSstevel (void) pci_config_teardown(&config_handle); 24793db86aabSstevel ndi_devi_exit(cbp->cb_dip, circ); 24803db86aabSstevel 24813db86aabSstevel return (PCICFG_FAILURE); 24823db86aabSstevel } 24833db86aabSstevel 24843db86aabSstevel static struct isa_node isa_nodes[] = { 24853db86aabSstevel {"dummy", {NULL, NULL, NULL, NULL, NULL}, "serial", "", 0x4e, 0x2} 24863db86aabSstevel }; 24873db86aabSstevel 24883db86aabSstevel static int 24893db86aabSstevel cardbus_probe_children(cbus_t *cbp, dev_info_t *parent, uint_t bus, 24903db86aabSstevel uint_t device, uint_t func, uint8_t *header_type) 24913db86aabSstevel { 24923db86aabSstevel dev_info_t *new_child; 24933db86aabSstevel ddi_acc_handle_t config_handle; 24943db86aabSstevel int i, j; 24953db86aabSstevel ndi_ra_request_t req; 24963db86aabSstevel uint64_t next_bus; 24973db86aabSstevel uint64_t blen; 24983db86aabSstevel uint32_t request; 24993db86aabSstevel uint8_t base_class; 25003db86aabSstevel uint_t new_bus; 25013db86aabSstevel int ret; 25023db86aabSstevel int circ; 25033db86aabSstevel 25043db86aabSstevel cardbus_err(parent, 6, 25053db86aabSstevel "cardbus_probe_children bus %d device %d func %d\n", 25063db86aabSstevel bus, device, func); 25073db86aabSstevel 25083db86aabSstevel /* 25093db86aabSstevel * This node will be put immediately below 25103db86aabSstevel * "parent". Allocate a blank device node. It will either 25113db86aabSstevel * be filled in or freed up based on further probing. 25123db86aabSstevel */ 25133db86aabSstevel 25143db86aabSstevel ndi_devi_enter(parent, &circ); 25153db86aabSstevel 25163db86aabSstevel if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME, 25173db86aabSstevel (pnode_t)DEVI_SID_NODEID, 25183db86aabSstevel &new_child) != NDI_SUCCESS) { 25193db86aabSstevel cardbus_err(parent, 1, 25203db86aabSstevel "cardbus_probe_children(): Failed to alloc child node\n"); 25213db86aabSstevel ndi_devi_exit(parent, circ); 25223db86aabSstevel return (PCICFG_FAILURE); 25233db86aabSstevel } 25243db86aabSstevel 25253db86aabSstevel if (cardbus_add_config_reg(new_child, bus, 25263db86aabSstevel device, func) != DDI_SUCCESS) { 25273db86aabSstevel cardbus_err(parent, 1, 25283db86aabSstevel "cardbus_probe_children(): Failed to add candidate REG\n"); 25293db86aabSstevel goto failedconfig; 25303db86aabSstevel } 25313db86aabSstevel 25323db86aabSstevel if ((ret = cardbus_config_setup(new_child, &config_handle)) 25333db86aabSstevel != PCICFG_SUCCESS) { 25343db86aabSstevel 25353db86aabSstevel if (ret == PCICFG_NODEVICE) { 25363db86aabSstevel (void) ndi_devi_free(new_child); 25373db86aabSstevel return (ret); 25383db86aabSstevel } 25393db86aabSstevel cardbus_err(parent, 1, 25403db86aabSstevel "cardbus_probe_children(): Failed to setup config space\n"); 25413db86aabSstevel 25423db86aabSstevel goto failedconfig; 25433db86aabSstevel } 25443db86aabSstevel 25453db86aabSstevel base_class = pci_config_get8(config_handle, PCI_CONF_BASCLASS); 25463db86aabSstevel 25473db86aabSstevel if (func == 0) { 25483db86aabSstevel /* 25493db86aabSstevel * Preserve the header type from function 0. 25503db86aabSstevel * Additional functions may not preserve the PCI_HEADER_MULTI 25513db86aabSstevel * bit. 25523db86aabSstevel */ 25533db86aabSstevel *header_type = pci_config_get8(config_handle, PCI_CONF_HEADER); 25543db86aabSstevel } else if (!(*header_type & PCI_HEADER_MULTI) || 25553db86aabSstevel ((*header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) || 25563db86aabSstevel (base_class == PCI_CLASS_BRIDGE)) { 25573db86aabSstevel 25583db86aabSstevel (void) cardbus_config_teardown(&config_handle); 25593db86aabSstevel (void) ndi_devi_free(new_child); 25603db86aabSstevel return (PCICFG_NOMULTI); 25613db86aabSstevel } 25623db86aabSstevel 25633db86aabSstevel /* 25643db86aabSstevel * As soon as we have access to config space, 25653db86aabSstevel * turn off device. It will get turned on 25663db86aabSstevel * later (after memory is assigned). 25673db86aabSstevel * not if it's a cardbus device. It may be OK to leave 25683db86aabSstevel * it on - try LATER 25693db86aabSstevel */ 25703db86aabSstevel disable_cardbus_device(config_handle); 25713db86aabSstevel 25723db86aabSstevel /* 25733db86aabSstevel * Set 1275 properties common to all devices 25743db86aabSstevel */ 25753db86aabSstevel if (cardbus_set_standard_props(parent, new_child, 25763db86aabSstevel config_handle) != PCICFG_SUCCESS) { 25773db86aabSstevel cardbus_err(parent, 1, "Failed to set standard properties\n"); 25783db86aabSstevel goto failedchild; 25793db86aabSstevel } 25803db86aabSstevel 25813db86aabSstevel /* 25823db86aabSstevel * Child node properties NOTE: Both for PCI-PCI bridge and child node 25833db86aabSstevel */ 25843db86aabSstevel if (cardbus_set_childnode_props(new_child, 25853db86aabSstevel config_handle) != PCICFG_SUCCESS) { 25863db86aabSstevel goto failedchild; 25873db86aabSstevel } 25883db86aabSstevel 25893db86aabSstevel cardbus_err(parent, 8, 25903db86aabSstevel "---Vendor ID = [0x%04x]\n", 25913db86aabSstevel pci_config_get16(config_handle, PCI_CONF_VENID)); 25923db86aabSstevel cardbus_err(parent, 8, 25933db86aabSstevel "---Device ID = [0x%04x]\n", 25943db86aabSstevel pci_config_get16(config_handle, PCI_CONF_DEVID)); 25953db86aabSstevel 25963db86aabSstevel if (base_class == PCI_CLASS_BRIDGE) { 25973db86aabSstevel uint8_t sub_class; 25983db86aabSstevel 25993db86aabSstevel sub_class = pci_config_get8(config_handle, PCI_CONF_SUBCLASS); 26003db86aabSstevel 26013db86aabSstevel switch (sub_class) { 26023db86aabSstevel case PCI_BRIDGE_PCI: 26033db86aabSstevel if ((*header_type & PCI_HEADER_TYPE_M) 26043db86aabSstevel == PCI_HEADER_PPB) { 26053db86aabSstevel cardbus_bus_range_t *bus_range; 26063db86aabSstevel int k; 26073db86aabSstevel 26083db86aabSstevel /* say what type of header */ 26093db86aabSstevel cardbus_err(parent, 8, 26103db86aabSstevel "-- Found PCI-PCI bridge @ " 26113db86aabSstevel " bus [0x%x] device [0x%x] func [0x%x]\n", 26123db86aabSstevel bus, device, func); 26133db86aabSstevel 26143db86aabSstevel if (ddi_getlongprop(DDI_DEV_T_ANY, 26153db86aabSstevel new_child, 0, "bus-range", 26163db86aabSstevel (caddr_t)&bus_range, 26173db86aabSstevel &k) != DDI_PROP_SUCCESS) 26183db86aabSstevel cardbus_err(new_child, 1, 26193db86aabSstevel "No bus-range property" 26203db86aabSstevel " seems to have been set up\n"); 26213db86aabSstevel else { 26223db86aabSstevel cardbus_err(new_child, 8, 26233db86aabSstevel "allowable bus range is %u->%u\n", 26243db86aabSstevel bus_range->lo, bus_range->hi); 26253db86aabSstevel kmem_free((caddr_t)bus_range, k); 26263db86aabSstevel } 26273db86aabSstevel 26283db86aabSstevel /* 26293db86aabSstevel * Get next bus in sequence and program device. 26303db86aabSstevel */ 26313db86aabSstevel bzero((caddr_t)&req, sizeof (ndi_ra_request_t)); 26323db86aabSstevel req.ra_len = 1; 26333db86aabSstevel 26343db86aabSstevel if (ndi_ra_alloc(new_child, &req, 26353db86aabSstevel &next_bus, &blen, 26363db86aabSstevel NDI_RA_TYPE_PCI_BUSNUM, 26373db86aabSstevel NDI_RA_PASS) != NDI_SUCCESS) { 26380d282d13Srw148561 cmn_err(CE_WARN, 26393db86aabSstevel "Failed to get a bus number\n"); 26403db86aabSstevel goto failedchild; 26413db86aabSstevel } 26423db86aabSstevel 26433db86aabSstevel new_bus = next_bus; 26443db86aabSstevel 26453db86aabSstevel cardbus_err(new_child, 8, 26463db86aabSstevel "NEW bus found [%u]->[%u]\n", bus, new_bus); 26473db86aabSstevel 26483db86aabSstevel /* Enable it all */ 26493db86aabSstevel enable_pci_pci_bridge(new_child, config_handle); 26503db86aabSstevel (void) cardbus_set_bus_numbers(config_handle, 26513db86aabSstevel bus, new_bus); 26523db86aabSstevel 26533db86aabSstevel #if defined(CARDBUS_DEBUG) 26543db86aabSstevel if (cardbus_debug >= 9) { 26553db86aabSstevel cardbus_dump_config(config_handle); 26563db86aabSstevel } 26573db86aabSstevel #endif 26583db86aabSstevel 26593db86aabSstevel /* 26603db86aabSstevel * Set bus properties 26613db86aabSstevel */ 26623db86aabSstevel if (cardbus_set_busnode_props(new_child) 26633db86aabSstevel != PCICFG_SUCCESS) { 26643db86aabSstevel cardbus_err(new_child, 1, 26653db86aabSstevel "Failed to set busnode props\n"); 26663db86aabSstevel disable_pci_pci_bridge(new_child, 26673db86aabSstevel config_handle); 26683db86aabSstevel goto failedchild; 26693db86aabSstevel } 26703db86aabSstevel 26713db86aabSstevel /* 26723db86aabSstevel * Probe all children devices 26733db86aabSstevel */ 26743db86aabSstevel for (i = 0; i < pcicfg_max_device; i++) 26753db86aabSstevel for (j = 0; j < pcicfg_max_function; 26763db86aabSstevel j++) 26773db86aabSstevel switch (cardbus_probe_children( 26783db86aabSstevel cbp, 26793db86aabSstevel new_child, 26803db86aabSstevel new_bus, i, 26813db86aabSstevel j, header_type)) { 26823db86aabSstevel case PCICFG_FAILURE: 26833db86aabSstevel cardbus_err(parent, 1, 26843db86aabSstevel "Failed to " 26853db86aabSstevel "configure " 26863db86aabSstevel "bus [0x%x] " 26873db86aabSstevel "device [0x%x] " 26883db86aabSstevel "func [0x%x]\n", 26893db86aabSstevel new_bus, i, j); 26903db86aabSstevel disable_pci_pci_bridge( 26913db86aabSstevel new_child, 26923db86aabSstevel config_handle); 26933db86aabSstevel goto failedchild; 26943db86aabSstevel 26953db86aabSstevel case PCICFG_NODEVICE: 26963db86aabSstevel /* 26973db86aabSstevel * if there's no 26983db86aabSstevel * function 0 26993db86aabSstevel * there's no point in 27003db86aabSstevel * probing other 27013db86aabSstevel * functions 27023db86aabSstevel */ 27033db86aabSstevel if (j != 0) 27043db86aabSstevel break; 27053db86aabSstevel /* FALLTHROUGH */ 27063db86aabSstevel case PCICFG_NOMULTI: 27073db86aabSstevel j = pcicfg_max_function; 27083db86aabSstevel break; 27093db86aabSstevel 27103db86aabSstevel default: 27113db86aabSstevel break; 27123db86aabSstevel } 27133db86aabSstevel } 27143db86aabSstevel break; 27153db86aabSstevel 27163db86aabSstevel case PCI_BRIDGE_CARDBUS: 27173db86aabSstevel cardbus_err(parent, 8, 27183db86aabSstevel "--Found Cardbus bridge @ " 27193db86aabSstevel "bus [0x%x] device [0x%x] func [0x%x]\n", 27203db86aabSstevel bus, device, func); 27213db86aabSstevel pci_config_put32(config_handle, 27223db86aabSstevel PCI_CONF_BASE0, 0xffffffff); 27233db86aabSstevel 27243db86aabSstevel request = pci_config_get32(config_handle, 27253db86aabSstevel PCI_CONF_BASE0); 27263db86aabSstevel 27273db86aabSstevel /* 27283db86aabSstevel * If its a zero length, don't do 27293db86aabSstevel * any programming. 27303db86aabSstevel */ 27313db86aabSstevel if (request != 0) { 27323db86aabSstevel if (request == (uint32_t)0xffffffff) { 27333db86aabSstevel cmn_err(CE_WARN, 27343db86aabSstevel "cardbus_probe_children: " 27353db86aabSstevel "can't access device"); 27363db86aabSstevel goto failedchild; 27373db86aabSstevel } 27383db86aabSstevel /* 27393db86aabSstevel * Add to the "reg" property 27403db86aabSstevel */ 27413db86aabSstevel if (cardbus_update_reg_prop(new_child, 27423db86aabSstevel request, 27433db86aabSstevel PCI_CONF_BASE0) != PCICFG_SUCCESS) { 27443db86aabSstevel goto failedchild; 27453db86aabSstevel } 27463db86aabSstevel cardbus_err(parent, 8, 27473db86aabSstevel "BASE register [0x%x] asks for " 27483db86aabSstevel "[0x%x]=[0x%x](32)\n", 27493db86aabSstevel PCI_CONF_BASE0, request, 27503db86aabSstevel (~(PCI_BASE_M_ADDR_M & request))+1); 27513db86aabSstevel } 27523db86aabSstevel break; 27533db86aabSstevel 27543db86aabSstevel case PCI_BRIDGE_ISA: 27553db86aabSstevel cardbus_err(parent, 8, 27563db86aabSstevel "--Found ISA bridge @ " 27573db86aabSstevel "bus [0x%x] device [0x%x] func [0x%x]\n", 27583db86aabSstevel bus, device, func); 27593db86aabSstevel enable_pci_isa_bridge(new_child, config_handle); 27603db86aabSstevel 27613db86aabSstevel #if defined(CARDBUS_DEBUG) 27623db86aabSstevel if (cardbus_debug >= 4) { 27633db86aabSstevel cardbus_dump_common_config(config_handle); 27643db86aabSstevel cardbus_err(NULL, 1, 27653db86aabSstevel " DDMA SlvCh0 = [0x%04x] " 27663db86aabSstevel "DDMA SlvCh1 = [0x%04x]\n", 27673db86aabSstevel pci_config_get16(config_handle, 0x40), 27683db86aabSstevel pci_config_get16(config_handle, 0x42)); 27693db86aabSstevel cardbus_err(NULL, 1, 27703db86aabSstevel " DDMA SlvCh2 = [0x%04x] " 27713db86aabSstevel "DDMA SlvCh3 = [0x%04x]\n", 27723db86aabSstevel pci_config_get16(config_handle, 0x44), 27733db86aabSstevel pci_config_get16(config_handle, 0x46)); 27743db86aabSstevel cardbus_err(NULL, 1, 27753db86aabSstevel " DDMA SlvCh5 = [0x%04x] " 27763db86aabSstevel "DDMA SlvCh6 = [0x%04x]\n", 27773db86aabSstevel pci_config_get16(config_handle, 0x4a), 27783db86aabSstevel pci_config_get16(config_handle, 0x4c)); 27793db86aabSstevel cardbus_err(NULL, 1, 27803db86aabSstevel " DDMA SlvCh7 = [0x%04x] " 27813db86aabSstevel "Misc Cntrl = [0x%02x]\n", 27823db86aabSstevel pci_config_get16(config_handle, 0x4e), 27833db86aabSstevel pci_config_get8(config_handle, 0x57)); 27843db86aabSstevel cardbus_err(NULL, 1, 27853db86aabSstevel " DMA Cntl = [0x%02x] " 27863db86aabSstevel "DMA TyF Tim = [0x%02x]\n", 27873db86aabSstevel pci_config_get8(config_handle, 0x48), 27883db86aabSstevel pci_config_get8(config_handle, 0x49)); 27893db86aabSstevel cardbus_err(NULL, 1, 27903db86aabSstevel " TimCntrl = [0x%02x] " 27913db86aabSstevel "MTOP = [0x%02x]\n", 27923db86aabSstevel pci_config_get8(config_handle, 0x50), 27933db86aabSstevel pci_config_get8(config_handle, 0x51)); 27943db86aabSstevel cardbus_err(NULL, 1, 27953db86aabSstevel " MDMA Access = [0x%02x] " 27963db86aabSstevel "ROMCS = [0x%02x]\n", 27973db86aabSstevel pci_config_get8(config_handle, 0x52), 27983db86aabSstevel pci_config_get8(config_handle, 0x53)); 27993db86aabSstevel cardbus_err(NULL, 1, 28003db86aabSstevel " Dscrd Tmr = [0x%02x] " 28013db86aabSstevel "Retry Tmr = [0x%02x]\n", 28023db86aabSstevel pci_config_get8(config_handle, 0x55), 28033db86aabSstevel pci_config_get8(config_handle, 0x54)); 28043db86aabSstevel cardbus_err(NULL, 1, 28053db86aabSstevel " I/O Spc 0 = [0x%08x] " 28063db86aabSstevel "I/O Spc 1 = [0x%08x]\n", 28073db86aabSstevel pci_config_get32(config_handle, 0x58), 28083db86aabSstevel pci_config_get32(config_handle, 0x5c)); 28093db86aabSstevel cardbus_err(NULL, 1, 28103db86aabSstevel " I/O Spc 2 = [0x%08x] " 28113db86aabSstevel "I/O Spc 3 = [0x%08x]\n", 28123db86aabSstevel pci_config_get32(config_handle, 0x60), 28133db86aabSstevel pci_config_get32(config_handle, 0x64)); 28143db86aabSstevel cardbus_err(NULL, 1, 28153db86aabSstevel " I/O Spc 4 = [0x%08x] " 28163db86aabSstevel "I/O Spc 5 = [0x%08x]\n", 28173db86aabSstevel pci_config_get32(config_handle, 0x68), 28183db86aabSstevel pci_config_get32(config_handle, 0x6c)); 28193db86aabSstevel cardbus_err(NULL, 1, 28203db86aabSstevel " Mem Spc 0 = [0x%08x] " 28213db86aabSstevel "Mem Spc 1 = [0x%08x]\n", 28223db86aabSstevel pci_config_get32(config_handle, 0x70), 28233db86aabSstevel pci_config_get32(config_handle, 0x74)); 28243db86aabSstevel cardbus_err(NULL, 1, 28253db86aabSstevel " Mem Spc 2 = [0x%08x] " 28263db86aabSstevel "Mem Spc 3 = [0x%08x]\n", 28273db86aabSstevel pci_config_get32(config_handle, 0x78), 28283db86aabSstevel pci_config_get32(config_handle, 0x7c)); 28293db86aabSstevel } 28303db86aabSstevel #endif 28313db86aabSstevel /* 28323db86aabSstevel * Set bus properties 28333db86aabSstevel */ 28343db86aabSstevel if (cardbus_set_busnode_isaprops(new_child) 28353db86aabSstevel != PCICFG_SUCCESS) { 28363db86aabSstevel cardbus_err(new_child, 1, 28373db86aabSstevel "Failed to set busnode props\n"); 28383db86aabSstevel disable_cardbus_device(config_handle); 28393db86aabSstevel goto failedchild; 28403db86aabSstevel } 28413db86aabSstevel 28423db86aabSstevel /* 28433db86aabSstevel * Add to the "reg" property. 28443db86aabSstevel * Simply grab 1K of I/O space. 28453db86aabSstevel */ 28463db86aabSstevel if (cardbus_update_reg_prop(new_child, 28473db86aabSstevel 0xfffffc00 | PCI_BASE_SPACE_IO, 28483db86aabSstevel PCI_CONF_BASE0) != PCICFG_SUCCESS) { 28493db86aabSstevel goto failedchild; 28503db86aabSstevel } 28513db86aabSstevel 28523db86aabSstevel /* 28533db86aabSstevel * Probe all potential children devices. 28543db86aabSstevel */ 28553db86aabSstevel for (i = 0; 28563db86aabSstevel i < sizeof (isa_nodes) / sizeof (isa_nodes[0]); 28573db86aabSstevel i++) 28583db86aabSstevel switch (cardbus_add_isa_node(cbp, new_child, 28593db86aabSstevel &isa_nodes[i])) { 28603db86aabSstevel case PCICFG_FAILURE: 28613db86aabSstevel cardbus_err(parent, 1, 28623db86aabSstevel "Failed to configure isa bus\n"); 28633db86aabSstevel disable_cardbus_device(config_handle); 28643db86aabSstevel goto failedchild; 28653db86aabSstevel 28663db86aabSstevel case PCICFG_NODEVICE: 28673db86aabSstevel continue; 28683db86aabSstevel } 28693db86aabSstevel 28703db86aabSstevel break; 28713db86aabSstevel 28723db86aabSstevel case PCI_BRIDGE_OTHER: 28733db86aabSstevel default: 28743db86aabSstevel cardbus_err(parent, 8, 28753db86aabSstevel "--Found unknown bridge, subclass 0x%x @ " 28763db86aabSstevel "bus [0x%x] device [0x%x] func [0x%x]\n", 28773db86aabSstevel sub_class, bus, device, func); 28783db86aabSstevel goto leaf_node; 28793db86aabSstevel } 28803db86aabSstevel } else { 28813db86aabSstevel cardbus_err(parent, 8, 28823db86aabSstevel "--Leaf device found " 28833db86aabSstevel "bus [0x%x] device [0x%x] func [0x%x]\n", 28843db86aabSstevel bus, device, func); 28853db86aabSstevel /* 28863db86aabSstevel * Ethernet devices. 28873db86aabSstevel */ 28883db86aabSstevel if (strcmp(ddi_binding_name(new_child), "ethernet") == 0) { 28893db86aabSstevel extern int localetheraddr(struct ether_addr *, 28903db86aabSstevel struct ether_addr *); 28913db86aabSstevel uchar_t mac[6]; 28923db86aabSstevel 28933db86aabSstevel cardbus_force_stringprop(new_child, 28943db86aabSstevel "device_type", "network"); 28953db86aabSstevel 28963db86aabSstevel if (localetheraddr(NULL, (struct ether_addr *)mac)) { 28973db86aabSstevel (void) ddi_prop_create(DDI_DEV_T_NONE, 28983db86aabSstevel new_child, 28993db86aabSstevel DDI_PROP_CANSLEEP, "local-mac-address", 29003db86aabSstevel (caddr_t)mac, 6); 29013db86aabSstevel } 29023db86aabSstevel } 29033db86aabSstevel leaf_node: 29043db86aabSstevel if (cbp->cb_dsp) { 29053db86aabSstevel struct cb_deviceset_props *cdsp = cbp->cb_dsp; 29063db86aabSstevel uint16_t venid = pci_config_get16(config_handle, 29073db86aabSstevel PCI_CONF_VENID); 29083db86aabSstevel uint16_t devid = pci_config_get16(config_handle, 29093db86aabSstevel PCI_CONF_DEVID); 29103db86aabSstevel ddi_prop_t *propp; 29113db86aabSstevel 29123db86aabSstevel for (cdsp = cbp->cb_dsp; cdsp; cdsp = cdsp->next) { 29133db86aabSstevel if (cdsp->binding_name && 29143db86aabSstevel strcmp(ddi_binding_name(new_child), 29153db86aabSstevel cdsp->binding_name)) 29163db86aabSstevel continue; 29173db86aabSstevel if (cdsp->venid && (cdsp->venid != venid)) 29183db86aabSstevel continue; 29193db86aabSstevel if (cdsp->devid && (cdsp->devid != devid)) 29203db86aabSstevel continue; 29213db86aabSstevel if (cdsp->nodename) { 29223db86aabSstevel if (ndi_devi_set_nodename(new_child, 29233db86aabSstevel cdsp->nodename, 29243db86aabSstevel 0) != NDI_SUCCESS) 29253db86aabSstevel cardbus_err(new_child, 1, 29263db86aabSstevel "Failed to set nodename\n"); 29273db86aabSstevel } 29283db86aabSstevel for (propp = cdsp->prop_list; propp; 29293db86aabSstevel propp = propp->prop_next) { 29303db86aabSstevel switch (propp->prop_flags) { 29313db86aabSstevel case DDI_PROP_TYPE_INT: 29323db86aabSstevel cardbus_force_intprop( 29333db86aabSstevel new_child, 29343db86aabSstevel propp->prop_name, 29353db86aabSstevel (int *)propp->prop_val, 29363db86aabSstevel propp->prop_len); 29373db86aabSstevel break; 29383db86aabSstevel case DDI_PROP_TYPE_STRING: 29393db86aabSstevel cardbus_force_stringprop( 29403db86aabSstevel new_child, 29413db86aabSstevel propp->prop_name, 29423db86aabSstevel (char *)propp->prop_val); 29433db86aabSstevel break; 29443db86aabSstevel case DDI_PROP_TYPE_ANY: 29453db86aabSstevel cardbus_force_boolprop( 29463db86aabSstevel new_child, 29473db86aabSstevel propp->prop_name); 29483db86aabSstevel break; 29493db86aabSstevel } 29503db86aabSstevel } 29513db86aabSstevel } 29523db86aabSstevel } 29533db86aabSstevel 29543db86aabSstevel #if defined(CARDBUS_DEBUG) 29553db86aabSstevel if (cardbus_debug >= 9) { 29563db86aabSstevel cardbus_dump_config(config_handle); 29573db86aabSstevel } 29583db86aabSstevel #endif 29593db86aabSstevel 29603db86aabSstevel i = PCI_CONF_BASE0; 29613db86aabSstevel 29623db86aabSstevel while (i <= PCI_CONF_BASE5) { 29633db86aabSstevel pci_config_put32(config_handle, i, 0xffffffff); 29643db86aabSstevel 29653db86aabSstevel request = pci_config_get32(config_handle, i); 29663db86aabSstevel 29673db86aabSstevel /* 29683db86aabSstevel * If its a zero length, don't do 29693db86aabSstevel * any programming. 29703db86aabSstevel */ 29713db86aabSstevel if (request != 0) { 29723db86aabSstevel if (request == (uint32_t)0xffffffff) { 29733db86aabSstevel cmn_err(CE_WARN, 29743db86aabSstevel "cardbus_probe_children: " 29753db86aabSstevel "can't access device"); 29763db86aabSstevel goto failedchild; 29773db86aabSstevel } 29783db86aabSstevel /* 29793db86aabSstevel * Add to the "reg" property 29803db86aabSstevel */ 29813db86aabSstevel if (cardbus_update_reg_prop(new_child, 29823db86aabSstevel request, i) != PCICFG_SUCCESS) { 29833db86aabSstevel goto failedchild; 29843db86aabSstevel } 29853db86aabSstevel } else { 29863db86aabSstevel cardbus_err(parent, 8, "All memory found\n"); 29873db86aabSstevel break; 29883db86aabSstevel } 29893db86aabSstevel 29903db86aabSstevel /* 29913db86aabSstevel * Increment by eight if it is 64 bit address space 29923db86aabSstevel * only if memory space 29933db86aabSstevel */ 29943db86aabSstevel if (((PCI_BASE_TYPE_M & request) 29953db86aabSstevel == PCI_BASE_TYPE_ALL) && 29963db86aabSstevel ((PCI_BASE_SPACE_M & request) 29973db86aabSstevel == PCI_BASE_SPACE_MEM)) { 29983db86aabSstevel cardbus_err(parent, 8, 29993db86aabSstevel "BASE register [0x%x] asks for " 30003db86aabSstevel "[0x%x]=[0x%x] (64)\n", 30013db86aabSstevel i, request, 30023db86aabSstevel (~(PCI_BASE_M_ADDR_M & request))+1); 30033db86aabSstevel i += 8; 30043db86aabSstevel } else { 30053db86aabSstevel cardbus_err(parent, 8, 30063db86aabSstevel "BASE register [0x%x] asks for " 30073db86aabSstevel "[0x%x]=[0x%x](32)\n", 30083db86aabSstevel i, request, 30093db86aabSstevel (~(PCI_BASE_M_ADDR_M & request))+1); 30103db86aabSstevel i += 4; 30113db86aabSstevel } 30123db86aabSstevel } 30133db86aabSstevel 30143db86aabSstevel /* 30153db86aabSstevel * Get the ROM size and create register for it 30163db86aabSstevel */ 30173db86aabSstevel pci_config_put32(config_handle, PCI_CONF_ROM, 0xffffffff); 30183db86aabSstevel 30193db86aabSstevel request = pci_config_get32(config_handle, PCI_CONF_ROM); 30203db86aabSstevel /* 30213db86aabSstevel * If its a zero length, don't do 30223db86aabSstevel * any programming. 30233db86aabSstevel */ 30243db86aabSstevel 30253db86aabSstevel if (request != 0) { 30263db86aabSstevel cardbus_err(parent, 9, 30273db86aabSstevel "BASE register [0x%x] asks for " 30283db86aabSstevel "[0x%x]=[0x%x] (ROM)\n", 30293db86aabSstevel PCI_CONF_ROM, request, 30303db86aabSstevel (~(PCI_BASE_ROM_ADDR_M & request))+1); 30313db86aabSstevel /* 30323db86aabSstevel * Add to the "reg" property 30333db86aabSstevel */ 30343db86aabSstevel if (cardbus_update_reg_prop(new_child, 30353db86aabSstevel request, 30363db86aabSstevel PCI_CONF_ROM) != PCICFG_SUCCESS) { 30373db86aabSstevel goto failedchild; 30383db86aabSstevel } 30393db86aabSstevel } 30403db86aabSstevel } 30413db86aabSstevel 30423db86aabSstevel (void) cardbus_config_teardown(&config_handle); 30433db86aabSstevel 30443db86aabSstevel /* 30453db86aabSstevel * Attach the child to its parent 30463db86aabSstevel */ 30473db86aabSstevel (void) i_ndi_config_node(new_child, DS_LINKED, 0); 30483db86aabSstevel ndi_devi_exit(parent, circ); 30493db86aabSstevel 30503db86aabSstevel return (PCICFG_SUCCESS); 30513db86aabSstevel failedchild: 30523db86aabSstevel /* 30533db86aabSstevel * check if it should be taken offline (if online) 30543db86aabSstevel */ 30553db86aabSstevel (void) cardbus_config_teardown(&config_handle); 30563db86aabSstevel 30573db86aabSstevel failedconfig: 30583db86aabSstevel 30593db86aabSstevel (void) ndi_devi_free(new_child); 30603db86aabSstevel ndi_devi_exit(parent, circ); 30613db86aabSstevel 30623db86aabSstevel return (PCICFG_FAILURE); 30633db86aabSstevel } 30643db86aabSstevel 30653db86aabSstevel static int 30663db86aabSstevel cardbus_add_config_reg(dev_info_t *dip, 30673db86aabSstevel uint_t bus, uint_t device, uint_t func) 30683db86aabSstevel { 30693db86aabSstevel int reg[10] = { PCI_ADDR_CONFIG, 0, 0, 0, 0}; 30703db86aabSstevel 30713db86aabSstevel reg[0] = PCICFG_MAKE_REG_HIGH(bus, device, func, 0); 30723db86aabSstevel 30733db86aabSstevel return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 30743db86aabSstevel "reg", reg, 5)); 30753db86aabSstevel } 30763db86aabSstevel 30773db86aabSstevel static int 30783db86aabSstevel cardbus_add_isa_node(cbus_t *cbp, dev_info_t *parent, struct isa_node *node) 30793db86aabSstevel { 30803db86aabSstevel dev_info_t *new_child; 30813db86aabSstevel int ret; 30823db86aabSstevel uint32_t reg[3]; 30833db86aabSstevel 30843db86aabSstevel _NOTE(ARGUNUSED(cbp)) 30853db86aabSstevel 30863db86aabSstevel cardbus_err(parent, 6, "cardbus_add_isa_node\n"); 30873db86aabSstevel 30883db86aabSstevel /* 30893db86aabSstevel * This node will be put immediately below 30903db86aabSstevel * "parent". Allocate a blank device node. 30913db86aabSstevel */ 30923db86aabSstevel if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME, 30933db86aabSstevel (pnode_t)DEVI_SID_NODEID, 30943db86aabSstevel &new_child) != NDI_SUCCESS) { 30953db86aabSstevel cardbus_err(parent, 1, 30963db86aabSstevel "cardbus_add_isa_child(): Failed to alloc child node\n"); 30973db86aabSstevel return (PCICFG_FAILURE); 30983db86aabSstevel } 30993db86aabSstevel 31003db86aabSstevel /* 31013db86aabSstevel * Set properties common to ISA devices 31023db86aabSstevel */ 31033db86aabSstevel if (cardbus_set_isa_props(parent, new_child, node->name, 31043db86aabSstevel node->compatible) != PCICFG_SUCCESS) { 31053db86aabSstevel cardbus_err(parent, 1, "Failed to set ISA properties\n"); 31063db86aabSstevel goto failed; 31073db86aabSstevel } 31083db86aabSstevel 31093db86aabSstevel cardbus_err(new_child, 8, "--Leaf ISA device\n"); 31103db86aabSstevel 31113db86aabSstevel /* 31123db86aabSstevel * Add the "reg" property. 31133db86aabSstevel */ 31143db86aabSstevel reg[0] = 0; 31153db86aabSstevel reg[1] = node->reg; 31163db86aabSstevel reg[2] = node->span; 31173db86aabSstevel 31183db86aabSstevel ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child, 31193db86aabSstevel "basereg", (int *)reg, 3); 31203db86aabSstevel if (ret != DDI_SUCCESS) 31213db86aabSstevel goto failed; 31223db86aabSstevel 31233db86aabSstevel (void) i_ndi_config_node(new_child, DS_LINKED, 0); 31243db86aabSstevel 31253db86aabSstevel return (PCICFG_SUCCESS); 31263db86aabSstevel 31273db86aabSstevel failed: 31283db86aabSstevel (void) ndi_devi_free(new_child); 31293db86aabSstevel 31303db86aabSstevel return (PCICFG_FAILURE); 31313db86aabSstevel } 31323db86aabSstevel 31333db86aabSstevel static int 31343db86aabSstevel cardbus_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle) 31353db86aabSstevel { 31363db86aabSstevel caddr_t cfgaddr; 31373db86aabSstevel ddi_device_acc_attr_t attr; 31383db86aabSstevel dev_info_t *anode; 31393db86aabSstevel int status; 31403db86aabSstevel int rlen; 31413db86aabSstevel pci_regspec_t *reg; 31423db86aabSstevel int ret; 31433db86aabSstevel #ifdef sparc 31443db86aabSstevel int16_t val; 31453db86aabSstevel #endif 31463db86aabSstevel 31473db86aabSstevel cardbus_err(dip, 10, 31483db86aabSstevel "cardbus_config_setup(dip=0x%p)\n", (void *) dip); 31493db86aabSstevel 31503db86aabSstevel /* 31513db86aabSstevel * Get the pci register spec from the node 31523db86aabSstevel */ 31533db86aabSstevel status = ddi_getlongprop(DDI_DEV_T_NONE, 31543db86aabSstevel dip, DDI_PROP_DONTPASS, "reg", 31553db86aabSstevel (caddr_t)®, &rlen); 31563db86aabSstevel 31573db86aabSstevel cardbus_err(dip, 10, 31583db86aabSstevel "cardbus_config_setup, reg = 0x%p\n", (void *) reg); 31593db86aabSstevel 31603db86aabSstevel switch (status) { 31613db86aabSstevel case DDI_PROP_SUCCESS: 31623db86aabSstevel break; 31633db86aabSstevel case DDI_PROP_NO_MEMORY: 31643db86aabSstevel cardbus_err(dip, 1, "reg present, but unable to get memory\n"); 31653db86aabSstevel return (PCICFG_FAILURE); 31663db86aabSstevel default: 31673db86aabSstevel cardbus_err(dip, 1, "no reg property\n"); 31683db86aabSstevel return (PCICFG_FAILURE); 31693db86aabSstevel } 31703db86aabSstevel 31713db86aabSstevel anode = dip; 31723db86aabSstevel 31733db86aabSstevel /* 31743db86aabSstevel * Find the attachment point node 31753db86aabSstevel */ 31763db86aabSstevel while ((anode != NULL) && (strcmp(ddi_binding_name(anode), 31773db86aabSstevel "hp_attachment") != 0)) { 31783db86aabSstevel anode = ddi_get_parent(anode); 31793db86aabSstevel } 31803db86aabSstevel 31813db86aabSstevel if (anode == NULL) { 31823db86aabSstevel cardbus_err(dip, 1, "Tree not in PROBE state\n"); 31833db86aabSstevel kmem_free((caddr_t)reg, rlen); 31843db86aabSstevel return (PCICFG_FAILURE); 31853db86aabSstevel } 31863db86aabSstevel 31873db86aabSstevel if ((ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, anode, 31883db86aabSstevel "reg", (int *)reg, 5)) != 0) { 31893db86aabSstevel cardbus_err(dip, 1, 31903db86aabSstevel "Failed to update reg property, error code %d\n", ret); 31913db86aabSstevel kmem_free((caddr_t)reg, rlen); 31923db86aabSstevel return (PCICFG_FAILURE); 31933db86aabSstevel } 31943db86aabSstevel 31953db86aabSstevel attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 31963db86aabSstevel attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 31973db86aabSstevel attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 31983db86aabSstevel 31993db86aabSstevel if (ddi_regs_map_setup(anode, 0, &cfgaddr, 32003db86aabSstevel 0, /* PCI_CONF_HDR_SIZE */ 32013db86aabSstevel 0, 32023db86aabSstevel &attr, handle) != DDI_SUCCESS) { 32033db86aabSstevel cardbus_err(dip, 1, 32043db86aabSstevel "Failed to setup registers for [0x%x][0x%x][0x%x]\n", 32053db86aabSstevel PCI_REG_BUS_G(reg->pci_phys_hi), 32063db86aabSstevel PCI_REG_DEV_G(reg->pci_phys_hi), 32073db86aabSstevel PCI_REG_FUNC_G(reg->pci_phys_hi)); 32083db86aabSstevel kmem_free((caddr_t)reg, rlen); 32093db86aabSstevel return (PCICFG_FAILURE); 32103db86aabSstevel } 32113db86aabSstevel 32123db86aabSstevel cardbus_err(dip, 9, 32133db86aabSstevel "PROBING =>->->->->->-> [0x%x][0x%x][0x%x] 0x%x 0x%p\n", 32143db86aabSstevel PCI_REG_BUS_G(reg->pci_phys_hi), 32153db86aabSstevel PCI_REG_DEV_G(reg->pci_phys_hi), 32163db86aabSstevel PCI_REG_FUNC_G(reg->pci_phys_hi), 32173db86aabSstevel reg->pci_phys_hi, (void *) cfgaddr); 32183db86aabSstevel 32193db86aabSstevel /* 32203db86aabSstevel * must do peek16 otherwise the system crashes when probing 32213db86aabSstevel * a non zero function on a non-multi-function card. 32223db86aabSstevel */ 32233db86aabSstevel #ifdef sparc 32243db86aabSstevel if (ddi_peek16(anode, (int16_t *)cfgaddr, &val) != DDI_SUCCESS) { 32253db86aabSstevel cardbus_err(dip, 8, 32263db86aabSstevel "cardbus_config_setup peek failed\n"); 32273db86aabSstevel ret = PCICFG_NODEVICE; 32283db86aabSstevel } else if (ddi_get16(*handle, (uint16_t *)cfgaddr) == 0xffff) { 32293db86aabSstevel cardbus_err(dip, 8, 32303db86aabSstevel "cardbus_config_setup PCICFG_NODEVICE\n"); 32313db86aabSstevel ret = PCICFG_NODEVICE; 32323db86aabSstevel #elif defined(__x86) || defined(__amd64) 32333db86aabSstevel if (ddi_get16(*handle, (uint16_t *)cfgaddr) == 0xffff) { 32343db86aabSstevel cardbus_err(dip, 8, 32353db86aabSstevel "cardbus_config_setup PCICFG_NODEVICE\n"); 32363db86aabSstevel ret = PCICFG_NODEVICE; 32373db86aabSstevel #endif 32383db86aabSstevel } else { 32393db86aabSstevel cardbus_err(dip, 1, 32403db86aabSstevel "cardbus_config_setup found device at:[0x%x][0x%x][0x%x]\n", 32413db86aabSstevel PCI_REG_BUS_G(reg->pci_phys_hi), 32423db86aabSstevel PCI_REG_DEV_G(reg->pci_phys_hi), 32433db86aabSstevel PCI_REG_FUNC_G(reg->pci_phys_hi)); 32443db86aabSstevel 32453db86aabSstevel ret = PCICFG_SUCCESS; 32463db86aabSstevel } 32473db86aabSstevel 32483db86aabSstevel kmem_free((caddr_t)reg, rlen); 32493db86aabSstevel if (ret != PCICFG_SUCCESS) { 32503db86aabSstevel cardbus_config_teardown(handle); 32513db86aabSstevel } 32523db86aabSstevel 32533db86aabSstevel cardbus_err(dip, 7, 32543db86aabSstevel "cardbus_config_setup returning %d\n", ret); 32553db86aabSstevel 32563db86aabSstevel return (ret); 32573db86aabSstevel } 32583db86aabSstevel 32593db86aabSstevel static void 32603db86aabSstevel cardbus_config_teardown(ddi_acc_handle_t *handle) 32613db86aabSstevel { 32623db86aabSstevel (void) ddi_regs_map_free(handle); 32633db86aabSstevel } 32643db86aabSstevel 32653db86aabSstevel static void 32663db86aabSstevel cardbus_reparent_children(dev_info_t *dip, dev_info_t *parent) 32673db86aabSstevel { 32683db86aabSstevel dev_info_t *child; 32693db86aabSstevel int circ; 32703db86aabSstevel 32713db86aabSstevel while (child = ddi_get_child(dip)) { 32723db86aabSstevel ASSERT(i_ddi_node_state(child) <= DS_LINKED); 32733db86aabSstevel /* 32743db86aabSstevel * Unlink node from tree before reparenting 32753db86aabSstevel */ 32763db86aabSstevel ndi_devi_enter(dip, &circ); 32773db86aabSstevel (void) i_ndi_unconfig_node(child, DS_PROTO, 0); 32783db86aabSstevel ndi_devi_exit(dip, circ); 32793db86aabSstevel DEVI(child)->devi_parent = DEVI(parent); 32803db86aabSstevel DEVI(child)->devi_bus_ctl = DEVI(parent); 32813db86aabSstevel ndi_devi_enter(parent, &circ); 32823db86aabSstevel (void) i_ndi_config_node(child, DS_LINKED, 0); 32833db86aabSstevel ndi_devi_exit(parent, circ); 32843db86aabSstevel } 32853db86aabSstevel } 32863db86aabSstevel 32873db86aabSstevel static int 32883db86aabSstevel cardbus_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone) 32893db86aabSstevel { 32903db86aabSstevel int alen; 32913db86aabSstevel pci_regspec_t *assigned; 32923db86aabSstevel caddr_t newreg; 32933db86aabSstevel uint_t status; 32943db86aabSstevel 32953db86aabSstevel status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 32963db86aabSstevel "assigned-addresses", (caddr_t)&assigned, &alen); 32973db86aabSstevel switch (status) { 32983db86aabSstevel case DDI_PROP_SUCCESS: 32993db86aabSstevel cardbus_err(dip, 5, 33003db86aabSstevel "cardbus_update_assigned_prop: found prop len %d\n", 33013db86aabSstevel alen); 33023db86aabSstevel /* 33033db86aabSstevel * Allocate memory for the existing 33043db86aabSstevel * assigned-addresses(s) plus one and then 33053db86aabSstevel * build it. 33063db86aabSstevel */ 33073db86aabSstevel newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP); 33083db86aabSstevel 33093db86aabSstevel bcopy(assigned, newreg, alen); 33103db86aabSstevel bcopy(newone, newreg + alen, sizeof (*newone)); 33113db86aabSstevel break; 33123db86aabSstevel 33133db86aabSstevel case DDI_PROP_NO_MEMORY: 33143db86aabSstevel cardbus_err(dip, 1, 33153db86aabSstevel "no memory for assigned-addresses property\n"); 33163db86aabSstevel return (PCICFG_FAILURE); 33173db86aabSstevel 33183db86aabSstevel default: 33193db86aabSstevel cardbus_err(dip, 5, 33203db86aabSstevel "cardbus_update_assigned_prop: creating prop\n"); 33213db86aabSstevel alen = 0; 33223db86aabSstevel newreg = (caddr_t)newone; 33233db86aabSstevel break; 33243db86aabSstevel } 33253db86aabSstevel 33263db86aabSstevel /* 33273db86aabSstevel * Write out the new "assigned-addresses" spec 33283db86aabSstevel */ 33293db86aabSstevel (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 33303db86aabSstevel "assigned-addresses", (int *)newreg, 33313db86aabSstevel (alen + sizeof (*newone))/sizeof (int)); 33323db86aabSstevel 33333db86aabSstevel if (status == DDI_PROP_SUCCESS) 33343db86aabSstevel kmem_free((caddr_t)newreg, alen+sizeof (*newone)); 33353db86aabSstevel 33363db86aabSstevel if (alen) 33373db86aabSstevel kmem_free(assigned, alen); 33383db86aabSstevel 33393db86aabSstevel return (PCICFG_SUCCESS); 33403db86aabSstevel } 33413db86aabSstevel 33423db86aabSstevel static int 33433db86aabSstevel cardbus_update_available_prop(dev_info_t *dip, uint32_t hi_type, 33443db86aabSstevel uint64_t base, uint64_t size) 33453db86aabSstevel { 33463db86aabSstevel int alen, rlen; 33473db86aabSstevel pci_regspec_t *available, *reg; 33483db86aabSstevel pci_regspec_t addition; 33493db86aabSstevel caddr_t newreg; 33503db86aabSstevel uint_t status; 33513db86aabSstevel 33523db86aabSstevel cardbus_err(dip, 6, "cardbus_update_available_prop\n"); 33533db86aabSstevel 33543db86aabSstevel status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 33553db86aabSstevel "reg", (caddr_t)®, &rlen); 33563db86aabSstevel 33573db86aabSstevel switch (status) { 33583db86aabSstevel case DDI_PROP_SUCCESS: 33593db86aabSstevel break; 33603db86aabSstevel case DDI_PROP_NO_MEMORY: 33613db86aabSstevel cardbus_err(dip, 1, "reg present, but unable to get memory\n"); 33623db86aabSstevel return (PCICFG_FAILURE); 33633db86aabSstevel default: 33643db86aabSstevel cardbus_err(dip, 1, "no reg property\n"); 33653db86aabSstevel return (PCICFG_FAILURE); 33663db86aabSstevel } 33673db86aabSstevel 33683db86aabSstevel status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, 33693db86aabSstevel "available", (caddr_t)&available, &alen); 33703db86aabSstevel switch (status) { 33713db86aabSstevel case DDI_PROP_SUCCESS: 33723db86aabSstevel break; 33733db86aabSstevel case DDI_PROP_NO_MEMORY: 33743db86aabSstevel cardbus_err(dip, 1, "no memory for available property\n"); 33753db86aabSstevel kmem_free((caddr_t)reg, rlen); 33763db86aabSstevel return (PCICFG_FAILURE); 33773db86aabSstevel default: 33783db86aabSstevel alen = 0; 33793db86aabSstevel } 33803db86aabSstevel 33813db86aabSstevel /* 33823db86aabSstevel * Allocate memory for the existing 33833db86aabSstevel * available(s) plus one and then 33843db86aabSstevel * build it. 33853db86aabSstevel */ 33863db86aabSstevel newreg = kmem_zalloc(alen + sizeof (pci_regspec_t), KM_SLEEP); 33873db86aabSstevel 33883db86aabSstevel /* 33893db86aabSstevel * Build the regspec, then add it to the existing one(s) 33903db86aabSstevel */ 33913db86aabSstevel addition.pci_phys_hi = hi_type | 33923db86aabSstevel PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi), 33933db86aabSstevel PCI_REG_DEV_G(reg->pci_phys_hi), 33943db86aabSstevel PCI_REG_FUNC_G(reg->pci_phys_hi), 0); 33953db86aabSstevel 33963db86aabSstevel addition.pci_phys_mid = (uint32_t)((base>>32) & 0xffffffff); 33973db86aabSstevel addition.pci_phys_low = (uint32_t)(base & 0xffffffff); 33983db86aabSstevel addition.pci_size_hi = (uint32_t)((size>>32) & 0xffffffff); 33993db86aabSstevel addition.pci_size_low = (uint32_t)(size & 0xffffffff); 34003db86aabSstevel 34013db86aabSstevel #ifdef DEBUG 34023db86aabSstevel cardbus_dump_reg(dip, &addition, 1); 34033db86aabSstevel #endif 34043db86aabSstevel 34053db86aabSstevel if (alen) 34063db86aabSstevel bcopy(available, newreg, alen); 34073db86aabSstevel bcopy(&addition, newreg + alen, sizeof (pci_regspec_t)); 34083db86aabSstevel 34093db86aabSstevel /* 34103db86aabSstevel * Write out the new "available" spec 34113db86aabSstevel */ 34123db86aabSstevel (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 34133db86aabSstevel "available", (int *)newreg, 34143db86aabSstevel (alen + sizeof (pci_regspec_t))/sizeof (int)); 34153db86aabSstevel 34163db86aabSstevel if (alen) 34173db86aabSstevel kmem_free((caddr_t)available, alen); 34183db86aabSstevel kmem_free((caddr_t)reg, rlen); 34193db86aabSstevel kmem_free((caddr_t)newreg, alen + sizeof (pci_regspec_t)); 34203db86aabSstevel 34213db86aabSstevel return (PCICFG_SUCCESS); 34223db86aabSstevel } 34233db86aabSstevel 34243db86aabSstevel static int 34253db86aabSstevel cardbus_update_ranges_prop(dev_info_t *dip, cardbus_range_t *addition) 34263db86aabSstevel { 34273db86aabSstevel int rlen; 34283db86aabSstevel cardbus_range_t *ranges; 34293db86aabSstevel caddr_t newreg; 34303db86aabSstevel uint_t status; 34313db86aabSstevel #if defined(CARDBUS_DEBUG) 34323db86aabSstevel int i, nrange; 34333db86aabSstevel const cardbus_range_t *nr; 34343db86aabSstevel #endif 34353db86aabSstevel 34363db86aabSstevel cardbus_err(dip, 6, "cardbus_update_ranges_prop\n"); 34373db86aabSstevel 34383db86aabSstevel status = ddi_getlongprop(DDI_DEV_T_NONE, 34393db86aabSstevel dip, DDI_PROP_DONTPASS, "ranges", 34403db86aabSstevel (caddr_t)&ranges, &rlen); 34413db86aabSstevel 34423db86aabSstevel switch (status) { 34433db86aabSstevel case DDI_PROP_SUCCESS: 34443db86aabSstevel break; 34453db86aabSstevel case DDI_PROP_NO_MEMORY: 34463db86aabSstevel cardbus_err(dip, 1, 34473db86aabSstevel "ranges present, but unable to get memory\n"); 34483db86aabSstevel return (PCICFG_FAILURE); 34493db86aabSstevel default: 34503db86aabSstevel cardbus_err(dip, 8, "no ranges property - creating one\n"); 34513db86aabSstevel if (ndi_prop_update_int_array(DDI_DEV_T_NONE, 34523db86aabSstevel dip, "ranges", (int *)addition, 34533db86aabSstevel sizeof (cardbus_range_t)/sizeof (int)) 34543db86aabSstevel != DDI_SUCCESS) { 34553db86aabSstevel cardbus_err(dip, 1, "Did'nt create ranges property\n"); 34563db86aabSstevel return (PCICFG_FAILURE); 34573db86aabSstevel } 34583db86aabSstevel return (PCICFG_SUCCESS); 34593db86aabSstevel } 34603db86aabSstevel 34613db86aabSstevel /* 34623db86aabSstevel * Allocate memory for the existing reg(s) plus one and then 34633db86aabSstevel * build it. 34643db86aabSstevel */ 34653db86aabSstevel newreg = kmem_zalloc(rlen+sizeof (cardbus_range_t), KM_SLEEP); 34663db86aabSstevel 34673db86aabSstevel bcopy(ranges, newreg, rlen); 34683db86aabSstevel bcopy(addition, newreg + rlen, sizeof (cardbus_range_t)); 34693db86aabSstevel 34703db86aabSstevel /* 34713db86aabSstevel * Write out the new "ranges" property 34723db86aabSstevel */ 34733db86aabSstevel (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 34743db86aabSstevel dip, "ranges", (int *)newreg, 34753db86aabSstevel (rlen + sizeof (cardbus_range_t))/sizeof (int)); 34763db86aabSstevel 34773db86aabSstevel #if defined(CARDBUS_DEBUG) 34783db86aabSstevel cardbus_err(dip, 8, "cardbus_update_ranges_prop ranges property:\n"); 34793db86aabSstevel 34803db86aabSstevel nrange = rlen / sizeof (cardbus_range_t); 34813db86aabSstevel nr = (cardbus_range_t *)newreg; 34823db86aabSstevel for (i = 0; i <= nrange; i++) { 34833db86aabSstevel /* nrange is one higher for new entry */ 34843db86aabSstevel cardbus_err(dip, 9, 34853db86aabSstevel "\trange parent addr 0x%x.0x%x.0x%x " 34863db86aabSstevel "child addr 0x%x.0x%x.0x%x size 0x%x.0x%x\n", 34873db86aabSstevel nr->parent_hi, 34883db86aabSstevel nr->parent_mid, nr->parent_lo, 34893db86aabSstevel nr->child_hi, 34903db86aabSstevel nr->child_mid, nr->child_lo, 34913db86aabSstevel nr->size_hi, nr->size_lo); 34923db86aabSstevel nr++; 34933db86aabSstevel } 34943db86aabSstevel #endif 34953db86aabSstevel 34963db86aabSstevel kmem_free((caddr_t)newreg, rlen+sizeof (cardbus_range_t)); 34973db86aabSstevel kmem_free((caddr_t)ranges, rlen); 34983db86aabSstevel 34993db86aabSstevel return (PCICFG_SUCCESS); 35003db86aabSstevel } 35013db86aabSstevel 35023db86aabSstevel static int 35033db86aabSstevel cardbus_update_reg_prop(dev_info_t *dip, uint32_t regvalue, uint_t reg_offset) 35043db86aabSstevel { 35053db86aabSstevel int rlen; 35063db86aabSstevel pci_regspec_t *reg; 35073db86aabSstevel caddr_t newreg; 35083db86aabSstevel uint32_t hiword; 35093db86aabSstevel pci_regspec_t addition; 35103db86aabSstevel uint32_t size; 35113db86aabSstevel uint_t status; 35123db86aabSstevel 35133db86aabSstevel status = ddi_getlongprop(DDI_DEV_T_NONE, 35143db86aabSstevel dip, DDI_PROP_DONTPASS, "reg", (caddr_t)®, &rlen); 35153db86aabSstevel 35163db86aabSstevel switch (status) { 35173db86aabSstevel case DDI_PROP_SUCCESS: 35183db86aabSstevel break; 35193db86aabSstevel case DDI_PROP_NO_MEMORY: 35203db86aabSstevel cardbus_err(dip, 1, "reg present, but unable to get memory\n"); 35213db86aabSstevel return (PCICFG_FAILURE); 35223db86aabSstevel default: 35233db86aabSstevel cardbus_err(dip, 1, "no reg property\n"); 35243db86aabSstevel return (PCICFG_FAILURE); 35253db86aabSstevel } 35263db86aabSstevel 35273db86aabSstevel /* 35283db86aabSstevel * Allocate memory for the existing reg(s) plus one and then 35293db86aabSstevel * build it. 35303db86aabSstevel */ 35313db86aabSstevel newreg = kmem_zalloc(rlen+sizeof (pci_regspec_t), KM_SLEEP); 35323db86aabSstevel 35333db86aabSstevel /* 35343db86aabSstevel * Build the regspec, then add it to the existing one(s) 35353db86aabSstevel */ 35363db86aabSstevel hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi), 35373db86aabSstevel PCI_REG_DEV_G(reg->pci_phys_hi), 35383db86aabSstevel PCI_REG_FUNC_G(reg->pci_phys_hi), 35393db86aabSstevel reg_offset); 35403db86aabSstevel 35413db86aabSstevel if (reg_offset == PCI_CONF_ROM) { 35423db86aabSstevel size = (~(PCI_BASE_ROM_ADDR_M & regvalue))+1; 35433db86aabSstevel hiword |= PCI_ADDR_MEM32; 35443db86aabSstevel } else { 35453db86aabSstevel size = (~(PCI_BASE_M_ADDR_M & regvalue))+1; 35463db86aabSstevel 35473db86aabSstevel if ((PCI_BASE_SPACE_M & regvalue) == PCI_BASE_SPACE_MEM) { 35483db86aabSstevel if ((PCI_BASE_TYPE_M & regvalue) == PCI_BASE_TYPE_MEM) { 35493db86aabSstevel hiword |= PCI_ADDR_MEM32; 35503db86aabSstevel } else if ((PCI_BASE_TYPE_M & regvalue) 35513db86aabSstevel == PCI_BASE_TYPE_ALL) { 35523db86aabSstevel /* 35533db86aabSstevel * This is a 64 bit PCI memory space. 35543db86aabSstevel * It needs to be allocated as 32 bit 35553db86aabSstevel * for bus map purposes. 35563db86aabSstevel */ 35573db86aabSstevel hiword |= PCI_ADDR_MEM32; 35583db86aabSstevel } 35593db86aabSstevel } else { 35603db86aabSstevel hiword |= PCI_ADDR_IO; 35613db86aabSstevel } 35623db86aabSstevel } 35633db86aabSstevel 35643db86aabSstevel addition.pci_phys_hi = hiword; 35653db86aabSstevel addition.pci_phys_mid = 0; 35663db86aabSstevel addition.pci_phys_low = 0; 35673db86aabSstevel addition.pci_size_hi = 0; 35683db86aabSstevel addition.pci_size_low = size; 35693db86aabSstevel 35703db86aabSstevel cardbus_err(dip, 8, 35713db86aabSstevel "cardbus_update_reg_prop, phys_hi 0x%08x," 35723db86aabSstevel " phys_mid 0x%08x, phys_low 0x%08x, size_hi 0x%08x," 35733db86aabSstevel " size_low 0x%08x\n", hiword, 0, 0, 0, size); 35743db86aabSstevel 35753db86aabSstevel bcopy(reg, newreg, rlen); 35763db86aabSstevel bcopy(&addition, newreg + rlen, sizeof (pci_regspec_t)); 35773db86aabSstevel 35783db86aabSstevel /* 35793db86aabSstevel * Write out the new "reg" property 35803db86aabSstevel */ 35813db86aabSstevel (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 35823db86aabSstevel dip, "reg", (int *)newreg, 35833db86aabSstevel (rlen + sizeof (pci_regspec_t))/sizeof (int)); 35843db86aabSstevel 35853db86aabSstevel kmem_free((caddr_t)reg, rlen); 35863db86aabSstevel kmem_free((caddr_t)newreg, rlen+sizeof (pci_regspec_t)); 35873db86aabSstevel 35883db86aabSstevel return (PCICFG_SUCCESS); 35893db86aabSstevel } 35903db86aabSstevel 35913db86aabSstevel /* 35923db86aabSstevel * Setup the basic 1275 properties based on information found in the config 35933db86aabSstevel * header of the PCI device 35943db86aabSstevel */ 35953db86aabSstevel static int 35963db86aabSstevel cardbus_set_standard_props(dev_info_t *parent, dev_info_t *dip, 35973db86aabSstevel ddi_acc_handle_t config_handle) 35983db86aabSstevel { 35993db86aabSstevel int ret; 36003db86aabSstevel uint16_t val; 36013db86aabSstevel uint32_t wordval; 36023db86aabSstevel uint8_t byteval; 36033db86aabSstevel 36043db86aabSstevel /* These two exists only for non-bridges */ 36053db86aabSstevel if ((pci_config_get8(config_handle, 36063db86aabSstevel PCI_CONF_HEADER) & PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) { 36073db86aabSstevel byteval = pci_config_get8(config_handle, PCI_CONF_MIN_G); 36083db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36093db86aabSstevel "min-grant", byteval)) != DDI_SUCCESS) { 36103db86aabSstevel cardbus_err(dip, 1, "Failed to sent min-grant\n"); 36113db86aabSstevel return (ret); 36123db86aabSstevel } 36133db86aabSstevel 36143db86aabSstevel byteval = pci_config_get8(config_handle, PCI_CONF_MAX_L); 36153db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36163db86aabSstevel "max-latency", byteval)) != DDI_SUCCESS) { 36173db86aabSstevel return (ret); 36183db86aabSstevel } 36193db86aabSstevel } 36203db86aabSstevel 36213db86aabSstevel /* 36223db86aabSstevel * These should always exist and have the value of the 36233db86aabSstevel * corresponding register value 36243db86aabSstevel */ 36253db86aabSstevel val = pci_config_get16(config_handle, PCI_CONF_VENID); 36263db86aabSstevel 36273db86aabSstevel /* 36283db86aabSstevel * according to section 6.2.1 of revision 2 of the PCI local 36293db86aabSstevel * bus specification - 0FFFFh is an invalid value for the vendor ID 36303db86aabSstevel */ 36313db86aabSstevel if (val == 0xffff) { 36323db86aabSstevel cardbus_err(dip, 1, "Illegal vendor-id 0x%x\n", val); 36333db86aabSstevel return (PCICFG_FAILURE); 36343db86aabSstevel } 36353db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36363db86aabSstevel "vendor-id", val)) != DDI_SUCCESS) { 36373db86aabSstevel return (ret); 36383db86aabSstevel } 36393db86aabSstevel 36403db86aabSstevel val = pci_config_get16(config_handle, PCI_CONF_DEVID); 36413db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36423db86aabSstevel "device-id", val)) != DDI_SUCCESS) { 36433db86aabSstevel return (ret); 36443db86aabSstevel } 36453db86aabSstevel byteval = pci_config_get8(config_handle, PCI_CONF_REVID); 36463db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36473db86aabSstevel "revision-id", byteval)) != DDI_SUCCESS) { 36483db86aabSstevel return (ret); 36493db86aabSstevel } 36503db86aabSstevel 36513db86aabSstevel wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) | 36523db86aabSstevel (pci_config_get8(config_handle, PCI_CONF_PROGCLASS)); 36533db86aabSstevel 36543db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36553db86aabSstevel "class-code", wordval)) != DDI_SUCCESS) { 36563db86aabSstevel return (ret); 36573db86aabSstevel } 36583db86aabSstevel val = (pci_config_get16(config_handle, 3659*11c2b4c0Srw148561 PCI_CONF_STAT) & PCI_STAT_DEVSELT) >> 9; 36603db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36613db86aabSstevel "devsel-speed", val)) != DDI_SUCCESS) { 36623db86aabSstevel return (ret); 36633db86aabSstevel } 36643db86aabSstevel 36653db86aabSstevel /* 36663db86aabSstevel * The next three are bits set in the status register. The property is 36673db86aabSstevel * present (but with no value other than its own existence) if the bit 36683db86aabSstevel * is set, non-existent otherwise 36693db86aabSstevel */ 36703db86aabSstevel if (ddi_prop_exists(DDI_DEV_T_ANY, parent, DDI_PROP_DONTPASS, 36713db86aabSstevel "fast-back-to-back") && 36723db86aabSstevel pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_FBBC) { 36733db86aabSstevel 36743db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36753db86aabSstevel "fast-back-to-back", 0)) != DDI_SUCCESS) { 36763db86aabSstevel return (ret); 36773db86aabSstevel } 36783db86aabSstevel } 36793db86aabSstevel if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_66MHZ) { 36803db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36813db86aabSstevel "66mhz-capable", 0)) != DDI_SUCCESS) { 36823db86aabSstevel return (ret); 36833db86aabSstevel } 36843db86aabSstevel } 36853db86aabSstevel if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_UDF) { 36863db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 36873db86aabSstevel "udf-supported", 0)) != DDI_SUCCESS) { 36883db86aabSstevel return (ret); 36893db86aabSstevel } 36903db86aabSstevel } 36913db86aabSstevel 36923db86aabSstevel /* 36933db86aabSstevel * These next three are optional and are not present 36943db86aabSstevel * if the corresponding register is zero. If the value 36953db86aabSstevel * is non-zero then the property exists with the value 36963db86aabSstevel * of the register. 36973db86aabSstevel */ 36983db86aabSstevel 36993db86aabSstevel /* look in the correct place for header type 2 */ 37003db86aabSstevel byteval = pci_config_get8(config_handle, PCI_CONF_HEADER); 37013db86aabSstevel if ((byteval & PCI_HEADER_TYPE_M) == PCI_HEADER_TWO) { 37023db86aabSstevel if ((val = pci_config_get16(config_handle, 37033db86aabSstevel PCI_CBUS_SUBVENID)) != 0) { 37043db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 37053db86aabSstevel "subsystem-vendor-id", val)) != DDI_SUCCESS) { 37063db86aabSstevel return (ret); 37073db86aabSstevel } 37083db86aabSstevel } 37093db86aabSstevel if ((val = pci_config_get16(config_handle, 37103db86aabSstevel PCI_CBUS_SUBSYSID)) != 0) { 37113db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 37123db86aabSstevel "subsystem-id", val)) != DDI_SUCCESS) { 37133db86aabSstevel return (ret); 37143db86aabSstevel } 37153db86aabSstevel } 37163db86aabSstevel } else { 37173db86aabSstevel if ((val = pci_config_get16(config_handle, 37183db86aabSstevel PCI_CONF_SUBVENID)) != 0) { 37193db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 37203db86aabSstevel "subsystem-vendor-id", val)) != DDI_SUCCESS) { 37213db86aabSstevel return (ret); 37223db86aabSstevel } 37233db86aabSstevel } 37243db86aabSstevel if ((val = pci_config_get16(config_handle, 37253db86aabSstevel PCI_CONF_SUBSYSID)) != 0) { 37263db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 37273db86aabSstevel "subsystem-id", val)) != DDI_SUCCESS) { 37283db86aabSstevel return (ret); 37293db86aabSstevel } 37303db86aabSstevel } 37313db86aabSstevel } 37323db86aabSstevel 37333db86aabSstevel if ((val = pci_config_get8(config_handle, 37343db86aabSstevel PCI_CONF_CACHE_LINESZ)) != 0) { 37353db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 37363db86aabSstevel "cache-line-size", val)) != DDI_SUCCESS) { 37373db86aabSstevel return (ret); 37383db86aabSstevel } 37393db86aabSstevel } 37403db86aabSstevel 37413db86aabSstevel /* 37423db86aabSstevel * If the Interrupt Pin register is non-zero then the 37433db86aabSstevel * interrupts property exists 37443db86aabSstevel */ 37453db86aabSstevel if ((byteval = pci_config_get8(config_handle, PCI_CONF_IPIN)) != 0) { 37463db86aabSstevel /* 37473db86aabSstevel * If interrupt pin is non-zero, 37483db86aabSstevel * record the interrupt line used 37493db86aabSstevel */ 37503db86aabSstevel cardbus_err(dip, 8, "Adding interrupts property\n"); 37513db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 37523db86aabSstevel "interrupts", byteval)) != DDI_SUCCESS) { 37533db86aabSstevel return (ret); 37543db86aabSstevel } 37553db86aabSstevel } 37563db86aabSstevel return (PCICFG_SUCCESS); 37573db86aabSstevel } 37583db86aabSstevel 37593db86aabSstevel /* 37603db86aabSstevel * Setup the basic properties required by the ISA node. 37613db86aabSstevel */ 37623db86aabSstevel static int 37633db86aabSstevel cardbus_set_isa_props(dev_info_t *parent, dev_info_t *dip, 37643db86aabSstevel char *name, char *compat[]) 37653db86aabSstevel { 37663db86aabSstevel int ret, n; 37673db86aabSstevel 37683db86aabSstevel _NOTE(ARGUNUSED(parent)) 37693db86aabSstevel 37703db86aabSstevel cardbus_err(dip, 8, "Adding interrupts property\n"); 37713db86aabSstevel if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip, 37723db86aabSstevel "interrupts", 1)) != DDI_SUCCESS) { 37733db86aabSstevel return (ret); 37743db86aabSstevel } 37753db86aabSstevel 37763db86aabSstevel /* 37773db86aabSstevel * The node name field needs to be filled in with the name 37783db86aabSstevel */ 37793db86aabSstevel if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) { 37803db86aabSstevel cardbus_err(dip, 1, "Failed to set nodename for node\n"); 37813db86aabSstevel return (PCICFG_FAILURE); 37823db86aabSstevel } 37833db86aabSstevel 37843db86aabSstevel /* 37853db86aabSstevel * Create the compatible property as an array of pointers 37863db86aabSstevel * to strings. Start with the buffer created above. 37873db86aabSstevel */ 37883db86aabSstevel n = 0; 37893db86aabSstevel while (compat[n] != NULL) 37903db86aabSstevel n++; 37913db86aabSstevel 37923db86aabSstevel if (n != 0) 37933db86aabSstevel if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, 37943db86aabSstevel "compatible", compat, n)) != DDI_SUCCESS) 37953db86aabSstevel return (ret); 37963db86aabSstevel 37973db86aabSstevel return (PCICFG_SUCCESS); 37983db86aabSstevel } 37993db86aabSstevel 38003db86aabSstevel static int 38013db86aabSstevel cardbus_set_busnode_props(dev_info_t *dip) 38023db86aabSstevel { 38033db86aabSstevel cardbus_err(dip, 6, "cardbus_set_busnode_props\n"); 38043db86aabSstevel 38053db86aabSstevel cardbus_force_stringprop(dip, "device_type", "pci"); 38063db86aabSstevel 38073db86aabSstevel if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, 38083db86aabSstevel "#address-cells", 3) != DDI_SUCCESS) { 38093db86aabSstevel cardbus_err(dip, 4, "Failed to set #address-cells\n"); 38103db86aabSstevel } 38113db86aabSstevel if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, 38123db86aabSstevel "#size-cells", 2) != DDI_SUCCESS) { 38133db86aabSstevel cardbus_err(dip, 4, "Failed to set #size-cells\n"); 38143db86aabSstevel } 38153db86aabSstevel return (PCICFG_SUCCESS); 38163db86aabSstevel } 38173db86aabSstevel 38183db86aabSstevel static int 38193db86aabSstevel cardbus_set_busnode_isaprops(dev_info_t *dip) 38203db86aabSstevel { 38213db86aabSstevel cardbus_err(dip, 6, "cardbus_set_busnode_props\n"); 38223db86aabSstevel 38233db86aabSstevel cardbus_force_stringprop(dip, "device_type", "isa"); 38243db86aabSstevel 38253db86aabSstevel if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, 38263db86aabSstevel "#address-cells", 2) != DDI_SUCCESS) { 38273db86aabSstevel cardbus_err(dip, 4, "Failed to set #address-cells\n"); 38283db86aabSstevel } 38293db86aabSstevel if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, 38303db86aabSstevel "#size-cells", 1) != DDI_SUCCESS) { 38313db86aabSstevel cardbus_err(dip, 4, "Failed to set #size-cells\n"); 38323db86aabSstevel } 38333db86aabSstevel return (PCICFG_SUCCESS); 38343db86aabSstevel } 38353db86aabSstevel 38363db86aabSstevel /* 38373db86aabSstevel * Use cb%x,%x rather than pci%x,%x so that we can use specific cardbus 38383db86aabSstevel * drivers in /etc/driver_aliases if required 38393db86aabSstevel */ 38403db86aabSstevel static int 38413db86aabSstevel cardbus_set_childnode_props(dev_info_t *dip, ddi_acc_handle_t config_handle) 38423db86aabSstevel { 38433db86aabSstevel int ret; 38443db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES 38453db86aabSstevel uint32_t wordval; 38463db86aabSstevel #endif 38473db86aabSstevel char *name; 38483db86aabSstevel char buffer[64]; 38493db86aabSstevel uint32_t classcode; 38503db86aabSstevel char *compat[8]; 38513db86aabSstevel int i, n; 38523db86aabSstevel uint16_t subsysid, subvenid, devid, venid; 38533db86aabSstevel uint8_t header_type; 38543db86aabSstevel 38553db86aabSstevel /* 38563db86aabSstevel * NOTE: These are for both a child and PCI-PCI bridge node 38573db86aabSstevel */ 38583db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES 38593db86aabSstevel wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) | 38603db86aabSstevel (pci_config_get8(config_handle, PCI_CONF_PROGCLASS)); 38613db86aabSstevel #endif 38623db86aabSstevel 38633db86aabSstevel /* Cardbus support */ 38643db86aabSstevel venid = pci_config_get16(config_handle, PCI_CONF_VENID); 38653db86aabSstevel devid = pci_config_get16(config_handle, PCI_CONF_DEVID); 38663db86aabSstevel 38673db86aabSstevel header_type = pci_config_get8(config_handle, PCI_CONF_HEADER); 38683db86aabSstevel if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_TWO) { 38693db86aabSstevel subvenid = pci_config_get16(config_handle, PCI_CBUS_SUBVENID); 38703db86aabSstevel subsysid = pci_config_get16(config_handle, PCI_CBUS_SUBSYSID); 38713db86aabSstevel } else { 38723db86aabSstevel subvenid = pci_config_get16(config_handle, PCI_CONF_SUBVENID); 38733db86aabSstevel subsysid = pci_config_get16(config_handle, PCI_CONF_SUBSYSID); 38743db86aabSstevel } 38753db86aabSstevel 38763db86aabSstevel if (subsysid != 0) { 38773db86aabSstevel (void) sprintf(buffer, "pci%x,%x", subvenid, subsysid); 38783db86aabSstevel } else { 38793db86aabSstevel (void) sprintf(buffer, "pci%x,%x", venid, devid); 38803db86aabSstevel } 38813db86aabSstevel 38823db86aabSstevel cardbus_err(dip, 8, "Childname is %s\n", buffer); 38833db86aabSstevel 38843db86aabSstevel /* 38853db86aabSstevel * In some environments, trying to use "generic" 1275 names is 38863db86aabSstevel * not the convention. In those cases use the name as created 38873db86aabSstevel * above. In all the rest of the cases, check to see if there 38883db86aabSstevel * is a generic name first. 38893db86aabSstevel */ 38903db86aabSstevel #ifdef _DONT_USE_1275_GENERIC_NAMES 38913db86aabSstevel name = buffer; 38923db86aabSstevel #else 38933db86aabSstevel if ((name = cardbus_get_class_name(wordval>>8)) == NULL) { 38943db86aabSstevel /* 38953db86aabSstevel * Set name to the above fabricated name 38963db86aabSstevel */ 38973db86aabSstevel name = buffer; 38983db86aabSstevel } 38993db86aabSstevel 39003db86aabSstevel cardbus_err(dip, 8, "Set nodename to %s\n", name); 39013db86aabSstevel #endif 39023db86aabSstevel 39033db86aabSstevel /* 39043db86aabSstevel * The node name field needs to be filled in with the name 39053db86aabSstevel */ 39063db86aabSstevel if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) { 39073db86aabSstevel cardbus_err(dip, 1, "Failed to set nodename for node\n"); 39083db86aabSstevel return (PCICFG_FAILURE); 39093db86aabSstevel } 39103db86aabSstevel 39113db86aabSstevel /* 39123db86aabSstevel * Create the compatible property as an array of pointers 39133db86aabSstevel * to strings. Start with the cb name. 39143db86aabSstevel */ 39153db86aabSstevel n = 0; 39163db86aabSstevel 39173db86aabSstevel if (subsysid != 0) { 39183db86aabSstevel (void) sprintf(buffer, "cb%x,%x", subvenid, subsysid); 39193db86aabSstevel } else { 39203db86aabSstevel (void) sprintf(buffer, "cb%x,%x", venid, devid); 39213db86aabSstevel } 39223db86aabSstevel 39233db86aabSstevel compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP); 39243db86aabSstevel (void) strcpy(compat[n++], buffer); 39253db86aabSstevel 39263db86aabSstevel if (subsysid != 0) { 39273db86aabSstevel /* 39283db86aabSstevel * Add subsys numbers as pci compatible. 39293db86aabSstevel */ 39303db86aabSstevel (void) sprintf(buffer, "pci%x,%x", subvenid, subsysid); 39313db86aabSstevel compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP); 39323db86aabSstevel (void) strcpy(compat[n++], buffer); 39333db86aabSstevel } 39343db86aabSstevel 39353db86aabSstevel /* 39363db86aabSstevel * Add in the VendorID/DeviceID compatible name. 39373db86aabSstevel */ 39383db86aabSstevel (void) sprintf(buffer, "pci%x,%x", venid, devid); 39393db86aabSstevel 39403db86aabSstevel compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP); 39413db86aabSstevel (void) strcpy(compat[n++], buffer); 39423db86aabSstevel 39433db86aabSstevel classcode = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) | 39443db86aabSstevel (pci_config_get8(config_handle, PCI_CONF_PROGCLASS)); 39453db86aabSstevel 39463db86aabSstevel /* 39473db86aabSstevel * Add in the Classcode 39483db86aabSstevel */ 39493db86aabSstevel (void) sprintf(buffer, "pciclass,%06x", classcode); 39503db86aabSstevel 39513db86aabSstevel cardbus_err(dip, 8, "class code %s\n", buffer); 39523db86aabSstevel 39533db86aabSstevel compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP); 39543db86aabSstevel (void) strcpy(compat[n++], buffer); 39553db86aabSstevel 39563db86aabSstevel if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, 39573db86aabSstevel "compatible", (char **)compat, n)) != DDI_SUCCESS) { 39583db86aabSstevel return (ret); 39593db86aabSstevel } 39603db86aabSstevel 39613db86aabSstevel for (i = 0; i < n; i++) { 39623db86aabSstevel kmem_free(compat[i], strlen(compat[i]) + 1); 39633db86aabSstevel } 39643db86aabSstevel 39653db86aabSstevel return (PCICFG_SUCCESS); 39663db86aabSstevel } 39673db86aabSstevel 39683db86aabSstevel /* 39693db86aabSstevel * Program the bus numbers into the bridge 39703db86aabSstevel */ 39713db86aabSstevel static void 39723db86aabSstevel cardbus_set_bus_numbers(ddi_acc_handle_t config_handle, 39733db86aabSstevel uint_t primary, uint_t secondary) 39743db86aabSstevel { 39753db86aabSstevel cardbus_err(NULL, 8, 39763db86aabSstevel "cardbus_set_bus_numbers [%d->%d]\n", primary, secondary); 39773db86aabSstevel 39783db86aabSstevel /* 39793db86aabSstevel * Primary bus# 39803db86aabSstevel */ 39813db86aabSstevel pci_config_put8(config_handle, PCI_BCNF_PRIBUS, primary); 39823db86aabSstevel 39833db86aabSstevel /* 39843db86aabSstevel * Secondary bus# 39853db86aabSstevel */ 39863db86aabSstevel pci_config_put8(config_handle, PCI_BCNF_SECBUS, secondary); 39873db86aabSstevel 39883db86aabSstevel /* 39893db86aabSstevel * Set the subordinate bus number to ff in order to pass through any 39903db86aabSstevel * type 1 cycle with a bus number higher than the secondary bus# 39913db86aabSstevel * Note that this is reduced once the probe is complete in the 39923db86aabSstevel * cardbus_setup_bridge() function. 39933db86aabSstevel */ 39943db86aabSstevel pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0xFF); 39953db86aabSstevel } 39963db86aabSstevel 39973db86aabSstevel static void 39983db86aabSstevel enable_pci_isa_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle) 39993db86aabSstevel { 40003db86aabSstevel uint16_t comm, stat; 40013db86aabSstevel 40023db86aabSstevel stat = pci_config_get16(config_handle, PCI_CONF_STAT); 40033db86aabSstevel comm = pci_config_get16(config_handle, PCI_CONF_COMM); 40043db86aabSstevel 40053db86aabSstevel /* 40063db86aabSstevel * Enable memory, IO, bus mastership and error detection. 40073db86aabSstevel */ 40083db86aabSstevel comm |= (PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO | 40093db86aabSstevel PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE); 40103db86aabSstevel if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 40113db86aabSstevel "fast-back-to-back")) 40123db86aabSstevel comm |= PCI_COMM_BACK2BACK_ENAB; 40133db86aabSstevel pci_config_put16(config_handle, PCI_CONF_COMM, comm); 40143db86aabSstevel cardbus_err(NULL, 8, 40153db86aabSstevel "enable_pci_isa_bridge stat 0x%04x comm 0x%04x\n", stat, comm); 40163db86aabSstevel 40173db86aabSstevel /* 40183db86aabSstevel * ITE8888 Specific registers. 40193db86aabSstevel */ 40203db86aabSstevel pci_config_put8(config_handle, 0x50, 0x00); /* Timing Control */ 40213db86aabSstevel pci_config_put8(config_handle, 0x52, 0x00); /* Master DMA Access */ 40223db86aabSstevel pci_config_put8(config_handle, 0x53, 0x01); /* ROMCS */ 40233db86aabSstevel } 40243db86aabSstevel 40253db86aabSstevel static void 40263db86aabSstevel enable_pci_pci_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle) 40273db86aabSstevel { 40283db86aabSstevel uint16_t comm, stat, bctrl; 40293db86aabSstevel 40303db86aabSstevel stat = pci_config_get16(config_handle, PCI_CONF_STAT); 40313db86aabSstevel comm = pci_config_get16(config_handle, PCI_CONF_COMM); 40323db86aabSstevel bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL); 40333db86aabSstevel 40343db86aabSstevel comm &= ~(PCI_COMM_IO | PCI_COMM_MAE); 40353db86aabSstevel comm |= (PCI_COMM_ME | PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE); 40363db86aabSstevel 40373db86aabSstevel /* 40383db86aabSstevel * Enable back to back. 40393db86aabSstevel */ 40403db86aabSstevel if (stat & PCI_STAT_FBBC) 40413db86aabSstevel comm |= PCI_COMM_BACK2BACK_ENAB; 40423db86aabSstevel 40433db86aabSstevel pci_config_put16(config_handle, PCI_CONF_COMM, comm); 40443db86aabSstevel 40453db86aabSstevel /* 40463db86aabSstevel * Reset the sub-ordinate bus. 40473db86aabSstevel */ 40483db86aabSstevel if (!(bctrl & PCI_BCNF_BCNTRL_RESET)) 40493db86aabSstevel pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, 40503db86aabSstevel bctrl | PCI_BCNF_BCNTRL_RESET); 40513db86aabSstevel else 40523db86aabSstevel bctrl &= ~PCI_BCNF_BCNTRL_RESET; 40533db86aabSstevel 40543db86aabSstevel /* 40553db86aabSstevel * Enable error reporting. 40563db86aabSstevel */ 40573db86aabSstevel bctrl |= (PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE | 40583db86aabSstevel PCI_BCNF_BCNTRL_MAST_AB_MODE); 40593db86aabSstevel 40603db86aabSstevel /* 40613db86aabSstevel * Enable back to back on secondary bus. 40623db86aabSstevel */ 40633db86aabSstevel if (stat & PCI_STAT_FBBC) 40643db86aabSstevel bctrl |= PCI_BCNF_BCNTRL_B2B_ENAB; 40653db86aabSstevel 40663db86aabSstevel pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl); 40673db86aabSstevel cardbus_err(dip, 8, 40683db86aabSstevel "enable_pci_pci_bridge stat 0x%04x comm 0x%04x bctrl 0x%04x\n", 40693db86aabSstevel stat, comm, bctrl); 40703db86aabSstevel } 40713db86aabSstevel 40723db86aabSstevel static int cardbus_reset_wait = 20; 40733db86aabSstevel 40743db86aabSstevel static void 40753db86aabSstevel enable_cardbus_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle) 40763db86aabSstevel { 40773db86aabSstevel uint16_t comm, stat, bctrl; 40783db86aabSstevel 40793db86aabSstevel stat = pci_config_get16(config_handle, PCI_CONF_STAT); 40803db86aabSstevel comm = pci_config_get16(config_handle, PCI_CONF_COMM); 40813db86aabSstevel bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL); 40823db86aabSstevel 40833db86aabSstevel /* 40843db86aabSstevel * Don't mess with the command register on the cardbus bridge 40853db86aabSstevel * itself. This should have been done when it's parent 40863db86aabSstevel * did the setup. Some devices *require* certain things to 40873db86aabSstevel * disabled, this can be done using the "command-preserve" 40883db86aabSstevel * property and if we mess with it here it breaks that. 40893db86aabSstevel * 40903db86aabSstevel * comm |= (PCI_COMM_ME | PCI_COMM_PARITY_DETECT | 40913db86aabSstevel * PCI_COMM_SERR_ENABLE); 40923db86aabSstevel */ 40933db86aabSstevel 40943db86aabSstevel /* 40953db86aabSstevel * Reset the sub-ordinate bus. 40963db86aabSstevel */ 40973db86aabSstevel if (!(bctrl & PCI_BCNF_BCNTRL_RESET)) 40983db86aabSstevel pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, 40993db86aabSstevel bctrl | PCI_BCNF_BCNTRL_RESET); 41003db86aabSstevel else 41013db86aabSstevel bctrl &= ~PCI_BCNF_BCNTRL_RESET; 41023db86aabSstevel 41033db86aabSstevel /* 41043db86aabSstevel * Turn off pre-fetch. 41053db86aabSstevel */ 41063db86aabSstevel bctrl &= ~(CB_BCNF_BCNTRL_MEM0_PREF | CB_BCNF_BCNTRL_MEM1_PREF | 41073db86aabSstevel PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE); 41083db86aabSstevel 41093db86aabSstevel /* 41103db86aabSstevel * Enable error reporting. 41113db86aabSstevel */ 41123db86aabSstevel bctrl |= (PCI_BCNF_BCNTRL_MAST_AB_MODE | CB_BCNF_BCNTRL_WRITE_POST); 41133db86aabSstevel if (comm & PCI_COMM_PARITY_DETECT) 41143db86aabSstevel bctrl |= PCI_BCNF_BCNTRL_PARITY_ENABLE; 41153db86aabSstevel if (comm & PCI_COMM_SERR_ENABLE) 41163db86aabSstevel bctrl |= PCI_BCNF_BCNTRL_SERR_ENABLE; 41173db86aabSstevel 41183db86aabSstevel pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl); 41193db86aabSstevel pci_config_put8(config_handle, PCI_CBUS_LATENCY_TIMER, 41203db86aabSstevel cardbus_latency_timer); 41213db86aabSstevel 41223db86aabSstevel pci_config_put16(config_handle, PCI_CONF_STAT, stat); 41233db86aabSstevel pci_config_put16(config_handle, PCI_CONF_COMM, comm); 41243db86aabSstevel 41253db86aabSstevel cardbus_err(dip, 8, 41263db86aabSstevel "enable_cardbus_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n", 41273db86aabSstevel stat, comm, bctrl); 41283db86aabSstevel 41293db86aabSstevel /* after resetting the bridge, wait for everything to stablize */ 41303db86aabSstevel delay(drv_usectohz(cardbus_reset_wait * 1000)); 41313db86aabSstevel 41323db86aabSstevel } 41333db86aabSstevel 41343db86aabSstevel static void 41353db86aabSstevel disable_pci_pci_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle) 41363db86aabSstevel { 41373db86aabSstevel uint16_t comm, bctrl; 41383db86aabSstevel 41393db86aabSstevel comm = pci_config_get16(config_handle, PCI_CONF_COMM); 41403db86aabSstevel bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL); 41413db86aabSstevel 41423db86aabSstevel /* 41433db86aabSstevel * Turn off subordinate bus access. 41443db86aabSstevel */ 41453db86aabSstevel pci_config_put8(config_handle, PCI_BCNF_SECBUS, 0); 41463db86aabSstevel pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0); 41473db86aabSstevel 41483db86aabSstevel /* 41493db86aabSstevel * Disable error reporting. 41503db86aabSstevel */ 41513db86aabSstevel bctrl &= ~(PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE | 41523db86aabSstevel PCI_BCNF_BCNTRL_MAST_AB_MODE); 41533db86aabSstevel comm = 0; 41543db86aabSstevel 41553db86aabSstevel pci_config_put16(config_handle, PCI_CONF_COMM, comm); 41563db86aabSstevel pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl); 41573db86aabSstevel 41583db86aabSstevel cardbus_err(dip, 6, 41593db86aabSstevel "disable_pci_pci_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n", 41603db86aabSstevel pci_config_get16(config_handle, PCI_CONF_STAT), comm, bctrl); 41613db86aabSstevel } 41623db86aabSstevel 41633db86aabSstevel static void 41643db86aabSstevel disable_cardbus_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle) 41653db86aabSstevel { 41663db86aabSstevel uint16_t comm, bctrl; 41673db86aabSstevel 41683db86aabSstevel comm = pci_config_get16(config_handle, PCI_CONF_COMM); 41693db86aabSstevel bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL); 41703db86aabSstevel 41713db86aabSstevel /* 41723db86aabSstevel * Turn off subordinate bus access. 41733db86aabSstevel */ 41743db86aabSstevel pci_config_put8(config_handle, PCI_BCNF_SECBUS, 0); 41753db86aabSstevel pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0); 41763db86aabSstevel 41773db86aabSstevel /* 41783db86aabSstevel * Disable error reporting. 41793db86aabSstevel */ 41803db86aabSstevel bctrl &= ~(PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE | 41813db86aabSstevel PCI_BCNF_BCNTRL_MAST_AB_MODE); 41823db86aabSstevel 41833db86aabSstevel pci_config_put32(config_handle, PCI_CBUS_MEM_LIMIT0, 0); 41843db86aabSstevel pci_config_put32(config_handle, PCI_CBUS_MEM_BASE0, 0); 41853db86aabSstevel pci_config_put32(config_handle, PCI_CBUS_IO_LIMIT0, 0); 41863db86aabSstevel pci_config_put32(config_handle, PCI_CBUS_IO_BASE0, 0); 41873db86aabSstevel pci_config_put16(config_handle, PCI_CONF_COMM, comm); 41883db86aabSstevel pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl); 41893db86aabSstevel 41903db86aabSstevel cardbus_err(dip, 6, 41913db86aabSstevel "disable_cardbus_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n", 41923db86aabSstevel pci_config_get16(config_handle, PCI_CONF_STAT), comm, bctrl); 41933db86aabSstevel } 41943db86aabSstevel 41953db86aabSstevel static void 41963db86aabSstevel enable_cardbus_device(dev_info_t *dip, ddi_acc_handle_t config_handle) 41973db86aabSstevel { 41983db86aabSstevel uint16_t comm, stat; 41993db86aabSstevel 42003db86aabSstevel stat = pci_config_get16(config_handle, PCI_CONF_STAT); 42013db86aabSstevel comm = pci_config_get16(config_handle, PCI_CONF_COMM); 42023db86aabSstevel 42033db86aabSstevel /* 42043db86aabSstevel * Enable memory, IO, bus mastership and error detection. 42053db86aabSstevel */ 42063db86aabSstevel comm |= (PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO | 42073db86aabSstevel PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE); 42083db86aabSstevel if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 42093db86aabSstevel "fast-back-to-back")) 42103db86aabSstevel comm |= PCI_COMM_BACK2BACK_ENAB; 42113db86aabSstevel pci_config_put16(config_handle, PCI_CONF_COMM, comm); 42123db86aabSstevel cardbus_err(NULL, 8, 42133db86aabSstevel "enable_cardbus_device stat 0x%04x comm 0x%04x\n", stat, comm); 42143db86aabSstevel } 42153db86aabSstevel 42163db86aabSstevel static void 42173db86aabSstevel disable_cardbus_device(ddi_acc_handle_t config_handle) 42183db86aabSstevel { 42193db86aabSstevel cardbus_err(NULL, 8, "disable_cardbus_device\n"); 42203db86aabSstevel 42213db86aabSstevel /* 42223db86aabSstevel * Turn off everything in the command register. 42233db86aabSstevel */ 42243db86aabSstevel pci_config_put16(config_handle, PCI_CONF_COMM, 0x0); 42253db86aabSstevel } 42263db86aabSstevel 42273db86aabSstevel #ifndef _DONT_USE_1275_GENERIC_NAMES 42283db86aabSstevel static char * 42293db86aabSstevel cardbus_get_class_name(uint32_t classcode) 42303db86aabSstevel { 42313db86aabSstevel struct cardbus_name_entry *ptr; 42323db86aabSstevel 42333db86aabSstevel for (ptr = &cardbus_class_lookup[0]; ptr->name != NULL; ptr++) { 42343db86aabSstevel if (ptr->class_code == classcode) { 42353db86aabSstevel return (ptr->name); 42363db86aabSstevel } 42373db86aabSstevel } 42383db86aabSstevel return (NULL); 42393db86aabSstevel } 42403db86aabSstevel #endif /* _DONT_USE_1275_GENERIC_NAMES */ 42413db86aabSstevel 42423db86aabSstevel static void 42433db86aabSstevel cardbus_force_boolprop(dev_info_t *dip, char *pname) 42443db86aabSstevel { 42453db86aabSstevel int ret; 42463db86aabSstevel 42473db86aabSstevel if ((ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, dip, 42483db86aabSstevel pname)) != DDI_SUCCESS) { 42493db86aabSstevel if (ret == DDI_PROP_NOT_FOUND) 42503db86aabSstevel if (ddi_prop_create(DDI_DEV_T_NONE, dip, 42513db86aabSstevel DDI_PROP_CANSLEEP, pname, 42523db86aabSstevel (caddr_t)NULL, 0) != DDI_SUCCESS) 42533db86aabSstevel cardbus_err(dip, 4, 42543db86aabSstevel "Failed to set boolean property " 42553db86aabSstevel "\"%s\"\n", pname); 42563db86aabSstevel } 42573db86aabSstevel } 42583db86aabSstevel 42593db86aabSstevel static void 42603db86aabSstevel cardbus_force_intprop(dev_info_t *dip, char *pname, int *pval, int len) 42613db86aabSstevel { 42623db86aabSstevel int ret; 42633db86aabSstevel 42643db86aabSstevel if ((ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 42653db86aabSstevel pname, pval, len)) != DDI_SUCCESS) { 42663db86aabSstevel if (ret == DDI_PROP_NOT_FOUND) 42673db86aabSstevel if (ddi_prop_create(DDI_DEV_T_NONE, dip, 42683db86aabSstevel DDI_PROP_CANSLEEP, pname, 42693db86aabSstevel (caddr_t)pval, len*sizeof (int)) 42703db86aabSstevel != DDI_SUCCESS) 42713db86aabSstevel cardbus_err(dip, 4, 42723db86aabSstevel "Failed to set int property \"%s\"\n", 42733db86aabSstevel pname); 42743db86aabSstevel } 42753db86aabSstevel } 42763db86aabSstevel 42773db86aabSstevel static void 42783db86aabSstevel cardbus_force_stringprop(dev_info_t *dip, char *pname, char *pval) 42793db86aabSstevel { 42803db86aabSstevel int ret; 42813db86aabSstevel 42823db86aabSstevel if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip, 42833db86aabSstevel pname, pval)) != DDI_SUCCESS) { 42843db86aabSstevel if (ret == DDI_PROP_NOT_FOUND) 42853db86aabSstevel if (ddi_prop_create(DDI_DEV_T_NONE, dip, 42863db86aabSstevel DDI_PROP_CANSLEEP, pname, 42873db86aabSstevel pval, strlen(pval) + 1) != DDI_SUCCESS) 42883db86aabSstevel cardbus_err(dip, 4, 42893db86aabSstevel "Failed to set string property " 42903db86aabSstevel "\"%s\" to \"%s\"\n", 42913db86aabSstevel pname, pval); 42923db86aabSstevel } 42933db86aabSstevel } 42943db86aabSstevel 42953db86aabSstevel static void 42963db86aabSstevel split_addr(char *naddr, int *dev, int *func) 42973db86aabSstevel { 42983db86aabSstevel char c; 42993db86aabSstevel int *ip = dev; 43003db86aabSstevel 43013db86aabSstevel *dev = 0; 43023db86aabSstevel *func = 0; 43033db86aabSstevel 43043db86aabSstevel while (c = *naddr++) { 43053db86aabSstevel if (c == ',') { 43063db86aabSstevel ip = func; 43073db86aabSstevel continue; 43083db86aabSstevel } 43093db86aabSstevel if (c >= '0' && c <= '9') { 43103db86aabSstevel *ip = (*ip * 16) + (c - '0'); 43113db86aabSstevel } else if (c >= 'a' && c <= 'f') { 43123db86aabSstevel *ip = (*ip * 16) + 10 + (c - 'a'); 43133db86aabSstevel } else 43143db86aabSstevel break; 43153db86aabSstevel } 43163db86aabSstevel } 43173db86aabSstevel 43183db86aabSstevel #ifdef DEBUG 43193db86aabSstevel static void 43203db86aabSstevel cardbus_dump_common_config(ddi_acc_handle_t config_handle) 43213db86aabSstevel { 43223db86aabSstevel cardbus_err(NULL, 1, 43233db86aabSstevel " Vendor ID = [0x%04x] " 43243db86aabSstevel "Device ID = [0x%04x]\n", 43253db86aabSstevel pci_config_get16(config_handle, PCI_CONF_VENID), 43263db86aabSstevel pci_config_get16(config_handle, PCI_CONF_DEVID)); 43273db86aabSstevel cardbus_err(NULL, 1, 43283db86aabSstevel " Command REG = [0x%04x] " 43293db86aabSstevel "Status REG = [0x%04x]\n", 43303db86aabSstevel pci_config_get16(config_handle, PCI_CONF_COMM), 43313db86aabSstevel pci_config_get16(config_handle, PCI_CONF_STAT)); 43323db86aabSstevel cardbus_err(NULL, 1, 43333db86aabSstevel " Revision ID = [0x%02x] " 43343db86aabSstevel "Prog Class = [0x%02x]\n", 43353db86aabSstevel pci_config_get8(config_handle, PCI_CONF_REVID), 43363db86aabSstevel pci_config_get8(config_handle, PCI_CONF_PROGCLASS)); 43373db86aabSstevel cardbus_err(NULL, 1, 43383db86aabSstevel " Dev Class = [0x%02x] " 43393db86aabSstevel "Base Class = [0x%02x]\n", 43403db86aabSstevel pci_config_get8(config_handle, PCI_CONF_SUBCLASS), 43413db86aabSstevel pci_config_get8(config_handle, PCI_CONF_BASCLASS)); 43423db86aabSstevel cardbus_err(NULL, 1, 43433db86aabSstevel " Cache LnSz = [0x%02x] " 43443db86aabSstevel "Latency Tmr = [0x%02x]\n", 43453db86aabSstevel pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ), 43463db86aabSstevel pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER)); 43473db86aabSstevel cardbus_err(NULL, 1, 43483db86aabSstevel " Header Type = [0x%02x] " 43493db86aabSstevel "BIST = [0x%02x]\n", 43503db86aabSstevel pci_config_get8(config_handle, PCI_CONF_HEADER), 43513db86aabSstevel pci_config_get8(config_handle, PCI_CONF_BIST)); 43523db86aabSstevel } 43533db86aabSstevel 43543db86aabSstevel static void 43553db86aabSstevel cardbus_dump_device_config(ddi_acc_handle_t config_handle) 43563db86aabSstevel { 43573db86aabSstevel cardbus_dump_common_config(config_handle); 43583db86aabSstevel 43593db86aabSstevel cardbus_err(NULL, 1, 43603db86aabSstevel " BASE 0 = [0x%08x] BASE 1 = [0x%08x]\n", 43613db86aabSstevel pci_config_get32(config_handle, PCI_CONF_BASE0), 43623db86aabSstevel pci_config_get32(config_handle, PCI_CONF_BASE1)); 43633db86aabSstevel cardbus_err(NULL, 1, 43643db86aabSstevel " BASE 2 = [0x%08x] BASE 3 = [0x%08x]\n", 43653db86aabSstevel pci_config_get32(config_handle, PCI_CONF_BASE2), 43663db86aabSstevel pci_config_get32(config_handle, PCI_CONF_BASE3)); 43673db86aabSstevel cardbus_err(NULL, 1, 43683db86aabSstevel " BASE 4 = [0x%08x] BASE 5 = [0x%08x]\n", 43693db86aabSstevel pci_config_get32(config_handle, PCI_CONF_BASE4), 43703db86aabSstevel pci_config_get32(config_handle, PCI_CONF_BASE5)); 43713db86aabSstevel cardbus_err(NULL, 1, 43723db86aabSstevel " Cardbus CIS = [0x%08x] ROM = [0x%08x]\n", 43733db86aabSstevel pci_config_get32(config_handle, PCI_CONF_CIS), 43743db86aabSstevel pci_config_get32(config_handle, PCI_CONF_ROM)); 43753db86aabSstevel cardbus_err(NULL, 1, 43763db86aabSstevel " Sub VID = [0x%04x] Sub SID = [0x%04x]\n", 43773db86aabSstevel pci_config_get16(config_handle, PCI_CONF_SUBVENID), 43783db86aabSstevel pci_config_get16(config_handle, PCI_CONF_SUBSYSID)); 43793db86aabSstevel cardbus_err(NULL, 1, 43803db86aabSstevel " I Line = [0x%02x] I Pin = [0x%02x]\n", 43813db86aabSstevel pci_config_get8(config_handle, PCI_CONF_ILINE), 43823db86aabSstevel pci_config_get8(config_handle, PCI_CONF_IPIN)); 43833db86aabSstevel cardbus_err(NULL, 1, 43843db86aabSstevel " Max Grant = [0x%02x] Max Latent = [0x%02x]\n", 43853db86aabSstevel pci_config_get8(config_handle, PCI_CONF_MIN_G), 43863db86aabSstevel pci_config_get8(config_handle, PCI_CONF_MAX_L)); 43873db86aabSstevel } 43883db86aabSstevel 43893db86aabSstevel static void 43903db86aabSstevel cardbus_dump_bridge_config(ddi_acc_handle_t config_handle, 43913db86aabSstevel uint8_t header_type) 43923db86aabSstevel { 43933db86aabSstevel if (header_type == PCI_HEADER_PPB) { 43943db86aabSstevel cardbus_dump_common_config(config_handle); 43953db86aabSstevel cardbus_err(NULL, 1, 43963db86aabSstevel "........................................\n"); 43973db86aabSstevel } else { 43983db86aabSstevel cardbus_dump_common_config(config_handle); 43993db86aabSstevel cardbus_err(NULL, 1, 44003db86aabSstevel " Mem Base = [0x%08x] CBus Status = [0x%04x]\n", 44013db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_SOCK_REG), 44023db86aabSstevel pci_config_get16(config_handle, PCI_CBUS_SEC_STATUS)); 44033db86aabSstevel } 44043db86aabSstevel 44053db86aabSstevel cardbus_err(NULL, 1, 44063db86aabSstevel " Pri Bus = [0x%02x] Sec Bus = [0x%02x]\n", 44073db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_PRIBUS), 44083db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_SECBUS)); 44093db86aabSstevel cardbus_err(NULL, 1, 44103db86aabSstevel " Sub Bus = [0x%02x] Sec Latency = [0x%02x]\n", 44113db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_SUBBUS), 44123db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_LATENCY_TIMER)); 44133db86aabSstevel 44143db86aabSstevel switch (header_type) { 44153db86aabSstevel case PCI_HEADER_PPB: 44163db86aabSstevel cardbus_err(NULL, 1, 44173db86aabSstevel " I/O Base LO = [0x%02x] I/O Lim LO = [0x%02x]\n", 44183db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW), 44193db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW)); 44203db86aabSstevel cardbus_err(NULL, 1, 44213db86aabSstevel " Sec. Status = [0x%04x]\n", 44223db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_SEC_STATUS)); 44233db86aabSstevel cardbus_err(NULL, 1, 44243db86aabSstevel " Mem Base = [0x%04x] Mem Limit = [0x%04x]\n", 44253db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_MEM_BASE), 44263db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT)); 44273db86aabSstevel cardbus_err(NULL, 1, 44283db86aabSstevel " PF Mem Base = [0x%04x] PF Mem Lim = [0x%04x]\n", 44293db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_PF_BASE_LOW), 44303db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_PF_LIMIT_LOW)); 44313db86aabSstevel cardbus_err(NULL, 1, 44323db86aabSstevel " PF Base HI = [0x%08x] PF Lim HI = [0x%08x]\n", 44333db86aabSstevel pci_config_get32(config_handle, PCI_BCNF_PF_BASE_HIGH), 44343db86aabSstevel pci_config_get32(config_handle, PCI_BCNF_PF_LIMIT_HIGH)); 44353db86aabSstevel cardbus_err(NULL, 1, 44363db86aabSstevel " I/O Base HI = [0x%04x] I/O Lim HI = [0x%04x]\n", 44373db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI), 44383db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI)); 44393db86aabSstevel cardbus_err(NULL, 1, 44403db86aabSstevel " ROM addr = [0x%08x]\n", 44413db86aabSstevel pci_config_get32(config_handle, PCI_BCNF_ROM)); 44423db86aabSstevel break; 44433db86aabSstevel case PCI_HEADER_CARDBUS: 44443db86aabSstevel cardbus_err(NULL, 1, 44453db86aabSstevel " Mem Base 0 = [0x%08x] Mem Limit 0 = [0x%08x]\n", 44463db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_MEM_BASE0), 44473db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_MEM_LIMIT0)); 44483db86aabSstevel cardbus_err(NULL, 1, 44493db86aabSstevel " Mem Base 1 = [0x%08x] Mem Limit 1 = [0x%08x]\n", 44503db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_MEM_BASE1), 44513db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_MEM_LIMIT1)); 44523db86aabSstevel cardbus_err(NULL, 1, 44533db86aabSstevel " IO Base 0 = [0x%08x] IO Limit 0 = [0x%08x]\n", 44543db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_IO_BASE0), 44553db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_IO_LIMIT0)); 44563db86aabSstevel cardbus_err(NULL, 1, 44573db86aabSstevel " IO Base 1 = [0x%08x] IO Limit 1 = [0x%08x]\n", 44583db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_IO_BASE1), 44593db86aabSstevel pci_config_get32(config_handle, PCI_CBUS_IO_LIMIT1)); 44603db86aabSstevel break; 44613db86aabSstevel } 44623db86aabSstevel cardbus_err(NULL, 1, 44633db86aabSstevel " Intr Line = [0x%02x] Intr Pin = [0x%02x]\n", 44643db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_ILINE), 44653db86aabSstevel pci_config_get8(config_handle, PCI_BCNF_IPIN)); 44663db86aabSstevel cardbus_err(NULL, 1, 44673db86aabSstevel " Bridge Ctrl = [0x%04x]\n", 44683db86aabSstevel pci_config_get16(config_handle, PCI_BCNF_BCNTRL)); 44693db86aabSstevel 44703db86aabSstevel switch (header_type) { 44713db86aabSstevel case PCI_HEADER_CARDBUS: 44723db86aabSstevel cardbus_err(NULL, 1, 44733db86aabSstevel " Sub VID = [0x%04x] Sub SID = [0x%04x]\n", 44743db86aabSstevel pci_config_get16(config_handle, PCI_CBUS_SUBVENID), 44753db86aabSstevel pci_config_get16(config_handle, PCI_CBUS_SUBSYSID)); 44763db86aabSstevel /* LATER: TI1250 only */ 44773db86aabSstevel cardbus_err(NULL, 1, 44783db86aabSstevel " Sys Control = [0x%08x]\n", 44793db86aabSstevel pci_config_get32(config_handle, 0x80)); 44803db86aabSstevel } 44813db86aabSstevel } 44823db86aabSstevel 44833db86aabSstevel static void 44843db86aabSstevel cardbus_dump_config(ddi_acc_handle_t config_handle) 44853db86aabSstevel { 44863db86aabSstevel uint8_t header_type = pci_config_get8(config_handle, 44873db86aabSstevel PCI_CONF_HEADER) & PCI_HEADER_TYPE_M; 44883db86aabSstevel 44893db86aabSstevel if (header_type == PCI_HEADER_PPB || header_type == PCI_HEADER_CARDBUS) 44903db86aabSstevel cardbus_dump_bridge_config(config_handle, header_type); 44913db86aabSstevel else 44923db86aabSstevel cardbus_dump_device_config(config_handle); 44933db86aabSstevel } 44943db86aabSstevel 44953db86aabSstevel static void 44963db86aabSstevel cardbus_dump_reg(dev_info_t *dip, const pci_regspec_t *regspec, int nelems) 44973db86aabSstevel { 44983db86aabSstevel /* int rlen = nelems * sizeof(pci_regspec_t); */ 44993db86aabSstevel 45003db86aabSstevel cardbus_err(dip, 6, 45013db86aabSstevel "cardbus_dump_reg: \"reg\" has %d elements\n", nelems); 45023db86aabSstevel 45033db86aabSstevel #if defined(CARDBUS_DEBUG) 45043db86aabSstevel if (cardbus_debug >= 1) { 45053db86aabSstevel int i; 45063db86aabSstevel uint32_t *regs = (uint32_t *)regspec; 45073db86aabSstevel 45083db86aabSstevel for (i = 0; i < nelems; i++) { 45093db86aabSstevel 45103db86aabSstevel cardbus_err(NULL, 6, 45113db86aabSstevel "\t%d:%08x %08x %08x %08x %08x\n", 45123db86aabSstevel i, regs[0], regs[1], regs[2], regs[3], regs[4]); 45133db86aabSstevel } 45143db86aabSstevel } 45153db86aabSstevel #endif 45163db86aabSstevel } 45173db86aabSstevel 45183db86aabSstevel #endif 45193db86aabSstevel 45203db86aabSstevel #if defined(CARDBUS_DEBUG) 45213db86aabSstevel void 45223db86aabSstevel cardbus_dump_children(dev_info_t *dip, int level) 45233db86aabSstevel { 45243db86aabSstevel dev_info_t *next; 45253db86aabSstevel 45263db86aabSstevel cardbus_err(dip, 1, 45273db86aabSstevel "\t%d: %s: 0x%p\n", level, ddi_node_name(dip), (void *) dip); 45283db86aabSstevel for (next = ddi_get_child(dip); next; 45293db86aabSstevel next = ddi_get_next_sibling(next)) 45303db86aabSstevel cardbus_dump_children(next, level + 1); 45313db86aabSstevel } 45323db86aabSstevel 45333db86aabSstevel void 45343db86aabSstevel cardbus_dump_family_tree(dev_info_t *dip) 45353db86aabSstevel { 45363db86aabSstevel cardbus_err(dip, 1, "0x%p family tree:\n", (void *) dip); 45373db86aabSstevel cardbus_dump_children(dip, 1); 45383db86aabSstevel } 45393db86aabSstevel #endif 4540