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