cardbus_cfg.c revision d577a05052763490983ba19d548a252fed6f75d9
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER START
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The contents of this file are subject to the terms of the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Common Development and Distribution License (the "License").
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You may not use this file except in compliance with the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * or http://www.opensolaris.org/os/licensing.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * See the License for the specific language governing permissions
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and limitations under the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * When distributing Covered Code, include this CDDL HEADER in each
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If applicable, add the following below this CDDL HEADER, with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner]
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER END
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald * Use is subject to license terms.
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal */
6319b0c72e1681f79a5f33dfa976a63eedd4a2a4Garrett D'Amore/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Copyright (c) * Copyright (c) 2001 Tadpole Technology plc
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * All rights reserved.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * From "@(#)pcicfg.c 1.31 99/06/18 SMI"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#pragma ident "%Z%%M% %I% %E% SMI"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Cardbus configurator
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/ddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sunndi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/ndi_impldefs.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/pci.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/ebus.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/hotplug/hpctrl.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/hotplug/pci/pcicfg.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/pctypes.h>
4558d122136f151d62acbbc02ddb42df89a5ef66Viswanathan Kannappan#include <sys/pcmcia.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sservice.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/isa_defs.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/note.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/ethernet.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include "cardbus.h"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include "cardbus_parse.h"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include "cardbus_cfg.h"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * ************************************************************************
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * *** Implementation specific local data structures/definitions. ***
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * ************************************************************************
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_MAX_DEVICE 32
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_MAX_FUNCTION 8
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic uint32_t pcicfg_max_device = PCICFG_MAX_DEVICE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic uint32_t pcicfg_max_function = PCICFG_MAX_FUNCTION;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_NODEVICE 42
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_NOMEMORY 43
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_NOMULTI 44
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_LADDR(lo, hi) (((uint64_t)(hi) << 32) | (uint32_t)(lo))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_HIWORD(n) ((uint16_t)(((uint32_t)(n) & 0xFFFF0000)>> 16))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_LOWORD(n) ((uint16_t)((uint32_t)(n) & 0x0000FFFF))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_HIBYTE(n) ((uint8_t)(((uint16_t)(n) & 0xFF00)>> 8))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_LOBYTE(n) ((uint8_t)((uint16_t)(n) & 0x00FF))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_ROUND_UP(addr, gran) ((uintptr_t)((gran+addr-1)&(~(gran-1))))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_ROUND_DOWN(addr, gran) ((uintptr_t)((addr) & ~(gran-1)))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_MEMGRAN 0x100000
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_IOGRAN 0x1000
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_4GIG_LIMIT 0xFFFFFFFFUL
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define CBCFG_MEMGRAN 0x1000
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define CBCFG_IOGRAN 0x4
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_MEM_MULT 4
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_IO_MULT 4
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_RANGE_LEN 2 /* Number of range entries */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
63528ae45fc8c92cddd3c3b0dc846a9be84f44acJames Moore * ISA node declaration structure.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstruct isa_node {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *name;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *compatible[5];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *type;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *model;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint16_t reg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint16_t span;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstruct cardbus_name_entry {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t class_code;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *name;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int pil;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstruct cardbus_find_ctrl {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t device;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t function;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dev_info_t *dip;
3fc1e17e160b171792527e6238216e3a602e8f8bPriya Krishnan};
3fc1e17e160b171792527e6238216e3a602e8f8bPriya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#define PCICFG_MAKE_REG_HIGH(busnum, devnum, funcnum, register)\
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (\
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((ulong_t)(busnum & 0xff) << 16) |\
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((ulong_t)(devnum & 0x1f) << 11) |\
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ((ulong_t)(funcnum & 0x7) << 8) |\
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ((ulong_t)(register & 0x3f)))
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnantypedef struct cardbus_phdl cardbus_phdl_t;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstruct cardbus_phdl {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan dev_info_t *dip; /* Associated with the attach point */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan dev_info_t *res_dip; /* dip from which io/mem is allocated */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_phdl_t *next;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint64_t memory_base; /* Memory base for this attach point */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint64_t memory_last;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint64_t memory_len;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint32_t memory_gran;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint32_t io_base; /* I/O base for this attach point */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint32_t io_last;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint32_t io_len;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint32_t io_gran;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int error;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint_t highest_bus; /* Highest bus seen on the probe */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ndi_ra_request_t mem_req; /* allocator request for memory */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ndi_ra_request_t io_req; /* allocator request for I/O */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlaptypedef struct {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dev_info_t *dip; /* Associated with the attach point */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t handle; /* open handle on parent PCI config space */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t io_base; /* I/O base for this attach point */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int io_decode_reg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap} isa_phdl_t;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * forward declarations for routines defined in this module (called here)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic cardbus_phdl_t *cardbus_find_phdl(dev_info_t *dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic cardbus_phdl_t *cardbus_create_phdl(dev_info_t *dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_destroy_phdl(dev_info_t *dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_program_ap(dev_info_t *);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic void cardbus_topbridge_assign(dev_info_t *, cardbus_phdl_t *);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic int cardbus_bridge_ranges(dev_info_t *, cardbus_phdl_t *,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ddi_acc_handle_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_bridge_assign(dev_info_t *, void *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_isa_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_add_isa_reg(dev_info_t *, void *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_allocate_chunk(dev_info_t *, uint8_t, uint8_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_free_chunk(dev_info_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_setup_bridge(dev_info_t *, cardbus_phdl_t *,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_update_bridge(dev_info_t *, cardbus_phdl_t *,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_get_mem(dev_info_t *, cardbus_phdl_t *, uint32_t,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_get_io(dev_info_t *, cardbus_phdl_t *, uint32_t,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_sum_resources(dev_info_t *, void *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_free_bridge_resources(dev_info_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_free_device_resources(dev_info_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_free_resources(dev_info_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_probe_bridge(cbus_t *, dev_info_t *, uint_t,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t, uint_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_probe_children(cbus_t *, dev_info_t *, uint_t, uint_t,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t, uint8_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_add_config_reg(dev_info_t *, uint_t, uint_t, uint_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_add_isa_node(cbus_t *, dev_info_t *, struct isa_node *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_config_setup(dev_info_t *, ddi_acc_handle_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_config_teardown(ddi_acc_handle_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_reparent_children(dev_info_t *, dev_info_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_update_assigned_prop(dev_info_t *, pci_regspec_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_update_available_prop(dev_info_t *, uint32_t,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t, uint64_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_update_ranges_prop(dev_info_t *, cardbus_range_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_update_reg_prop(dev_info_t *dip, uint32_t regvalue,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t reg_offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_set_standard_props(dev_info_t *parent, dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_set_isa_props(dev_info_t *parent, dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *name, char *compat[]);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_set_busnode_props(dev_info_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_set_busnode_isaprops(dev_info_t *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int cardbus_set_childnode_props(dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_set_bus_numbers(ddi_acc_handle_t config_handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t primary, uint_t secondary);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void enable_pci_isa_bridge(dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void enable_pci_pci_bridge(dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void enable_cardbus_bridge(dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void disable_pci_pci_bridge(dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void disable_cardbus_bridge(dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void enable_cardbus_device(dev_info_t *, ddi_acc_handle_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void disable_cardbus_device(ddi_acc_handle_t config_handle);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapstatic void cardbus_force_boolprop(dev_info_t *dip, char *pname);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapstatic void cardbus_force_intprop(dev_info_t *dip, char *pname,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap int *pval, int len);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapstatic void cardbus_force_stringprop(dev_info_t *dip, char *pname,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap char *pval);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapstatic void split_addr(char *, int *, int *);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef DEBUG
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_dump_common_config(ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_dump_device_config(ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_dump_bridge_config(ddi_acc_handle_t config_handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t header_type);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_dump_config(ddi_acc_handle_t config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void cardbus_dump_reg(dev_info_t *dip, const pci_regspec_t *regspec,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int nelems);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic cardbus_phdl_t *cardbus_phdl_list = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapstatic struct cardbus_name_entry cardbus_class_lookup [] = {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap { 0x001, "display", 9 },
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap { 0x100, "scsi", 4 },
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap { 0x101, "ide", 4 },
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap { 0x102, "fdc", 4 },
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap { 0x103, "ipi", 4 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x104, "raid", 4 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x200, "ethernet", 6 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x201, "token-ring", 6 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x202, "fddi", 6 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x203, "atm", 6 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x300, "display", 9 }, /* VGA card */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x380, "display", 9 }, /* other - for the Raptor Card */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x400, "video", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x401, "sound", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x500, "memory", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x501, "flash", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x600, "host", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x601, "isa", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x602, "eisa", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x603, "mca", 11 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x604, "pci", 11 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x605, "pcmcia", 11 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x606, "nubus", 11 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x607, "cardbus", 11 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x680, NULL, 8 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x700, "serial", 11 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x701, "parallel", 6 },
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States { 0x800, "interrupt-controller", 3 },
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States { 0x801, "dma-controller", 3 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x802, "timer", 3 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0x803, "rtc", 3 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x900, "keyboard", 8 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0x901, "pen", 8 },
3fc1e17e160b171792527e6238216e3a602e8f8bPriya Krishnan { 0x902, "mouse", 8 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0xa00, "dock", 1 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0xb00, "cpu", 1 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0xc00, "firewire", 9 },
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan { 0xc01, "access-bus", 4 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0xc02, "ssa", 4 },
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States { 0xc03, "usb", 9 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0xc04, "fibre-channel", 6 },
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap { 0, 0 }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifndef _DONT_USE_1275_GENERIC_NAMES
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic char *cardbus_get_class_name(uint32_t classcode);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif /* _DONT_USE_1275_GENERIC_NAMES */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Reprogram ILINE with default value only if BIOS doesn't program it
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_validate_iline(dev_info_t *dip, ddi_acc_handle_t handle)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t intline = 0xff;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_get8(handle, PCI_CONF_IPIN)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap intline = pci_config_get8(handle, PCI_CONF_ILINE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((intline == 0) || (intline == 0xff)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap intline = ddi_getprop(DDI_DEV_T_ANY, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "interrupt-line", 0xff);
3fc1e17e160b171792527e6238216e3a602e8f8bPriya Krishnan if (intline == (uint8_t)0xff) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan intline = ddi_getprop(DDI_DEV_T_ANY,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States ddi_get_parent(dip),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_CANSLEEP /* |DDI_PROP_DONTPASS */,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "interrupt-line", 0xb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put8(handle, PCI_CONF_ILINE, intline);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "interrupt-line", intline);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (intline);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This entry point is called to configure a device (and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * all its children) on the given bus. It is called when
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * a new device is added to the PCI domain. This routine
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * will create the device tree and program the devices
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * registers.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_configure(cbus_t *cbp)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int cardbus_dev, func;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dev_info_t *attach_point;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 6, "cardbus_configure ()\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus = cardbus_primary_busno(cbp->cb_dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_devi_alloc(cbp->cb_dip, DEVI_PSEUDO_NEXNAME,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (pnode_t)DEVI_SID_NODEID,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &attach_point) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_configure(): Failed to alloc probe node\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Node name marks this node as the "attachment point".
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_devi_set_nodename(attach_point,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "hp_attachment", 0) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to set nodename for attachment node\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_devi_free(attach_point);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(ddi_get_parent(attach_point), 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Set bus type to cardbus\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ddi_prop_update_string(DDI_DEV_T_NONE,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_get_parent(attach_point), PCM_DEVICETYPE,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap split_addr(ddi_get_name_addr(cbp->cb_dip), &cardbus_dev, &func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(attach_point, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Configuring [0x%x][0x%x][0x%x]\n", bus, cardbus_dev, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (cardbus_probe_bridge(cbp, attach_point,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus, cardbus_dev, func)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_FAILURE:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 4,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "configure failed: bus [0x%x] slot [0x%x] func [0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus, cardbus_dev, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto cleanup;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_NODEVICE:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 4,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "no device: bus [0x%x] slot [0x%x] func [0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus, cardbus_dev, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto cleanup;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States cardbus_err(cbp->cb_dip, 9,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "configure: bus => [%d] slot => [%d] func => [%d]\n",
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States bus, cardbus_dev, func);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States break;
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (cardbus_program_ap(cbp->cb_dip) == PCICFG_SUCCESS) {
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States (void) cardbus_reparent_children(attach_point, cbp->cb_dip);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States (void) ndi_devi_free(attach_point);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cbp->cb_nex_ops->enable_intr(cbp->cb_dip);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 1, "Failed to program devices\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcleanup:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Clean up a partially created "probe state" tree.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * There are no resources allocated to the in the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * probe state.
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Look up device [0x%x] function [0x%x] to clean up\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_dev, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Cleaning up device [0x%x] function [0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_dev, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If this was a bridge device it will have a
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * probe handle - if not, no harm in calling this.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_destroy_phdl(cbp->cb_dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ddi_get_child(attach_point)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This will free up the node
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_devi_offline(ddi_get_child(attach_point),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NDI_UNCONFIG|NDI_DEVI_REMOVE);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States (void) ndi_devi_free(attach_point);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_unconfigure(cbus_t *cbp)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dev_info_t *dip = cbp->cb_dip;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cbp->cb_nex_ops->disable_intr(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_setup(dip, &config_handle) == DDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap disable_cardbus_bridge(dip, config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pci_config_teardown(&config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_unconfigure(): Failed to setup config space\n");
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States }
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) cardbus_free_chunk(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_unconfigure: calling cardbus_free_bridge_resources\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_free_bridge_resources(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United Statesint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_teardown_device(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Free up resources associated with 'dip'
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_free_resources(dip) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_teardown_device: Failed to free resources\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_devi_offline(dip, NDI_DEVI_REMOVE) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_teardown_device: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to offline and remove node\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Get the primary pci bus number. This should be the lowest number
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in the bus-range property of our parent.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United Statescardbus_primary_busno(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int len, rval;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char bus_type[16] = "(unknown)";
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dev_info_t *par = ddi_get_parent(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_bus_range_t *bus_range;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(strcmp(ddi_driver_name(dip), "pcic") == 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap len = sizeof (bus_type);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((ddi_prop_op(DDI_DEV_T_ANY, par, PROP_LEN_AND_VAL_BUF,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "device_type",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (caddr_t)&bus_type, &len) == DDI_SUCCESS)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT((strcmp(bus_type, "pci") == 0) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (strcmp(bus_type, "cardbus") == 0));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ddi_getlongprop(DDI_DEV_T_ANY, par, 0, "bus-range",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (caddr_t)&bus_range, &len) == DDI_PROP_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 9,
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States "cardbus_primary_busno: bus range is %d to %d\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range->lo, bus_range->hi);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rval = (int)bus_range->lo;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free((caddr_t)bus_range, len);
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States return (rval);
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States }
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States }
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 2,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_primary_busno: Not a pci device or no bus-range\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic cardbus_phdl_t *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_find_phdl(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_phdl_t *entry;
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&cardbus_list_mutex);
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States for (entry = cardbus_phdl_list; entry != NULL; entry = entry->next) {
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States if (entry->dip == dip) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&cardbus_list_mutex);
fcc214c383d20beb968b623b83d851672e174702Charles Ting return (entry);
fcc214c383d20beb968b623b83d851672e174702Charles Ting }
fcc214c383d20beb968b623b83d851672e174702Charles Ting }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&cardbus_list_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Did'nt find entry - create one
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States */
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States return (cardbus_create_phdl(dip));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic cardbus_phdl_t *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_create_phdl(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_phdl_t *new;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new = (cardbus_phdl_t *)kmem_zalloc(sizeof (cardbus_phdl_t), KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States new->dip = dip;
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States new->io_gran = CBCFG_IOGRAN;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new->memory_gran = CBCFG_MEMGRAN;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&cardbus_list_mutex);
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States new->next = cardbus_phdl_list;
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States cardbus_phdl_list = new;
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&cardbus_list_mutex);
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (new);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United Statesstatic int
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United Statescardbus_destroy_phdl(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States cardbus_phdl_t *entry;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_phdl_t *follow = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ra_return_t res;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&cardbus_list_mutex);
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States for (entry = cardbus_phdl_list; entry != NULL; follow = entry,
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States entry = entry->next) {
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States if (entry->dip == dip) {
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States if (entry == cardbus_phdl_list) {
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States cardbus_phdl_list = entry->next;
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap follow->next = entry->next;
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If this entry has any allocated memory
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * or IO space associated with it, that
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * must be freed up.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (entry->memory_len > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap res.ra_addr_lo = entry->memory_base;
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States res.ra_len = entry->memory_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pcmcia_free_mem(entry->res_dip, &res);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_destroy_phdl: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "MEMORY BASE = [0x%lx] length [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_base, entry->memory_len);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "cardbus_destroy_phdl: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "MEMORY BASE = [0x%llx] length [0x%llx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_base, entry->memory_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (entry->io_len > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap res.ra_addr_lo = entry->io_base;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap res.ra_len = entry->io_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pcmcia_free_io(entry->res_dip, &res);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "cardbus_destroy_phdl: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "IO BASE = [0x%x] length [0x%x]\n",
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States entry->io_base, entry->io_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Destroy this entry
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States kmem_free((caddr_t)entry, sizeof (cardbus_phdl_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&cardbus_list_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&cardbus_list_mutex);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Didn't find the entry
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United Statesstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_program_ap(dev_info_t *dip)
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_phdl_t *phdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t header_type, sec_bus;
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States ddi_acc_handle_t handle;
07a2bfd1dc0b943009fd0adbf34cb344095e378fPeter Cudhea - Sun Microsystems - Burlington, MA United States
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_program_ap: Failed to map config space!\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap header_type = pci_config_get8(handle, PCI_CONF_HEADER);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sec_bus = pci_config_get8(handle, PCI_BCNF_SECBUS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_program_ap (header_type=0x%x)\n", header_type);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pci_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Header type two is PCI to Cardbus bridge, see page 43 of the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CL-PD6832 data sheet
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (header_type & PCI_HEADER_TYPE_M) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_HEADER_CARDBUS:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_program_ap calling cardbus_allocate_chunk\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_allocate_chunk(dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap header_type & PCI_HEADER_TYPE_M,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sec_bus) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_program_ap: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Not enough memory to hotplug\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_destroy_phdl(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_program_ap calling cardbus_find_phdl\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl = cardbus_find_phdl(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(phdl);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (phdl == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "cardbus_find_phdl failed\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->error = PCICFG_SUCCESS;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_program_ap calling cardbus_topbridge_assign\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_topbridge_assign(dip, phdl);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (phdl->error != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "Problem assigning bridge\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_destroy_phdl(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (phdl->error);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_topbridge_assign(dev_info_t *dip, cardbus_phdl_t *entry)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t handle;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t header_type;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6, "cardbus_topbridge_assign\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_topbridge_bridge_assign: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to map config space!\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap header_type = pci_config_get8(handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_HEADER) & PCI_HEADER_TYPE_M;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* cardbus bridge is the same as PCI-PCI bridge */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT((header_type == PCI_HEADER_PPB) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (header_type == PCI_HEADER_CARDBUS));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_bridge_ranges(dip, entry, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pci_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t handle)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_range_t range[PCICFG_RANGE_LEN];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int bus_range[2];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int count;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8, "cardbus_bridge_ranges\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero((caddr_t)range, sizeof (cardbus_range_t) * PCICFG_RANGE_LEN);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_setup_bridge(dip, entry, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range[0].child_hi = range[0].parent_hi |= (PCI_REG_REL_M | PCI_ADDR_IO);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range[0].child_lo = range[0].parent_lo = entry->io_last;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range[1].child_hi = range[1].parent_hi |= (PCI_REG_REL_M |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_ADDR_MEM32);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range[1].child_lo = range[1].parent_lo = entry->memory_last;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_enter(dip, &count);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_walk_devs(ddi_get_child(dip), cardbus_bridge_assign, (void *)entry);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_exit(dip, count);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_update_bridge(dip, entry, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range[0] = pci_config_get8(handle, PCI_BCNF_SECBUS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range[1] = pci_config_get8(handle, PCI_BCNF_SUBBUS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Set up bus-range property to %u->%u\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range[0], bus_range[1]);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((i = ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "bus-range",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range, 2)) != DDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (i == DDI_PROP_NOT_FOUND) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Create bus-range property, %u->%u\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range[0], bus_range[1]);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i = ddi_prop_create(DDI_DEV_T_NONE, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_CANSLEEP,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "bus-range", (caddr_t)bus_range,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan sizeof (bus_range));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (i != DDI_PROP_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to set bus-range property, %u->%u (%d)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range[0], bus_range[1], i);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (entry->io_len > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range[0].size_lo = entry->io_last - entry->io_base;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_update_ranges_prop(dip, &range[0])) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "Failed to update ranges (i/o)\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (entry->memory_len > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range[1].size_lo = entry->memory_last - entry->memory_base;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_update_ranges_prop(dip, &range[1])) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to update ranges (memory)\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_PRUNECHILD);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_bridge_assign(dev_info_t *dip, void *hdl)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t handle;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_regspec_t *reg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int length;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rcount;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int offset;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t mem_answer;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t io_answer, request;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t header_type, base_class;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_phdl_t *entry = (cardbus_phdl_t *)hdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Ignore the attachment point and pcs.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (strcmp(ddi_binding_name(dip), "hp_attachment") == 0 ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap strcmp(ddi_binding_name(dip), "pcs") == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8, "cardbus_bridge_assign: Ignoring\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_CONTINUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6, "cardbus_bridge_assign\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (entry == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "Failed to get entry\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_config_setup(dip, &handle) != DDI_SUCCESS) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_bridge_assign: Failed to map config space!\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap header_type = pci_config_get8(handle, PCI_CONF_HEADER) &
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_HEADER_TYPE_M;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap base_class = pci_config_get8(handle, PCI_CONF_BASCLASS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function is not called for the top bridge and we are
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * not enumerating down a further cardbus interface yet!
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (base_class == PCI_CLASS_BRIDGE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t sub_class;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (sub_class) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_PCI:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (header_type == PCI_HEADER_PPB) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i = cardbus_bridge_ranges(dip, entry, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (i);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto bad_device;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_ISA:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i = cardbus_isa_bridge_ranges(dip, entry, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (i);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_CARDBUS:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Fall through, there should be at least one register
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * set for this.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_OTHER:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef sparc
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If there is an interrupt pin set program
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * interrupt line with default values.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_get8(handle, PCI_CONF_IPIN)) {
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States#else
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States (void) cardbus_validate_iline(dip, handle);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States#endif
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States /*
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * A single device (under a bridge).
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * For each "reg" property with a length, allocate memory
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * and program the base registers.
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States */
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &length) != DDI_PROP_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "Failed to read reg property\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rcount = length / sizeof (pci_regspec_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 9, "rcount = %d\n", rcount);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0; i < rcount; i++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset = PCI_REG_REG_G(reg[i].pci_phys_hi);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_get_mem(ddi_get_parent(dip),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry, reg[i].pci_size_low, &mem_answer);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(!PCICFG_HIADDR(mem_answer));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, offset,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_LOADDR(mem_answer));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, offset + 4,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_HIADDR(mem_answer));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "REGISTER (64)LO [0x%x] ----> [0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(handle, offset), offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "REGISTER (64)HI [0x%x] ----> [0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(handle, offset+4),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset+4);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap reg[i].pci_phys_low = PCICFG_HIADDR(mem_answer);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap reg[i].pci_phys_mid = PCICFG_LOADDR(mem_answer);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* allocate memory space from the allocator */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) cardbus_get_mem(ddi_get_parent(dip),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan entry, reg[i].pci_size_low, &mem_answer);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan pci_config_put32(handle, offset, 0xffffffff);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan request = pci_config_get32(handle, offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, offset,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uint32_t)mem_answer);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap reg[i].pci_phys_low = (uint32_t)mem_answer;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap reg[i].pci_phys_mid = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (((PCI_BASE_TYPE_M & request) ==
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_BASE_TYPE_ALL) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((PCI_BASE_SPACE_M & request) ==
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_BASE_SPACE_MEM)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "REGISTER (64)LO [0x%x] ----> "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(handle, offset),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset + 4, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "REGISTER (64)HI [0x%x] ----> "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(handle, offset+4),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset+4);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "REGISTER (32)LO [0x%x] ----> "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(handle, offset),
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal offset);
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal }
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal break;
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal case PCI_REG_ADDR_G(PCI_ADDR_IO):
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal /* allocate I/O space from the allocator */
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal (void) cardbus_get_io(ddi_get_parent(dip),
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal entry, reg[i].pci_size_low, &io_answer);
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal pci_config_put32(handle, offset, io_answer);
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal cardbus_err(dip, 8,
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal "REGISTER (I/O)LO [0x%x] ----> [0x%02x]\n",
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal pci_config_get32(handle, offset), offset);
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal reg[i].pci_phys_low = io_answer;
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal break;
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "Unknown register type\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(reg, length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } /* switch */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Now that memory locations are assigned,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * update the assigned address property.
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap */
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap if (cardbus_update_assigned_prop(dip,
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap &reg[i]) != PCICFG_SUCCESS) {
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap kmem_free(reg, length);
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap (void) cardbus_config_teardown(&handle);
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap kmem_free(reg, length);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap enable_cardbus_device(dip, handle);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap#ifdef CARDBUS_DEBUG
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_debug >= 9) {
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap cardbus_dump_config(handle);
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapbad_device:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_CONTINUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_isa_bridge_ranges(dev_info_t *dip, cardbus_phdl_t *entry,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t handle)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap struct ebus_pci_rangespec range;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int count;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_regspec_t *reg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int length;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rcount;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t io_answer = 0xffffffff;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap isa_phdl_t isa_phdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8, "cardbus_isa_bridge_ranges\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero((caddr_t)&range, sizeof (range));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef sparc
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If there is an interrupt pin set program
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * interrupt line with default values.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_get8(handle, PCI_CONF_IPIN)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_validate_iline(dip, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * For each "reg" property with a length, allocate memory.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &length) != DDI_PROP_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "Failed to read reg property\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rcount = length / sizeof (pci_regspec_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0; i < rcount; i++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((reg[i].pci_size_low != 0) || (reg[i].pci_size_hi != 0)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (PCI_REG_ADDR_G(reg[i].pci_phys_hi)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_IO):
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* allocate I/O space from the allocator */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_get_io(ddi_get_parent(dip),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry, reg[i].pci_size_low, &io_answer);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "ISA (I/O)LO ----> [0x%x]\n", io_answer);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap reg[i].pci_phys_low = io_answer;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range.phys_hi = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range.phys_low = io_answer;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range.par_phys_hi = reg[i].pci_phys_hi |
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_REG_REL_M;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range.par_phys_low = reg[i].pci_phys_low;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range.par_phys_mid = reg[i].pci_phys_mid;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap range.rng_size = reg[i].pci_size_low;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i = rcount;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan default:
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(dip, 1, "Unknown register type\n");
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan kmem_free(reg, length);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan (void) cardbus_config_teardown(&handle);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan entry->error = PCICFG_FAILURE;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan return (DDI_WALK_TERMINATE);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan } /* switch */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan kmem_free(reg, length);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan (void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan dip, "ranges", (int *)&range,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan sizeof (range)/sizeof (int));
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan if (io_answer != 0xffffffff) {
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan isa_phdl.dip = dip;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan isa_phdl.handle = handle;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan isa_phdl.io_base = io_answer;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan isa_phdl.io_decode_reg = 0x58; /* Pos decoded IO space 0 reg */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /* i_ndi_block_device_tree_changes(&count); */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan ndi_devi_enter(dip, &count);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan ddi_walk_devs(ddi_get_child(dip),
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_add_isa_reg, (void *)&isa_phdl);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /* i_ndi_allow_device_tree_changes(count); */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan ndi_devi_exit(dip, count);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan return (DDI_WALK_PRUNECHILD);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan}
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan/*
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * This is specific to ITE8888 chip.
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnanstatic int
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnancardbus_add_isa_reg(dev_info_t *dip, void *arg)
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan{
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan uint32_t io_reg = 0;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan int length;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan uint32_t reg[3], *breg;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan isa_phdl_t *phdl;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan uint8_t sz;
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan phdl = (isa_phdl_t *)arg;
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan cardbus_err(dip, 6,
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan "cardbus_add_isa_reg, base 0x%x\n", phdl->io_base);
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan DDI_PROP_DONTPASS, "basereg", (caddr_t)&breg,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan &length) != DDI_PROP_SUCCESS) {
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan return (DDI_WALK_CONTINUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((length / sizeof (reg)) < 1) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(breg, length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_CONTINUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Add the "reg" property.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan reg[0] = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap reg[1] = breg[1] + phdl->io_base;
74f49fd455da72863376de7f46e076aa04893751Priya Krishnan reg[2] = breg[2];
74f49fd455da72863376de7f46e076aa04893751Priya Krishnan
74f49fd455da72863376de7f46e076aa04893751Priya Krishnan /*
74f49fd455da72863376de7f46e076aa04893751Priya Krishnan * Generate the postive IO decode register setting.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (sz = 0; sz < 8; sz++)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((1<<sz) >= breg[2]) {
74f49fd455da72863376de7f46e076aa04893751Priya Krishnan io_reg = breg[1]
74f49fd455da72863376de7f46e076aa04893751Priya Krishnan | (1uL <<31) /* Enable */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan | (2uL <<29) /* Medium speed */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap | (1uL <<28) /* Aliase enable, */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Don't care A[15:10] */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap | (sz<<24); /* Size code */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "reg", (int *)reg, 3);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "basereg");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan if (io_reg) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(phdl->handle, phdl->io_decode_reg, io_reg);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_add_isa_reg: I/O decode reg (0x%x) set to 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->io_decode_reg,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(phdl->handle, phdl->io_decode_reg));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->io_decode_reg += sizeof (io_reg);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap } else
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(dip, 1,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "cardbus_add_isa_reg: register size (0x%x) too large\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap breg[2]);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap kmem_free(breg, length);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap return (DDI_WALK_CONTINUE);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap}
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap/*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * In case we want to ensure that some space is allocated to the
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * device tree below the cardbus bridge.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * This is only necessary if there is a device that needs to allocate
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * resource below us. This can happen if there is another cardbus/PCMCIA
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * bridge downstream.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapstatic uint32_t cardbus_min_spare_mem = 0;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapstatic uint32_t cardbus_min_spare_io = 0;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap/*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * The "dip" passed to this routine is assumed to be
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * the device at the attachment point. Currently it is
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * assumed to be a bridge.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnanstatic int
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnancardbus_allocate_chunk(dev_info_t *dip, uint8_t type, uint8_t sec_bus)
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan{
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_phdl_t *phdl;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan ndi_ra_request_t *mem_request;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan ndi_ra_request_t *io_request;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan ra_return_t res;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan int count;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * This should not find an existing entry - so
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * it will create a new one.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap phdl = cardbus_find_phdl(dip);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap ASSERT(phdl);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mem_request = &phdl->mem_req;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap io_request = &phdl->io_req;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * Set highest_bus here.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * Otherwise if we don't find another bridge
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * this never gets set.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->highest_bus = sec_bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * From this point in the tree - walk the devices,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The function passed in will read and "sum" up
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the memory and I/O requirements and put them in
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * structure "phdl".
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap phdl->error = PCICFG_SUCCESS;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ndi_devi_enter(dip, &count);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States ddi_walk_devs(ddi_get_child(dip), cardbus_sum_resources, (void *)phdl);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ndi_devi_exit(dip, count);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (phdl->error != PCICFG_SUCCESS) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap cmn_err(CE_WARN, "Failure summing resources\n");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (phdl->error);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Call into the memory allocator with the request.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Record the addresses returned in the phdl
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "AP requires [0x%lx] bytes of memory space, alligned 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len, phdl->memory_gran);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "AP requires [0x%lx] bytes of I/O space, alligned 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len, phdl->io_gran);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "AP requires [0x%llx] bytes of memory space, alligned 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len, phdl->memory_gran);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "AP requires [0x%llx] bytes of I/O space, alligned 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len, phdl->io_gran);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore ASSERT(type == PCI_HEADER_CARDBUS);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore mem_request->ra_align_mask = phdl->memory_gran - 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_align_mask = phdl->io_gran - 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->res_dip = (dev_info_t *)-1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len += cardbus_min_spare_mem;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (mem_request->ra_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len = PCICFG_ROUND_UP(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->memory_gran);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_allocate_chunk: ndi_ra_alloc 0x%lx bytes\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_allocate_chunk: ndi_ra_alloc 0x%llx bytes\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pcmcia_alloc_mem(dip, mem_request, &res,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &phdl->res_dip) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cmn_err(CE_WARN, "Failed to allocate memory for %s\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_driver_name(dip));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->memory_base = phdl->memory_last = res.ra_addr_lo;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->memory_len = res.ra_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len += cardbus_min_spare_io;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (io_request->ra_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#if defined(__x86) || defined(__amd64)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_boundbase = 0x1000;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_boundlen = 0xefff;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_boundbase = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_boundlen = PCICFG_4GIG_LIMIT;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_flags |= NDI_RA_ALLOC_BOUNDED;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len = PCICFG_ROUND_UP(io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->io_gran);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_align_mask = max(PCICFG_IOGRAN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->io_gran) - 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pcmcia_alloc_io(dip, io_request, &res,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &phdl->res_dip) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cmn_err(CE_WARN, "Failed to allocate I/O space "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "for %s\n", ddi_driver_name(dip));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (mem_request->ra_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap res.ra_addr_lo = phdl->memory_base;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap res.ra_len = phdl->memory_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pcmcia_free_mem(phdl->res_dip, &res);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->memory_len = phdl->io_len = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->io_base = phdl->io_last = (uint32_t)res.ra_addr_lo;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->io_len = (uint32_t)res.ra_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "MEMORY BASE = [0x%lx] length [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->memory_base, phdl->memory_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "MEMORY BASE = [0x%llx] length [0x%llx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->memory_base, phdl->memory_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "IO BASE = [0x%x] length [0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap phdl->io_base, phdl->io_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_free_chunk(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t *bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int k;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6, "cardbus_free_chunk\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_destroy_phdl(dip);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &k) != DDI_PROP_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_free_chunk: Failed to read bus-range property\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_free_chunk: Freeing bus [%d] range [%d]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus[0], bus[1] - bus[0] + 1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_ra_free(dip,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (uint64_t)bus[0], (uint64_t)(bus[1] - bus[0] + 1),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan NDI_RA_TYPE_PCI_BUSNUM, NDI_RA_PASS) != NDI_SUCCESS) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_free_chunk: Failed to free bus numbers\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(bus, k);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free(bus, k);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_SUCCESS);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan/*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Put bridge registers into initial state
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic void
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_setup_bridge(dev_info_t *dip, cardbus_phdl_t *entry,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ddi_acc_handle_t handle)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint8_t header_type = pci_config_get8(handle, PCI_CONF_HEADER);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#ifdef _LP64
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(NULL, 6,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_setup_bridge: "
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "highest bus %d, mem_last 0x%lx, io_last 0x%x\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan entry->highest_bus, entry->memory_last, entry->io_last);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#else
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(NULL, 6,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_setup_bridge: "
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "highest bus %d, mem_last 0x%llx, io_last 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->highest_bus, entry->memory_last, entry->io_last);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t uval;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The highest bus seen during probing is
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the max-subordinate bus
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put8(handle, PCI_BCNF_SUBBUS, entry->highest_bus);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uval = PCICFG_ROUND_UP(entry->memory_last, PCICFG_MEMGRAN);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (uval != entry->memory_last) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Adding [0x%lx] before bridge (mem)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uval - entry->memory_last);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Adding [0x%llx] before bridge (mem)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uval - entry->memory_last);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_get_mem(ddi_get_parent(dip), entry,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uval - entry->memory_last, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan * Program the memory base register with the
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan * start of the memory range
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan */
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan#ifdef _LP64
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan cardbus_err(NULL, 8,
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan "store 0x%x(0x%lx) in pci bridge memory base register\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_HIWORD(PCICFG_LOADDR(uval)),
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore entry->memory_last);
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore#else
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore cardbus_err(NULL, 8,
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore "store 0x%x(0x%llx) in pci bridge memory base register\n",
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore PCICFG_HIWORD(PCICFG_LOADDR(uval)),
4142b486074471a886d6d0f0aa625a38b03d4ebaJames Moore entry->memory_last);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put16(handle, PCI_BCNF_MEM_BASE,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_HIWORD(PCICFG_LOADDR(uval)));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uval = PCICFG_ROUND_UP(entry->io_last, PCICFG_IOGRAN);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (uval != entry->io_last) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Adding [0x%x] before bridge (I/O)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uval - entry->io_last);
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan (void) cardbus_get_io(ddi_get_parent(dip), entry,
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan uval - entry->io_last, NULL);
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan }
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan cardbus_err(NULL, 8,
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan "store 0x%02x/0x%04x(0x%x) in "
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan "pci bridge I/O hi/low base register\n",
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan PCICFG_HIWORD(PCICFG_LOADDR(uval)),
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(uval))),
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan entry->io_last);
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan /*
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan * Program the I/O base register with the start of the I/O range
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan */
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan pci_config_put8(handle, PCI_BCNF_IO_BASE_LOW,
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(uval))));
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan pci_config_put16(handle, PCI_BCNF_IO_BASE_HI,
47715e7fd18d93fbdad6de94604baaa63665f0fbPriya Krishnan PCICFG_HIWORD(PCICFG_LOADDR(uval)));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Clear status bits
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put16(handle, PCI_BCNF_SEC_STATUS, 0xffff);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Turn off prefetchable range
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_BCNF_PF_BASE_LOW, 0x0000ffff);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_BCNF_PF_BASE_HIGH, 0xffffffff);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_BCNF_PF_LIMIT_HIGH, 0x0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef sparc
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If there is an interrupt pin set program
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * interrupt line with default values.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_get8(handle, PCI_CONF_IPIN)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
26ec4a22f5c6d9a66aa603d4a2182a2b95d15af9Priya Krishnan (void) cardbus_validate_iline(dip, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan } else if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_CARDBUS) {
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan /*
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan * The highest bus seen during probing is
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the max-subordinate bus
26ec4a22f5c6d9a66aa603d4a2182a2b95d15af9Priya Krishnan */
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan pci_config_put8(handle, PCI_CBUS_SUB_BUS_NO,
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan entry->highest_bus);
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan /*
01c0a610793607c653ebeb17728e674bb9d8a851Priya Krishnan * Program the memory base register with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * start of the memory range
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%x(0x%lx) in "
26ec4a22f5c6d9a66aa603d4a2182a2b95d15af9Priya Krishnan "cardbus memory base register 0, len 0x%lx\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_LOADDR(entry->memory_last), entry->memory_last,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%x(0x%llx) in "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus memory base register 0, len 0x%llx\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_LOADDR(entry->memory_last), entry->memory_last,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
26ec4a22f5c6d9a66aa603d4a2182a2b95d15af9Priya Krishnan pci_config_put32(handle, PCI_CBUS_MEM_BASE0,
26ec4a22f5c6d9a66aa603d4a2182a2b95d15af9Priya Krishnan PCICFG_LOADDR(entry->memory_last));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Program the I/O base register with the start of the I/O range
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%x in cb IO base register 0 len 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_LOADDR(entry->io_last),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->io_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_CBUS_IO_BASE0,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_LOADDR(entry->io_last));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Clear status bits
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put16(handle, PCI_CBUS_SEC_STATUS, 0xffff);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef sparc
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If there is an interrupt pin set program
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * interrupt line with default values.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_get8(handle, PCI_CONF_IPIN)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put8(handle, PCI_CONF_ILINE, 0xf);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_validate_iline(dip, handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * LATER: use these registers
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_CBUS_MEM_BASE1, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_CBUS_MEM_LIMIT1, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_CBUS_IO_BASE1, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_CBUS_IO_LIMIT1, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cmn_err(CE_WARN, "header type 0x%x, probably unknown bridge\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap header_type & PCI_HEADER_TYPE_M);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 7, "cardbus_setup_bridge complete\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlapstatic void
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlapcardbus_update_bridge(dev_info_t *dip, cardbus_phdl_t *entry,
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap ddi_acc_handle_t handle)
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap{
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap uint_t length;
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap uint16_t word16 = pci_config_get16(handle, PCI_CONF_COMM);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap const uint8_t header_type = pci_config_get8(handle, PCI_CONF_HEADER)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap & PCI_HEADER_TYPE_M;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t bridge_gran;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t rlval;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan if (header_type == PCI_HEADER_CARDBUS)
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan bridge_gran = CBCFG_MEMGRAN;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan else
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan bridge_gran = PCICFG_MEMGRAN;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /*
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * Program the memory limit register with the end of the memory range
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan#ifdef _LP64
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_update_bridge: Mem base 0x%lx len 0x%lx "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "last 0x%lx gran 0x%x gran end 0x%lx\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_base, entry->memory_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last, entry->memory_gran,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(entry->memory_last, entry->memory_gran));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_update_bridge: Mem base 0x%llx len 0x%llx "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "last 0x%llx gran 0x%x gran end 0x%lx\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan entry->memory_base, entry->memory_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last, entry->memory_gran,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(entry->memory_last, entry->memory_gran));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Since this is a bridge, the rest of this range will
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * be responded to by the bridge. We have to round up
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * so no other device claims it.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan length = PCICFG_ROUND_UP(entry->memory_last + cardbus_min_spare_mem,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bridge_gran) - entry->memory_last;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (length > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This is to allow space that isn't actually being used by
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * anything to be allocated by devices such as a downstream
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * PCMCIA controller.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_get_mem(dip, entry, length, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Added [0x%x] at the top of the bridge (mem)\n", length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (entry->memory_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (header_type == PCI_HEADER_CARDBUS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rlval = PCICFG_ROUND_DOWN(entry->memory_last - 1,
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap CBCFG_MEMGRAN);
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap#ifdef _LP64
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap cardbus_err(dip, 8,
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap "store 0x%x(0x%lx) in memory limit register 0\n",
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap PCICFG_LOADDR(rlval), rlval);
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap#else
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%x(0x%llx) in memory limit register 0\n",
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan PCICFG_LOADDR(rlval), rlval);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan#endif
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan pci_config_put32(handle, PCI_CBUS_MEM_LIMIT0,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan PCICFG_LOADDR(rlval));
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rlval = PCICFG_ROUND_DOWN(entry->memory_last - 1,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan PCICFG_MEMGRAN);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan#ifdef _LP64
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan cardbus_err(dip, 8,
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan "store 0x%x(0x%lx) in memory limit register\n",
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan rlval);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan#else
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(dip, 8,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "store 0x%x(0x%llx) in memory limit register\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan rlval);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan pci_config_put16(handle, PCI_BCNF_MEM_LIMIT,
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan PCICFG_HIWORD(PCICFG_LOADDR(rlval)));
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan }
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan word16 |= PCI_COMM_MAE;
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan }
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan cardbus_err(dip, 6,
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan "cardbus_update_bridge: I/O base 0x%x len 0x%x last 0x%x "
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan "gran 0x%x gran_end 0x%lx\n",
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan entry->io_base, entry->io_len, entry->io_last, entry->io_gran,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(entry->io_last, entry->io_gran));
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (header_type == PCI_HEADER_CARDBUS)
63528ae45fc8c92cddd3c3b0dc846a9be84f44acJames Moore bridge_gran = CBCFG_IOGRAN;
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan else
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan bridge_gran = PCICFG_IOGRAN;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Same as above for I/O space. Since this is a
70a38f022809785150671c14c5ed29eeaf0de287Priya Krishnan * bridge, the rest of this range will be responded
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to by the bridge. We have to round up so no
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * other device claims it.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap length = PCICFG_ROUND_UP(entry->io_last + cardbus_min_spare_io,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bridge_gran) - entry->io_last;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (length > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_get_io(dip, entry, length, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Added [0x%x] at the top of the bridge (I/O)\n", length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Program the I/O limit register with the end of the I/O range
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (entry->io_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (header_type == PCI_HEADER_CARDBUS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rlval = PCICFG_ROUND_DOWN(entry->io_last - 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap CBCFG_IOGRAN);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%lx in IO limit register 0\n", rlval);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%llx in IO limit register 0\n", rlval);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(handle, PCI_CBUS_IO_LIMIT0, rlval);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rlval = PCICFG_ROUND_DOWN(entry->io_last - 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%x/0x%x(0x%lx) in "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "IO limit low/hi register\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rlval);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "store 0x%x/0x%x(0x%llx) in "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "IO limit low/hi register\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))),
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_HIWORD(PCICFG_LOADDR(rlval)),
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap rlval);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap#endif
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_put8(handle, PCI_BCNF_IO_LIMIT_LOW,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_HIBYTE(PCICFG_LOWORD(PCICFG_LOADDR(rlval))));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_put16(handle, PCI_BCNF_IO_LIMIT_HI,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_HIWORD(PCICFG_LOADDR(rlval)));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap word16 |= PCI_COMM_IO;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put16(handle, PCI_CONF_COMM, word16);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_get_mem(dev_info_t *dip, cardbus_phdl_t *entry,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t length, uint64_t *ans)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan uint32_t hole;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_get_mem: memory_last 0x%lx, length 0x%x, "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "memory_base 0x%lx, memory_len 0x%lx ans=0x%p\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last, length,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan entry->memory_base, entry->memory_len, (void *) ans);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_get_mem: memory_last 0x%llx, length 0x%x, "
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan "memory_base 0x%llx, memory_len 0x%llx ans=0x%p\n",
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan entry->memory_last, length,
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan entry->memory_base, entry->memory_len, (void *) ans);
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan#endif
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan if (ans) {
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan /*
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan * Round up the request to the "size" boundary
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan */
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan hole = PCICFG_ROUND_UP(entry->memory_last, length)
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan - entry->memory_last;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (hole != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_update_available_prop(dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_ADDR_MEM32,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uint64_t)hole);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last += hole;
63528ae45fc8c92cddd3c3b0dc846a9be84f44acJames Moore
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_get_mem: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "rounded memory_last up by 0x%x to 0x%lx, ",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap hole, entry->memory_last);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_get_mem: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "rounded memory_last up by 0x%x to 0x%llx, ",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap hole, entry->memory_last);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan } else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_update_available_prop(dip, PCI_ADDR_MEM32,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uint64_t)length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * These routines should parcel out the memory
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * completely. There should never be a case of
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * over running the bounds.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((entry->memory_last + length) >
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (entry->memory_base + entry->memory_len))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_get_mem: assert will fail %ld <= %ld,"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "(0x%lx + 0x%x) <= (0x%lx + 0x%lx)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan cardbus_err(NULL, 1,
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan "cardbus_get_mem: assert will fail %lld <= %lld, "
1d7b78a3ad3ba3aedee339128153e8f515cb6f1cPriya Krishnan "(0x%llx + 0x%x) <= (0x%llx + 0x%llx)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last + length,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_base + entry->memory_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_last,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap length,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_base,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT((entry->memory_last + length) <=
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (entry->memory_base + entry->memory_len));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If ans is NULL don't return anything,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * they are just asking to reserve the memory.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ans != NULL)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *ans = entry->memory_last;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Increment to the next location
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap entry->memory_last += length;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_get_io(dev_info_t *dip, cardbus_phdl_t *entry,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t length, uint32_t *ans)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t hole;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_get_io: io_last 0x%x, length 0x%x, "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "io_base 0x%x, io_len 0x%x ans=0x%p\n",
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap entry->io_last, length,
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap entry->io_base, entry->io_len, (void *) ans);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ans) {
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap /*
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap * Round up the request to the "size" boundary
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap */
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap hole = PCICFG_ROUND_UP(entry->io_last, length) - entry->io_last;
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap if (hole != 0) {
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap (void) cardbus_update_available_prop(dip, PCI_ADDR_IO,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uint64_t)entry->io_last,
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap (uint64_t)hole);
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap entry->io_last += hole;
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap cardbus_err(NULL, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_get_io: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "rounded io_last up by 0x%x to 0x%x, ",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap hole, entry->io_last);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_update_available_prop(dip, PCI_ADDR_IO,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uint64_t)entry->io_last,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (uint64_t)length);
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * These routines should parcel out the memory
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * completely. There should never be a case of
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap * over running the bounds.
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap */
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap ASSERT((entry->io_last + length) <=
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap (entry->io_base + entry->io_len));
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If ans is NULL don't return anything,
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap * they are just asking to reserve the memory.
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap */
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap if (ans != NULL)
bf604c6405d5cbc4e94e3d0ecc9e6e074ed4ea67Peter Dunlap *ans = entry->io_last;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Increment to the next location
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->io_last += length;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_sum_resources(dev_info_t *dip, void *hdl)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_phdl_t *entry = (cardbus_phdl_t *)hdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_regspec_t *pci_rp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int length;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rcount;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i, ret;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_ra_request_t *mem_request;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_ra_request_t *io_request;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t header_type, base_class;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t handle;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Ignore the attachment point and pcs.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (strcmp(ddi_binding_name(dip), "hp_attachment") == 0 ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap strcmp(ddi_binding_name(dip), "pcs") == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8, "cardbus_sum_resources: Ignoring\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_CONTINUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request = &entry->mem_req;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request = &entry->io_req;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_config_setup(dip, &handle) != DDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_sum_resources: Failed to map config space!\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ret = DDI_WALK_CONTINUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap header_type = pci_config_get8(handle, PCI_CONF_HEADER);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap base_class = pci_config_get8(handle, PCI_CONF_BASCLASS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * If its a bridge - just record the highest bus seen
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (base_class == PCI_CLASS_BRIDGE) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap uint8_t sub_class;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (sub_class) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_PCI:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((header_type & PCI_HEADER_TYPE_M)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap == PCI_HEADER_PPB) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (entry->highest_bus < pci_config_get8(handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_BCNF_SECBUS)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->highest_bus = pci_config_get8(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap handle, PCI_BCNF_SECBUS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#if defined(CARDBUS_DEBUG)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (mem_request->ra_len !=
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Pre-align [0x%lx] to PCI bridge "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "memory gran "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%lx] -> [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN) -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Pre-align [0x%llx] to PCI bridge "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "memory gran "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%llx] -> [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN) -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (io_request->ra_len !=
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Pre-align [0x%lx] to PCI bridge "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "I/O gran "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%lx] -> [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN) -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#else
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Pre-align [0x%llx] to PCI bridge "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "I/O gran "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%llx] -> [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN) -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len = PCICFG_ROUND_UP(
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan mem_request->ra_len,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCICFG_MEMGRAN);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan io_request->ra_len = PCICFG_ROUND_UP(
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan io_request->ra_len,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCICFG_IOGRAN);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (entry->memory_gran < PCICFG_MEMGRAN)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan entry->memory_gran = PCICFG_MEMGRAN;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (entry->io_gran < PCICFG_IOGRAN)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan entry->io_gran = PCICFG_IOGRAN;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ddi_walk_devs(ddi_get_child(dip),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_sum_resources,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void *)entry);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#if defined(CARDBUS_DEBUG)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (mem_request->ra_len !=
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_min_spare_mem, PCICFG_MEMGRAN)) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Post-align [0x%lx] to PCI bridge "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "memory gran "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%lx] -> [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_min_spare_mem,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN) -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap + cardbus_min_spare_mem,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap#else
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(dip, 8,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "Post-align [0x%llx] to PCI bridge "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "memory gran "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%llx] -> [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_min_spare_mem,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN) -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap + cardbus_min_spare_mem,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_MEMGRAN));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (io_request->ra_len !=
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_min_spare_io,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#ifdef _LP64
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Post-align [0x%lx] to PCI bridge "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "I/O gran "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%lx] -> [0x%lx]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_min_spare_io,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN) -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_min_spare_io,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_IOGRAN));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap#else
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(dip, 8,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "Post-align [0x%llx] to PCI bridge "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "I/O gran "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "[0x%llx] -> [0x%lx]\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_ROUND_UP(io_request->ra_len +
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_min_spare_io,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_IOGRAN) -
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap io_request->ra_len,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap io_request->ra_len,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_ROUND_UP(io_request->ra_len +
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_min_spare_io,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_IOGRAN));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap#endif
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap#endif
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mem_request->ra_len = PCICFG_ROUND_UP(
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap mem_request->ra_len +
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_min_spare_mem,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_MEMGRAN);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap io_request->ra_len = PCICFG_ROUND_UP(
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap io_request->ra_len +
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_min_spare_io,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCICFG_IOGRAN);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap return (DDI_WALK_PRUNECHILD);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap case PCI_BRIDGE_CARDBUS:
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * Cardbus has I/O registers.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_ISA:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * All the registers requirements for ISA
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * are stored in the reg structure of the bridge.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Children of ISA are not of type PCI
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * so must not come through here because
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * cardbus_config_setup() will fail.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap ret = DDI_WALK_PRUNECHILD;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Treat other bridges as leaf nodes.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &length) != DDI_PROP_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If one node in (the subtree of nodes)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * does'nt have a "reg" property fail the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * allocation.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_len = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->io_len = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->error = PCICFG_FAILURE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (DDI_WALK_TERMINATE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * For each "reg" property with a length, add that to the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * total memory (or I/O) to allocate.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rcount = length / sizeof (pci_regspec_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0; i < rcount; i++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (PCI_REG_ADDR_G(pci_rp[i].pci_phys_hi)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "ADDING 32 --->0x%x for BAR@0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_REG_REG_G(pci_rp[i].pci_phys_hi));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the granualarity needs to be the larger of
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the maximum amount of memory that we're going to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * ask for, and the PCI-PCI bridge granularity (1M)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_rp[i].pci_size_low > entry->memory_gran)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->memory_gran = pci_rp[i].pci_size_low;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mem_request->ra_len =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(mem_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "ADDING 64 --->0x%x for BAR@0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_REG_REG_G(pci_rp[i].pci_phys_hi));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a668b114487acbb725f522170849c39f8e844673Priya Krishnan if (pci_rp[i].pci_size_low > entry->memory_gran)
a668b114487acbb725f522170849c39f8e844673Priya Krishnan entry->memory_gran = pci_rp[i].pci_size_low;
a668b114487acbb725f522170849c39f8e844673Priya Krishnan break;
a668b114487acbb725f522170849c39f8e844673Priya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_IO):
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap io_request->ra_len =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCICFG_ROUND_UP(io_request->ra_len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "ADDING I/O --->0x%x for BAR@0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_rp[i].pci_size_low,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_REG_REG_G(pci_rp[i].pci_phys_hi));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_rp[i].pci_size_low > entry->io_gran)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap entry->io_gran = pci_rp[i].pci_size_low;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Config space register - not included */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * free the memory allocated by ddi_getlongprop
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(pci_rp, length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * continue the walk to the next sibling to sum memory
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&handle);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan
a668b114487acbb725f522170849c39f8e844673Priya Krishnan#ifdef _LP64
a668b114487acbb725f522170849c39f8e844673Priya Krishnan cardbus_err(dip, 8,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan "Memory 0x%lx bytes, I/O 0x%lx bytes, "
a668b114487acbb725f522170849c39f8e844673Priya Krishnan "Memgran 0x%x, IOgran 0x%x\n",
a668b114487acbb725f522170849c39f8e844673Priya Krishnan mem_request->ra_len, io_request->ra_len,
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan entry->memory_gran, entry->io_gran);
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan#else
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan cardbus_err(dip, 8,
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan "Memory 0x%llx bytes, I/O 0x%llx bytes, "
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan "Memgran 0x%x, IOgran 0x%x\n",
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan mem_request->ra_len, io_request->ra_len,
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan entry->memory_gran, entry->io_gran);
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan#endif
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan
a668b114487acbb725f522170849c39f8e844673Priya Krishnan return (ret);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan}
a668b114487acbb725f522170849c39f8e844673Priya Krishnan
a668b114487acbb725f522170849c39f8e844673Priya Krishnan/*
a668b114487acbb725f522170849c39f8e844673Priya Krishnan * Free resources allocated to a bridge.
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan * Note that this routine does not call ndi_ra_free() to actually
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * free memory/IO/Bus. This is done as a single chunk for the entire
3badd8538576443eb4ff1566830fc1755924a88cPriya Krishnan * device tree in cardbus_free_chunk().
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_free_bridge_resources(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_range_t *ranges;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t *bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int k;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int length;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
241996a3debb0b7690aef018488c76770d83311eDan McDonald cardbus_err(dip, 6, "cardbus_free_bridge_resources\n");
241996a3debb0b7690aef018488c76770d83311eDan McDonald
241996a3debb0b7690aef018488c76770d83311eDan McDonald if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
241996a3debb0b7690aef018488c76770d83311eDan McDonald DDI_PROP_DONTPASS, "ranges", (caddr_t)&ranges,
241996a3debb0b7690aef018488c76770d83311eDan McDonald &length) == DDI_PROP_SUCCESS) {
241996a3debb0b7690aef018488c76770d83311eDan McDonald for (i = 0; i < length / sizeof (cardbus_range_t); i++) {
241996a3debb0b7690aef018488c76770d83311eDan McDonald if (ranges[i].size_lo != 0 || ranges[i].size_hi != 0) {
241996a3debb0b7690aef018488c76770d83311eDan McDonald switch (ranges[i].parent_hi & PCI_REG_ADDR_M) {
241996a3debb0b7690aef018488c76770d83311eDan McDonald case PCI_ADDR_IO:
241996a3debb0b7690aef018488c76770d83311eDan McDonald cardbus_err(dip, 6,
241996a3debb0b7690aef018488c76770d83311eDan McDonald "Need to Free I/O "
241996a3debb0b7690aef018488c76770d83311eDan McDonald "base/length = [0x%x]/[0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ranges[i].child_lo,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ranges[i].size_lo);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_ADDR_MEM32:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_ADDR_MEM64:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Need to Free Memory base/length = "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%x.%x]/[0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ranges[i].child_mid,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ranges[i].child_lo,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ranges[i].size_lo);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Unknown memory space\n");
6319b0c72e1681f79a5f33dfa976a63eedd4a2a4Garrett D'Amore break;
6319b0c72e1681f79a5f33dfa976a63eedd4a2a4Garrett D'Amore }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(ranges, length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "ranges");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan } else {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 8,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_free_bridge_resources: Failed"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "to read ranges property\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan DDI_PROP_DONTPASS, "bus-range", (caddr_t)&bus,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan &k) != DDI_PROP_SUCCESS) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 6, "Failed to read bus-range property\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 6,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "Need to free bus [%d] range [%d]\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan bus[0], bus[1] - bus[0] + 1);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free(bus, k);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "available");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, "bus-range");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_SUCCESS);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic int
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_free_device_resources(dev_info_t *dip)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan pci_regspec_t *assigned;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int length;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int acount;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int i;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DDI_PROP_DONTPASS, "assigned-addresses",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (caddr_t)&assigned,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &length) != DDI_PROP_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to read assigned-addresses property\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * For each "assigned-addresses" property entry with a length,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * call the memory allocation routines to return the
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * resource.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap acount = length / sizeof (pci_regspec_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0; i < acount; i++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Free the resource if the size of it is not zero.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((assigned[i].pci_size_low != 0)||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (assigned[i].pci_size_hi != 0)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (PCI_REG_ADDR_G(assigned[i].pci_phys_hi)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cardbus_err(dip, 6,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "Need to return 0x%x of 32 bit MEM space"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " @ 0x%x from register 0x%x\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap assigned[i].pci_size_low,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap assigned[i].pci_phys_low,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_REG_REG_G(assigned[i].pci_phys_hi));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan break;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(dip, 6,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "Need to return 0x%x of 64 bit MEM space"
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan " @ 0x%x.%x from register 0x%x\n",
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan assigned[i].pci_size_low,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap assigned[i].pci_phys_mid,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap assigned[i].pci_phys_low,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_REG_REG_G(assigned[i].pci_phys_hi));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap case PCI_REG_ADDR_G(PCI_ADDR_IO):
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cardbus_err(dip, 6,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "Need to return 0x%x of IO space @ 0x%x"
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap " from register 0x%x\n",
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap assigned[i].pci_size_low,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap assigned[i].pci_phys_low,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap PCI_REG_REG_G(assigned[i].pci_phys_hi));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap break;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap default:
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cardbus_err(dip, 1, "Unknown register type\n");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap kmem_free(assigned, length);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (PCICFG_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } /* switch */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(assigned, length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_free_resources(dev_info_t *dip)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan uint32_t classcode;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan classcode = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "class-code", -1);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /*
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * A different algorithim is used for bridges and leaf devices.
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (classcode != -1) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap classcode = ((uint_t)classcode & 0xffff00) >> 8;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (classcode == 0x604 || classcode == 0x607) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (cardbus_free_bridge_resources(dip)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap != PCICFG_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cardbus_err(dip, 1,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "Failed freeing up bridge resources\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_free_device_resources(dip) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(dip, 1, "Failed freeing up device resources\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_probe_bridge(cbus_t *cbp, dev_info_t *attpt, uint_t bus,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t device, uint_t func)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Declairations */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_bus_range_t *bus_range;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i, j;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t header_type;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_ra_request_t req;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t new_bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t blen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t next_bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int circ;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_probe_bridge bus %d device %d func %d\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus, device, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_enter(cbp->cb_dip, &circ);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pci_config_setup(cbp->cb_dip, &config_handle) != DDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 1,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "cardbus_probe_bridge(): Failed to setup config space\n");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ndi_devi_exit(cbp->cb_dip, circ);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (PCICFG_FAILURE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * As soon as we have access to config space, check device
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * is a bridge.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((header_type & PCI_HEADER_TYPE_M) != PCI_HEADER_CARDBUS)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failed;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "---Vendor ID = [0x%04x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get16(config_handle, PCI_CONF_VENID));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "---Device ID = [0x%04x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get16(config_handle, PCI_CONF_DEVID));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* say what type of header */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "--%s bridge found root bus [0x%x] device [0x%x] func [0x%x]\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) ?
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "PCI-PCI" : "Cardbus",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan bus, device, func);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ddi_getlongprop(DDI_DEV_T_ANY, cbp->cb_dip, 0, "bus-range",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (caddr_t)&bus_range, &i) != DDI_PROP_SUCCESS)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "No bus-range property seems to have been set up\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan else {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(cbp->cb_dip, 8,
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal "allowable bus range is %u->%u\n",
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal bus_range->lo, bus_range->hi);
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal kmem_free((caddr_t)bus_range, i);
a481fa48e4b49ab092647a92bb0ea0edf9afc5ceRick McNeal }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Get next bus in sequence and program device.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap req.ra_len = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_ra_alloc(cbp->cb_dip, &req,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &next_bus, &blen, NDI_RA_TYPE_PCI_BUSNUM,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NDI_RA_PASS) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cmn_err(CE_WARN, "Failed to get a bus number\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failed;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_bus = next_bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "NEW bus found [%u]->[%u]\n", bus, new_bus);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_set_bus_numbers(config_handle, bus, new_bus);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Enable it all */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap enable_cardbus_bridge(cbp->cb_dip, config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Probe all children devices
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0; i < pcicfg_max_device; i++)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (j = 0; j < pcicfg_max_function; j++)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (cardbus_probe_children(cbp, attpt, new_bus, i,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap j, &header_type)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_FAILURE:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(cbp->cb_dip, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to configure bus "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%x] device [0x%x] func [0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_bus, i, j);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap disable_cardbus_bridge(cbp->cb_dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failed;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_NODEVICE:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * if there's no function 0
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * there's no point in probing other
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * functions
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (j != 0)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* FALLTHROUGH */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_NOMULTI:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap j = pcicfg_max_function;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pci_config_teardown(&config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) i_ndi_config_node(attpt, DS_LINKED, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_exit(cbp->cb_dip, circ);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapfailed:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) pci_config_teardown(&config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_exit(cbp->cb_dip, circ);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic struct isa_node isa_nodes[] = {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap {"dummy", {NULL, NULL, NULL, NULL, NULL}, "serial", "", 0x4e, 0x2}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_probe_children(cbus_t *cbp, dev_info_t *parent, uint_t bus,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t device, uint_t func, uint8_t *header_type)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dev_info_t *new_child;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ddi_acc_handle_t config_handle;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i, j;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_ra_request_t req;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t next_bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint64_t blen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t request;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t base_class;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t new_bus;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int ret;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int circ;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 6,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_probe_children bus %d device %d func %d\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus, device, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This node will be put immediately below
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * "parent". Allocate a blank device node. It will either
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * be filled in or freed up based on further probing.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_enter(parent, &circ);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (pnode_t)DEVI_SID_NODEID,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &new_child) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_probe_children(): Failed to alloc child node\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_exit(parent, circ);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_add_config_reg(new_child, bus,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap device, func) != DDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_probe_children(): Failed to add candidate REG\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedconfig;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((ret = cardbus_config_setup(new_child, &config_handle))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ret == PCICFG_NODEVICE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_devi_free(new_child);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (ret);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_probe_children(): Failed to setup config space\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedconfig;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap base_class = pci_config_get8(config_handle, PCI_CONF_BASCLASS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (func == 0) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * Preserve the header type from function 0.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * Additional functions may not preserve the PCI_HEADER_MULTI
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * bit.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else if (!(*header_type & PCI_HEADER_MULTI) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((*header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (base_class == PCI_CLASS_BRIDGE)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_devi_free(new_child);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_NOMULTI);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /*
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * As soon as we have access to config space,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * turn off device. It will get turned on
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * later (after memory is assigned).
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * not if it's a cardbus device. It may be OK to leave
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * it on - try LATER
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap disable_cardbus_device(config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Set 1275 properties common to all devices
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_set_standard_props(parent, new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap config_handle) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 1, "Failed to set standard properties\n");
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Child node properties NOTE: Both for PCI-PCI bridge and child node
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_set_childnode_props(new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap config_handle) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "---Vendor ID = [0x%04x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get16(config_handle, PCI_CONF_VENID));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "---Device ID = [0x%04x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get16(config_handle, PCI_CONF_DEVID));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (base_class == PCI_CLASS_BRIDGE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t sub_class;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sub_class = pci_config_get8(config_handle, PCI_CONF_SUBCLASS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (sub_class) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_PCI:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((*header_type & PCI_HEADER_TYPE_M)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap == PCI_HEADER_PPB) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_bus_range_t *bus_range;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan int k;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /* say what type of header */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(parent, 8,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "-- Found PCI-PCI bridge @ "
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan " bus [0x%x] device [0x%x] func [0x%x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus, device, func);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ddi_getlongprop(DDI_DEV_T_ANY,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_child, 0, "bus-range",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (caddr_t)&bus_range,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &k) != DDI_PROP_SUCCESS)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(new_child, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "No bus-range property"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " seems to have been set up\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(new_child, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "allowable bus range is %u->%u\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus_range->lo, bus_range->hi);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free((caddr_t)bus_range, k);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Get next bus in sequence and program device.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero((caddr_t)&req, sizeof (ndi_ra_request_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap req.ra_len = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_ra_alloc(new_child, &req,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &next_bus, &blen,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NDI_RA_TYPE_PCI_BUSNUM,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NDI_RA_PASS) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cmn_err(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to get a bus number\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan goto failedchild;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan new_bus = next_bus;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(new_child, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "NEW bus found [%u]->[%u]\n", bus, new_bus);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Enable it all */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap enable_pci_pci_bridge(new_child, config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_set_bus_numbers(config_handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bus, new_bus);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#if defined(CARDBUS_DEBUG)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_debug >= 9) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_dump_config(config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Set bus properties
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (cardbus_set_busnode_props(new_child)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(new_child, 1,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "Failed to set busnode props\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan disable_pci_pci_bridge(new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Probe all children devices
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0; i < pcicfg_max_device; i++)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (j = 0; j < pcicfg_max_function;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap j++)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (cardbus_probe_children(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cbp,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan new_child,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan new_bus, i,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap j, header_type)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_FAILURE:
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(parent, 1,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "Failed to "
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "configure "
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "bus [0x%x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "device [0x%x] "
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "func [0x%x]\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan new_bus, i, j);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan disable_pci_pci_bridge(
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan new_child,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_NODEVICE:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * if there's no
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * function 0
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * there's no point in
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * probing other
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * functions
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (j != 0)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* FALLTHROUGH */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_NOMULTI:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap j = pcicfg_max_function;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan case PCI_BRIDGE_CARDBUS:
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan cardbus_err(parent, 8,
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "--Found Cardbus bridge @ "
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "bus [0x%x] device [0x%x] func [0x%x]\n",
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan bus, device, func);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_put32(config_handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_BASE0, 0xffffffff);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap request = pci_config_get32(config_handle,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_BASE0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If its a zero length, don't do
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * any programming.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (request != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (request == (uint32_t)0xffffffff) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cmn_err(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_probe_children: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "can't access device");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Add to the "reg" property
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_update_reg_prop(new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap request,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_BASE0) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "BASE register [0x%x] asks for "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%x]=[0x%x](32)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_BASE0, request,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap (~(PCI_BASE_M_ADDR_M & request))+1);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap break;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap case PCI_BRIDGE_ISA:
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(parent, 8,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "--Found ISA bridge @ "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "bus [0x%x] device [0x%x] func [0x%x]\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap bus, device, func);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap enable_pci_isa_bridge(new_child, config_handle);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap#if defined(CARDBUS_DEBUG)
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (cardbus_debug >= 4) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_dump_common_config(config_handle);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(NULL, 1,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap " DDMA SlvCh0 = [0x%04x] "
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan "DDMA SlvCh1 = [0x%04x]\n",
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan pci_config_get16(config_handle, 0x40),
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_get16(config_handle, 0x42));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(NULL, 1,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap " DDMA SlvCh2 = [0x%04x] "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "DDMA SlvCh3 = [0x%04x]\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_get16(config_handle, 0x44),
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_get16(config_handle, 0x46));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(NULL, 1,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap " DDMA SlvCh5 = [0x%04x] "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "DDMA SlvCh6 = [0x%04x]\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_get16(config_handle, 0x4a),
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_get16(config_handle, 0x4c));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(NULL, 1,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap " DDMA SlvCh7 = [0x%04x] "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "Misc Cntrl = [0x%02x]\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_get16(config_handle, 0x4e),
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap pci_config_get8(config_handle, 0x57));
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(NULL, 1,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap " DMA Cntl = [0x%02x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "DMA TyF Tim = [0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x48),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x49));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " TimCntrl = [0x%02x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "MTOP = [0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x50),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x51));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " MDMA Access = [0x%02x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "ROMCS = [0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x52),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x53));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " Dscrd Tmr = [0x%02x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Retry Tmr = [0x%02x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x55),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get8(config_handle, 0x54));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " I/O Spc 0 = [0x%08x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "I/O Spc 1 = [0x%08x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x58),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x5c));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " I/O Spc 2 = [0x%08x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "I/O Spc 3 = [0x%08x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x60),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x64));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " I/O Spc 4 = [0x%08x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "I/O Spc 5 = [0x%08x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x68),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x6c));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " Mem Spc 0 = [0x%08x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Mem Spc 1 = [0x%08x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x70),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x74));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(NULL, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap " Mem Spc 2 = [0x%08x] "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Mem Spc 3 = [0x%08x]\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x78),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_get32(config_handle, 0x7c));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Set bus properties
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_set_busnode_isaprops(new_child)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(new_child, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to set busnode props\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap disable_cardbus_device(config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Add to the "reg" property.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Simply grab 1K of I/O space.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_update_reg_prop(new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0xfffffc00 | PCI_BASE_SPACE_IO,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_BASE0) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Probe all potential children devices.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i < sizeof (isa_nodes) / sizeof (isa_nodes[0]);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i++)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (cardbus_add_isa_node(cbp, new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &isa_nodes[i])) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_FAILURE:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to configure isa bus\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap disable_cardbus_device(config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCICFG_NODEVICE:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case PCI_BRIDGE_OTHER:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 8,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "--Found unknown bridge, subclass 0x%x @ "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "bus [0x%x] device [0x%x] func [0x%x]\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap sub_class, bus, device, func);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap goto leaf_node;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap } else {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_err(parent, 8,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "--Leaf device found "
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "bus [0x%x] device [0x%x] func [0x%x]\n",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap bus, device, func);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap /*
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap * Ethernet devices.
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap */
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (strcmp(ddi_binding_name(new_child), "ethernet") == 0) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap extern int localetheraddr(struct ether_addr *,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap struct ether_addr *);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap uchar_t mac[6];
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cardbus_force_stringprop(new_child,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap "device_type", "network");
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (localetheraddr(NULL, (struct ether_addr *)mac)) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap (void) ddi_prop_create(DDI_DEV_T_NONE,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap new_child,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap DDI_PROP_CANSLEEP, "local-mac-address",
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap (caddr_t)mac, 6);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap }
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlapleaf_node:
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (cbp->cb_dsp) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap struct cb_deviceset_props *cdsp = cbp->cb_dsp;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap uint16_t venid = pci_config_get16(config_handle,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCI_CONF_VENID);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap uint16_t devid = pci_config_get16(config_handle,
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap PCI_CONF_DEVID);
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap ddi_prop_t *propp;
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap for (cdsp = cbp->cb_dsp; cdsp; cdsp = cdsp->next) {
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap if (cdsp->binding_name &&
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap strcmp(ddi_binding_name(new_child),
72cf314316bed51cd2e5fd0cb021a9725316a6b0peter dunlap cdsp->binding_name))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cdsp->venid && (cdsp->venid != venid))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cdsp->devid && (cdsp->devid != devid))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cdsp->nodename) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ndi_devi_set_nodename(new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cdsp->nodename,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap 0) != NDI_SUCCESS)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(new_child, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "Failed to set nodename\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (propp = cdsp->prop_list; propp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap propp = propp->prop_next) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (propp->prop_flags) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case DDI_PROP_TYPE_INT:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_force_intprop(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap propp->prop_name,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (int *)propp->prop_val,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap propp->prop_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case DDI_PROP_TYPE_STRING:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_force_stringprop(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap propp->prop_name,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (char *)propp->prop_val);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case DDI_PROP_TYPE_ANY:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_force_boolprop(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap propp->prop_name);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#if defined(CARDBUS_DEBUG)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_debug >= 9) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_dump_config(config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#endif
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i = PCI_CONF_BASE0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (i <= PCI_CONF_BASE5) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(config_handle, i, 0xffffffff);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap request = pci_config_get32(config_handle, i);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States /*
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * If its a zero length, don't do
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * any programming.
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States */
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (request != 0) {
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (request == (uint32_t)0xffffffff) {
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States cmn_err(CE_WARN,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "cardbus_probe_children: "
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "can't access device");
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States goto failedchild;
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States /*
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * Add to the "reg" property
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States */
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States if (cardbus_update_reg_prop(new_child,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States request, i) != PCICFG_SUCCESS) {
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States goto failedchild;
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States } else {
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States cardbus_err(parent, 8, "All memory found\n");
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States break;
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States }
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States /*
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * Increment by eight if it is 64 bit address space
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States * only if memory space
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (((PCI_BASE_TYPE_M & request)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap == PCI_BASE_TYPE_ALL) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((PCI_BASE_SPACE_M & request)
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States == PCI_BASE_SPACE_MEM)) {
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States cardbus_err(parent, 8,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "BASE register [0x%x] asks for "
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States "[0x%x]=[0x%x] (64)\n",
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States i, request,
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States (~(PCI_BASE_M_ADDR_M & request))+1);
8c629652ef2aba4749bf59757802cf9a4f1a7571Peter Cudhea - Sun Microsystems - Burlington, MA United States i += 8;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "BASE register [0x%x] asks for "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%x]=[0x%x](32)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i, request,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (~(PCI_BASE_M_ADDR_M & request))+1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap i += 4;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Get the ROM size and create register for it
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pci_config_put32(config_handle, PCI_CONF_ROM, 0xffffffff);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap request = pci_config_get32(config_handle, PCI_CONF_ROM);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If its a zero length, don't do
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * any programming.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (request != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 9,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "BASE register [0x%x] asks for "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "[0x%x]=[0x%x] (ROM)\n",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_ROM, request,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (~(PCI_BASE_ROM_ADDR_M & request))+1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Add to the "reg" property
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_update_reg_prop(new_child,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap request,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap PCI_CONF_ROM) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failedchild;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Attach the child to its parent
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) i_ndi_config_node(new_child, DS_LINKED, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_exit(parent, circ);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapfailedchild:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * check if it should be taken offline (if online)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) cardbus_config_teardown(&config_handle);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapfailedconfig:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void) ndi_devi_free(new_child);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ndi_devi_exit(parent, circ);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
ab003da878e3fe36b164e1856f9e15a78384c9ebJim Dunham
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_add_config_reg(dev_info_t *dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint_t bus, uint_t device, uint_t func)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int reg[10] = { PCI_ADDR_CONFIG, 0, 0, 0, 0};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap reg[0] = PCICFG_MAKE_REG_HIGH(bus, device, func, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "reg", reg, 5));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic int
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcardbus_add_isa_node(cbus_t *cbp, dev_info_t *parent, struct isa_node *node)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dev_info_t *new_child;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int ret;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t reg[3];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap _NOTE(ARGUNUSED(cbp))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 6, "cardbus_add_isa_node\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This node will be put immediately below
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * "parent". Allocate a blank device node.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ndi_devi_alloc(parent, DEVI_PSEUDO_NEXNAME,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (pnode_t)DEVI_SID_NODEID,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &new_child) != NDI_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 1,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "cardbus_add_isa_child(): Failed to alloc child node\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (PCICFG_FAILURE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Set properties common to ISA devices
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cardbus_set_isa_props(parent, new_child, node->name,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan node->compatible) != PCICFG_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cardbus_err(parent, 1, "Failed to set ISA properties\n");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto failed;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(new_child, 8, "--Leaf ISA device\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Add the "reg" property.
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan reg[0] = 0;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan reg[1] = node->reg;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan reg[2] = node->span;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, new_child,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "basereg", (int *)reg, 3);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ret != DDI_SUCCESS)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan goto failed;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) i_ndi_config_node(new_child, DS_LINKED, 0);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_SUCCESS);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanfailed:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) ndi_devi_free(new_child);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic int
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_config_setup(dev_info_t *dip, ddi_acc_handle_t *handle)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan caddr_t cfgaddr;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ddi_device_acc_attr_t attr;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan dev_info_t *anode;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int status;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int rlen;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan pci_regspec_t *reg;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int ret;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#ifdef sparc
55a3a0ef881a0e1c7da841d46bb5878758497dc1Josef 'Jeff' Sipek int16_t val;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#endif
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 10,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_config_setup(dip=0x%p)\n", (void *) dip);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Get the pci register spec from the node
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan status = ddi_getlongprop(DDI_DEV_T_NONE,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan dip, DDI_PROP_DONTPASS, "reg",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (caddr_t)&reg, &rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 10,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_config_setup, reg = 0x%p\n", (void *) reg);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan switch (status) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_SUCCESS:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan break;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_NO_MEMORY:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1, "reg present, but unable to get memory\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan default:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1, "no reg property\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan anode = dip;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Find the attachment point node
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan while ((anode != NULL) && (strcmp(ddi_binding_name(anode),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "hp_attachment") != 0)) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan anode = ddi_get_parent(anode);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (anode == NULL) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1, "Tree not in PROBE state\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)reg, rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if ((ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, anode,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "reg", (int *)reg, 5)) != 0) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "Failed to update reg property, error code %d\n", ret);
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald kmem_free((caddr_t)reg, rlen);
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald return (PCICFG_FAILURE);
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald }
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald if (ddi_regs_map_setup(anode, 0, &cfgaddr,
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald 0, /* PCI_CONF_HDR_SIZE */
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald 0,
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald &attr, handle) != DDI_SUCCESS) {
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald cardbus_err(dip, 1,
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald "Failed to setup registers for [0x%x][0x%x][0x%x]\n",
3e2514dc0f3dfbffad7bfb4744cf26707a910f26Dan McDonald PCI_REG_BUS_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_DEV_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_FUNC_G(reg->pci_phys_hi));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)reg, rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 9,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "PROBING =>->->->->->-> [0x%x][0x%x][0x%x] 0x%x 0x%p\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_BUS_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_DEV_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_FUNC_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan reg->pci_phys_hi, (void *) cfgaddr);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * must do peek16 otherwise the system crashes when probing
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * a non zero function on a non-multi-function card.
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#ifdef sparc
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ddi_peek16(anode, (int16_t *)cfgaddr, &val) != DDI_SUCCESS) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 8,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_config_setup peek failed\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ret = PCICFG_NODEVICE;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan } else if (ddi_get16(*handle, (uint16_t *)cfgaddr) == 0xffff) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 8,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_config_setup PCICFG_NODEVICE\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ret = PCICFG_NODEVICE;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#elif defined(__x86) || defined(__amd64)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ddi_get16(*handle, (uint16_t *)cfgaddr) == 0xffff) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 8,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_config_setup PCICFG_NODEVICE\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ret = PCICFG_NODEVICE;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#endif
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan } else {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_config_setup found device at:[0x%x][0x%x][0x%x]\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_BUS_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_DEV_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_FUNC_G(reg->pci_phys_hi));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ret = PCICFG_SUCCESS;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)reg, rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (ret != PCICFG_SUCCESS) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_config_teardown(handle);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 7,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_config_setup returning %d\n", ret);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (ret);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic void
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_config_teardown(ddi_acc_handle_t *handle)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) ddi_regs_map_free(handle);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic void
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_reparent_children(dev_info_t *dip, dev_info_t *parent)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan dev_info_t *child;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int circ;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan while (child = ddi_get_child(dip)) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ASSERT(i_ddi_node_state(child) <= DS_LINKED);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Unlink node from tree before reparenting
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ndi_devi_enter(dip, &circ);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) i_ndi_unconfig_node(child, DS_PROTO, 0);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ndi_devi_exit(dip, circ);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan DEVI(child)->devi_parent = DEVI(parent);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan DEVI(child)->devi_bus_ctl = DEVI(parent);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ndi_devi_enter(parent, &circ);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) i_ndi_config_node(child, DS_LINKED, 0);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan ndi_devi_exit(parent, circ);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic int
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int alen;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan pci_regspec_t *assigned;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan caddr_t newreg;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint_t status;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "assigned-addresses", (caddr_t)&assigned, &alen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan switch (status) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_SUCCESS:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 5,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_update_assigned_prop: found prop len %d\n",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan alen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Allocate memory for the existing
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * assigned-addresses(s) plus one and then
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * build it.
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan bcopy(assigned, newreg, alen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan bcopy(newone, newreg + alen, sizeof (*newone));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan break;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_NO_MEMORY:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "no memory for assigned-addresses property\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan default:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 5,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "cardbus_update_assigned_prop: creating prop\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan alen = 0;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan newreg = (caddr_t)newone;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan break;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Write out the new "assigned-addresses" spec
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "assigned-addresses", (int *)newreg,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (alen + sizeof (*newone))/sizeof (int));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (status == DDI_PROP_SUCCESS)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)newreg, alen+sizeof (*newone));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (alen)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free(assigned, alen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_SUCCESS);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic int
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_update_available_prop(dev_info_t *dip, uint32_t hi_type,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint64_t base, uint64_t size)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int alen, rlen;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan pci_regspec_t *available, *reg;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan pci_regspec_t addition;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan caddr_t newreg;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint_t status;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 6, "cardbus_update_available_prop\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "reg", (caddr_t)&reg, &rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan switch (status) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_SUCCESS:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan break;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_NO_MEMORY:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1, "reg present, but unable to get memory\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan default:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1, "no reg property\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan status = ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "available", (caddr_t)&available, &alen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan switch (status) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_SUCCESS:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan break;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_NO_MEMORY:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1, "no memory for available property\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)reg, rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_FAILURE);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan default:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan alen = 0;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan }
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Allocate memory for the existing
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * available(s) plus one and then
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * build it.
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan newreg = kmem_zalloc(alen + sizeof (pci_regspec_t), KM_SLEEP);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Build the regspec, then add it to the existing one(s)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan addition.pci_phys_hi = hi_type |
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_DEV_G(reg->pci_phys_hi),
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan PCI_REG_FUNC_G(reg->pci_phys_hi), 0);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan addition.pci_phys_mid = (uint32_t)((base>>32) & 0xffffffff);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan addition.pci_phys_low = (uint32_t)(base & 0xffffffff);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan addition.pci_size_hi = (uint32_t)((size>>32) & 0xffffffff);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan addition.pci_size_low = (uint32_t)(size & 0xffffffff);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#ifdef DEBUG
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_dump_reg(dip, &addition, 1);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#endif
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (alen)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan bcopy(available, newreg, alen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan bcopy(&addition, newreg + alen, sizeof (pci_regspec_t));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan /*
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan * Write out the new "available" spec
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan */
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "available", (int *)newreg,
55a3a0ef881a0e1c7da841d46bb5878758497dc1Josef 'Jeff' Sipek (alen + sizeof (pci_regspec_t))/sizeof (int));
55a3a0ef881a0e1c7da841d46bb5878758497dc1Josef 'Jeff' Sipek
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan if (alen)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)available, alen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)reg, rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan kmem_free((caddr_t)newreg, alen + sizeof (pci_regspec_t));
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan return (PCICFG_SUCCESS);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan}
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnanstatic int
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnancardbus_update_ranges_prop(dev_info_t *dip, cardbus_range_t *addition)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan{
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int rlen;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_range_t *ranges;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan caddr_t newreg;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan uint_t status;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#if defined(CARDBUS_DEBUG)
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan int i, nrange;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan const cardbus_range_t *nr;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan#endif
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 6, "cardbus_update_ranges_prop\n");
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan status = ddi_getlongprop(DDI_DEV_T_NONE,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan dip, DDI_PROP_DONTPASS, "ranges",
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan (caddr_t)&ranges, &rlen);
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan switch (status) {
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_SUCCESS:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan break;
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan case DDI_PROP_NO_MEMORY:
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan cardbus_err(dip, 1,
d618d68dcf9c6c8f2c1e2fbbd4de1de0cf30150ePriya Krishnan "ranges present, but unable to get memory\n");
return (PCICFG_FAILURE);
default:
cardbus_err(dip, 8, "no ranges property - creating one\n");
if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
dip, "ranges", (int *)addition,
sizeof (cardbus_range_t)/sizeof (int))
!= DDI_SUCCESS) {
cardbus_err(dip, 1, "Did'nt create ranges property\n");
return (PCICFG_FAILURE);
}
return (PCICFG_SUCCESS);
}
/*
* Allocate memory for the existing reg(s) plus one and then
* build it.
*/
newreg = kmem_zalloc(rlen+sizeof (cardbus_range_t), KM_SLEEP);
bcopy(ranges, newreg, rlen);
bcopy(addition, newreg + rlen, sizeof (cardbus_range_t));
/*
* Write out the new "ranges" property
*/
(void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
dip, "ranges", (int *)newreg,
(rlen + sizeof (cardbus_range_t))/sizeof (int));
#if defined(CARDBUS_DEBUG)
cardbus_err(dip, 8, "cardbus_update_ranges_prop ranges property:\n");
nrange = rlen / sizeof (cardbus_range_t);
nr = (cardbus_range_t *)newreg;
for (i = 0; i <= nrange; i++) {
/* nrange is one higher for new entry */
cardbus_err(dip, 9,
"\trange parent addr 0x%x.0x%x.0x%x "
"child addr 0x%x.0x%x.0x%x size 0x%x.0x%x\n",
nr->parent_hi,
nr->parent_mid, nr->parent_lo,
nr->child_hi,
nr->child_mid, nr->child_lo,
nr->size_hi, nr->size_lo);
nr++;
}
#endif
kmem_free((caddr_t)newreg, rlen+sizeof (cardbus_range_t));
kmem_free((caddr_t)ranges, rlen);
return (PCICFG_SUCCESS);
}
static int
cardbus_update_reg_prop(dev_info_t *dip, uint32_t regvalue, uint_t reg_offset)
{
int rlen;
pci_regspec_t *reg;
caddr_t newreg;
uint32_t hiword;
pci_regspec_t addition;
uint32_t size;
uint_t status;
status = ddi_getlongprop(DDI_DEV_T_NONE,
dip, DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &rlen);
switch (status) {
case DDI_PROP_SUCCESS:
break;
case DDI_PROP_NO_MEMORY:
cardbus_err(dip, 1, "reg present, but unable to get memory\n");
return (PCICFG_FAILURE);
default:
cardbus_err(dip, 1, "no reg property\n");
return (PCICFG_FAILURE);
}
/*
* Allocate memory for the existing reg(s) plus one and then
* build it.
*/
newreg = kmem_zalloc(rlen+sizeof (pci_regspec_t), KM_SLEEP);
/*
* Build the regspec, then add it to the existing one(s)
*/
hiword = PCICFG_MAKE_REG_HIGH(PCI_REG_BUS_G(reg->pci_phys_hi),
PCI_REG_DEV_G(reg->pci_phys_hi),
PCI_REG_FUNC_G(reg->pci_phys_hi),
reg_offset);
if (reg_offset == PCI_CONF_ROM) {
size = (~(PCI_BASE_ROM_ADDR_M & regvalue))+1;
hiword |= PCI_ADDR_MEM32;
} else {
size = (~(PCI_BASE_M_ADDR_M & regvalue))+1;
if ((PCI_BASE_SPACE_M & regvalue) == PCI_BASE_SPACE_MEM) {
if ((PCI_BASE_TYPE_M & regvalue) == PCI_BASE_TYPE_MEM) {
hiword |= PCI_ADDR_MEM32;
} else if ((PCI_BASE_TYPE_M & regvalue)
== PCI_BASE_TYPE_ALL) {
/*
* This is a 64 bit PCI memory space.
* It needs to be allocated as 32 bit
* for bus map purposes.
*/
hiword |= PCI_ADDR_MEM32;
}
} else {
hiword |= PCI_ADDR_IO;
}
}
addition.pci_phys_hi = hiword;
addition.pci_phys_mid = 0;
addition.pci_phys_low = 0;
addition.pci_size_hi = 0;
addition.pci_size_low = size;
cardbus_err(dip, 8,
"cardbus_update_reg_prop, phys_hi 0x%08x,"
" phys_mid 0x%08x, phys_low 0x%08x, size_hi 0x%08x,"
" size_low 0x%08x\n", hiword, 0, 0, 0, size);
bcopy(reg, newreg, rlen);
bcopy(&addition, newreg + rlen, sizeof (pci_regspec_t));
/*
* Write out the new "reg" property
*/
(void) ndi_prop_update_int_array(DDI_DEV_T_NONE,
dip, "reg", (int *)newreg,
(rlen + sizeof (pci_regspec_t))/sizeof (int));
kmem_free((caddr_t)reg, rlen);
kmem_free((caddr_t)newreg, rlen+sizeof (pci_regspec_t));
return (PCICFG_SUCCESS);
}
/*
* Setup the basic 1275 properties based on information found in the config
* header of the PCI device
*/
static int
cardbus_set_standard_props(dev_info_t *parent, dev_info_t *dip,
ddi_acc_handle_t config_handle)
{
int ret;
uint16_t val;
uint32_t wordval;
uint8_t byteval;
/* These two exists only for non-bridges */
if ((pci_config_get8(config_handle,
PCI_CONF_HEADER) & PCI_HEADER_TYPE_M) == PCI_HEADER_ZERO) {
byteval = pci_config_get8(config_handle, PCI_CONF_MIN_G);
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"min-grant", byteval)) != DDI_SUCCESS) {
cardbus_err(dip, 1, "Failed to sent min-grant\n");
return (ret);
}
byteval = pci_config_get8(config_handle, PCI_CONF_MAX_L);
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"max-latency", byteval)) != DDI_SUCCESS) {
return (ret);
}
}
/*
* These should always exist and have the value of the
* corresponding register value
*/
val = pci_config_get16(config_handle, PCI_CONF_VENID);
/*
* according to section 6.2.1 of revision 2 of the PCI local
* bus specification - 0FFFFh is an invalid value for the vendor ID
*/
if (val == 0xffff) {
cardbus_err(dip, 1, "Illegal vendor-id 0x%x\n", val);
return (PCICFG_FAILURE);
}
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"vendor-id", val)) != DDI_SUCCESS) {
return (ret);
}
val = pci_config_get16(config_handle, PCI_CONF_DEVID);
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"device-id", val)) != DDI_SUCCESS) {
return (ret);
}
byteval = pci_config_get8(config_handle, PCI_CONF_REVID);
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"revision-id", byteval)) != DDI_SUCCESS) {
return (ret);
}
wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
(pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"class-code", wordval)) != DDI_SUCCESS) {
return (ret);
}
val = (pci_config_get16(config_handle,
PCI_CONF_STAT) & PCI_STAT_DEVSELT);
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"devsel-speed", val)) != DDI_SUCCESS) {
return (ret);
}
/*
* The next three are bits set in the status register. The property is
* present (but with no value other than its own existence) if the bit
* is set, non-existent otherwise
*/
if (ddi_prop_exists(DDI_DEV_T_ANY, parent, DDI_PROP_DONTPASS,
"fast-back-to-back") &&
pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_FBBC) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"fast-back-to-back", 0)) != DDI_SUCCESS) {
return (ret);
}
}
if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_66MHZ) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"66mhz-capable", 0)) != DDI_SUCCESS) {
return (ret);
}
}
if (pci_config_get16(config_handle, PCI_CONF_STAT) & PCI_STAT_UDF) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"udf-supported", 0)) != DDI_SUCCESS) {
return (ret);
}
}
/*
* These next three are optional and are not present
* if the corresponding register is zero. If the value
* is non-zero then the property exists with the value
* of the register.
*/
/* look in the correct place for header type 2 */
byteval = pci_config_get8(config_handle, PCI_CONF_HEADER);
if ((byteval & PCI_HEADER_TYPE_M) == PCI_HEADER_TWO) {
if ((val = pci_config_get16(config_handle,
PCI_CBUS_SUBVENID)) != 0) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"subsystem-vendor-id", val)) != DDI_SUCCESS) {
return (ret);
}
}
if ((val = pci_config_get16(config_handle,
PCI_CBUS_SUBSYSID)) != 0) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"subsystem-id", val)) != DDI_SUCCESS) {
return (ret);
}
}
} else {
if ((val = pci_config_get16(config_handle,
PCI_CONF_SUBVENID)) != 0) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"subsystem-vendor-id", val)) != DDI_SUCCESS) {
return (ret);
}
}
if ((val = pci_config_get16(config_handle,
PCI_CONF_SUBSYSID)) != 0) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"subsystem-id", val)) != DDI_SUCCESS) {
return (ret);
}
}
}
if ((val = pci_config_get8(config_handle,
PCI_CONF_CACHE_LINESZ)) != 0) {
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"cache-line-size", val)) != DDI_SUCCESS) {
return (ret);
}
}
/*
* If the Interrupt Pin register is non-zero then the
* interrupts property exists
*/
if ((byteval = pci_config_get8(config_handle, PCI_CONF_IPIN)) != 0) {
/*
* If interrupt pin is non-zero,
* record the interrupt line used
*/
cardbus_err(dip, 8, "Adding interrupts property\n");
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"interrupts", byteval)) != DDI_SUCCESS) {
return (ret);
}
}
return (PCICFG_SUCCESS);
}
/*
* Setup the basic properties required by the ISA node.
*/
static int
cardbus_set_isa_props(dev_info_t *parent, dev_info_t *dip,
char *name, char *compat[])
{
int ret, n;
_NOTE(ARGUNUSED(parent))
cardbus_err(dip, 8, "Adding interrupts property\n");
if ((ret = ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"interrupts", 1)) != DDI_SUCCESS) {
return (ret);
}
/*
* The node name field needs to be filled in with the name
*/
if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
cardbus_err(dip, 1, "Failed to set nodename for node\n");
return (PCICFG_FAILURE);
}
/*
* Create the compatible property as an array of pointers
* to strings. Start with the buffer created above.
*/
n = 0;
while (compat[n] != NULL)
n++;
if (n != 0)
if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
"compatible", compat, n)) != DDI_SUCCESS)
return (ret);
return (PCICFG_SUCCESS);
}
static int
cardbus_set_busnode_props(dev_info_t *dip)
{
cardbus_err(dip, 6, "cardbus_set_busnode_props\n");
cardbus_force_stringprop(dip, "device_type", "pci");
if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"#address-cells", 3) != DDI_SUCCESS) {
cardbus_err(dip, 4, "Failed to set #address-cells\n");
}
if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"#size-cells", 2) != DDI_SUCCESS) {
cardbus_err(dip, 4, "Failed to set #size-cells\n");
}
return (PCICFG_SUCCESS);
}
static int
cardbus_set_busnode_isaprops(dev_info_t *dip)
{
cardbus_err(dip, 6, "cardbus_set_busnode_props\n");
cardbus_force_stringprop(dip, "device_type", "isa");
if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"#address-cells", 2) != DDI_SUCCESS) {
cardbus_err(dip, 4, "Failed to set #address-cells\n");
}
if (ndi_prop_update_int(DDI_DEV_T_NONE, dip,
"#size-cells", 1) != DDI_SUCCESS) {
cardbus_err(dip, 4, "Failed to set #size-cells\n");
}
return (PCICFG_SUCCESS);
}
/*
* Use cb%x,%x rather than pci%x,%x so that we can use specific cardbus
* drivers in /etc/driver_aliases if required
*/
static int
cardbus_set_childnode_props(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
int ret;
#ifndef _DONT_USE_1275_GENERIC_NAMES
uint32_t wordval;
#endif
char *name;
char buffer[64];
uint32_t classcode;
char *compat[8];
int i, n;
uint16_t subsysid, subvenid, devid, venid;
uint8_t header_type;
/*
* NOTE: These are for both a child and PCI-PCI bridge node
*/
#ifndef _DONT_USE_1275_GENERIC_NAMES
wordval = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
(pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
#endif
/* Cardbus support */
venid = pci_config_get16(config_handle, PCI_CONF_VENID);
devid = pci_config_get16(config_handle, PCI_CONF_DEVID);
header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_TWO) {
subvenid = pci_config_get16(config_handle, PCI_CBUS_SUBVENID);
subsysid = pci_config_get16(config_handle, PCI_CBUS_SUBSYSID);
} else {
subvenid = pci_config_get16(config_handle, PCI_CONF_SUBVENID);
subsysid = pci_config_get16(config_handle, PCI_CONF_SUBSYSID);
}
if (subsysid != 0) {
(void) sprintf(buffer, "pci%x,%x", subvenid, subsysid);
} else {
(void) sprintf(buffer, "pci%x,%x", venid, devid);
}
cardbus_err(dip, 8, "Childname is %s\n", buffer);
/*
* In some environments, trying to use "generic" 1275 names is
* not the convention. In those cases use the name as created
* above. In all the rest of the cases, check to see if there
* is a generic name first.
*/
#ifdef _DONT_USE_1275_GENERIC_NAMES
name = buffer;
#else
if ((name = cardbus_get_class_name(wordval>>8)) == NULL) {
/*
* Set name to the above fabricated name
*/
name = buffer;
}
cardbus_err(dip, 8, "Set nodename to %s\n", name);
#endif
/*
* The node name field needs to be filled in with the name
*/
if (ndi_devi_set_nodename(dip, name, 0) != NDI_SUCCESS) {
cardbus_err(dip, 1, "Failed to set nodename for node\n");
return (PCICFG_FAILURE);
}
/*
* Create the compatible property as an array of pointers
* to strings. Start with the cb name.
*/
n = 0;
if (subsysid != 0) {
(void) sprintf(buffer, "cb%x,%x", subvenid, subsysid);
} else {
(void) sprintf(buffer, "cb%x,%x", venid, devid);
}
compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
(void) strcpy(compat[n++], buffer);
if (subsysid != 0) {
/*
* Add subsys numbers as pci compatible.
*/
(void) sprintf(buffer, "pci%x,%x", subvenid, subsysid);
compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
(void) strcpy(compat[n++], buffer);
}
/*
* Add in the VendorID/DeviceID compatible name.
*/
(void) sprintf(buffer, "pci%x,%x", venid, devid);
compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
(void) strcpy(compat[n++], buffer);
classcode = (pci_config_get16(config_handle, PCI_CONF_SUBCLASS)<< 8) |
(pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
/*
* Add in the Classcode
*/
(void) sprintf(buffer, "pciclass,%06x", classcode);
cardbus_err(dip, 8, "class code %s\n", buffer);
compat[n] = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
(void) strcpy(compat[n++], buffer);
if ((ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
"compatible", (char **)compat, n)) != DDI_SUCCESS) {
return (ret);
}
for (i = 0; i < n; i++) {
kmem_free(compat[i], strlen(compat[i]) + 1);
}
return (PCICFG_SUCCESS);
}
/*
* Program the bus numbers into the bridge
*/
static void
cardbus_set_bus_numbers(ddi_acc_handle_t config_handle,
uint_t primary, uint_t secondary)
{
cardbus_err(NULL, 8,
"cardbus_set_bus_numbers [%d->%d]\n", primary, secondary);
/*
* Primary bus#
*/
pci_config_put8(config_handle, PCI_BCNF_PRIBUS, primary);
/*
* Secondary bus#
*/
pci_config_put8(config_handle, PCI_BCNF_SECBUS, secondary);
/*
* Set the subordinate bus number to ff in order to pass through any
* type 1 cycle with a bus number higher than the secondary bus#
* Note that this is reduced once the probe is complete in the
* cardbus_setup_bridge() function.
*/
pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0xFF);
}
static void
enable_pci_isa_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t comm, stat;
stat = pci_config_get16(config_handle, PCI_CONF_STAT);
comm = pci_config_get16(config_handle, PCI_CONF_COMM);
/*
* Enable memory, IO, bus mastership and error detection.
*/
comm |= (PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO |
PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
"fast-back-to-back"))
comm |= PCI_COMM_BACK2BACK_ENAB;
pci_config_put16(config_handle, PCI_CONF_COMM, comm);
cardbus_err(NULL, 8,
"enable_pci_isa_bridge stat 0x%04x comm 0x%04x\n", stat, comm);
/*
* ITE8888 Specific registers.
*/
pci_config_put8(config_handle, 0x50, 0x00); /* Timing Control */
pci_config_put8(config_handle, 0x52, 0x00); /* Master DMA Access */
pci_config_put8(config_handle, 0x53, 0x01); /* ROMCS */
}
static void
enable_pci_pci_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t comm, stat, bctrl;
stat = pci_config_get16(config_handle, PCI_CONF_STAT);
comm = pci_config_get16(config_handle, PCI_CONF_COMM);
bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
comm &= ~(PCI_COMM_IO | PCI_COMM_MAE);
comm |= (PCI_COMM_ME | PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
/*
* Enable back to back.
*/
if (stat & PCI_STAT_FBBC)
comm |= PCI_COMM_BACK2BACK_ENAB;
pci_config_put16(config_handle, PCI_CONF_COMM, comm);
/*
* Reset the sub-ordinate bus.
*/
if (!(bctrl & PCI_BCNF_BCNTRL_RESET))
pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL,
bctrl | PCI_BCNF_BCNTRL_RESET);
else
bctrl &= ~PCI_BCNF_BCNTRL_RESET;
/*
* Enable error reporting.
*/
bctrl |= (PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE |
PCI_BCNF_BCNTRL_MAST_AB_MODE);
/*
* Enable back to back on secondary bus.
*/
if (stat & PCI_STAT_FBBC)
bctrl |= PCI_BCNF_BCNTRL_B2B_ENAB;
pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
cardbus_err(dip, 8,
"enable_pci_pci_bridge stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
stat, comm, bctrl);
}
static int cardbus_reset_wait = 20;
static void
enable_cardbus_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t comm, stat, bctrl;
stat = pci_config_get16(config_handle, PCI_CONF_STAT);
comm = pci_config_get16(config_handle, PCI_CONF_COMM);
bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
/*
* Don't mess with the command register on the cardbus bridge
* itself. This should have been done when it's parent
* did the setup. Some devices *require* certain things to
* disabled, this can be done using the "command-preserve"
* property and if we mess with it here it breaks that.
*
* comm |= (PCI_COMM_ME | PCI_COMM_PARITY_DETECT |
* PCI_COMM_SERR_ENABLE);
*/
/*
* Reset the sub-ordinate bus.
*/
if (!(bctrl & PCI_BCNF_BCNTRL_RESET))
pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL,
bctrl | PCI_BCNF_BCNTRL_RESET);
else
bctrl &= ~PCI_BCNF_BCNTRL_RESET;
/*
* Turn off pre-fetch.
*/
bctrl &= ~(CB_BCNF_BCNTRL_MEM0_PREF | CB_BCNF_BCNTRL_MEM1_PREF |
PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE);
/*
* Enable error reporting.
*/
bctrl |= (PCI_BCNF_BCNTRL_MAST_AB_MODE | CB_BCNF_BCNTRL_WRITE_POST);
if (comm & PCI_COMM_PARITY_DETECT)
bctrl |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
if (comm & PCI_COMM_SERR_ENABLE)
bctrl |= PCI_BCNF_BCNTRL_SERR_ENABLE;
pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
pci_config_put8(config_handle, PCI_CBUS_LATENCY_TIMER,
cardbus_latency_timer);
pci_config_put16(config_handle, PCI_CONF_STAT, stat);
pci_config_put16(config_handle, PCI_CONF_COMM, comm);
cardbus_err(dip, 8,
"enable_cardbus_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
stat, comm, bctrl);
/* after resetting the bridge, wait for everything to stablize */
delay(drv_usectohz(cardbus_reset_wait * 1000));
}
static void
disable_pci_pci_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t comm, bctrl;
comm = pci_config_get16(config_handle, PCI_CONF_COMM);
bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
/*
* Turn off subordinate bus access.
*/
pci_config_put8(config_handle, PCI_BCNF_SECBUS, 0);
pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0);
/*
* Disable error reporting.
*/
bctrl &= ~(PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE |
PCI_BCNF_BCNTRL_MAST_AB_MODE);
comm = 0;
pci_config_put16(config_handle, PCI_CONF_COMM, comm);
pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
cardbus_err(dip, 6,
"disable_pci_pci_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
pci_config_get16(config_handle, PCI_CONF_STAT), comm, bctrl);
}
static void
disable_cardbus_bridge(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t comm, bctrl;
comm = pci_config_get16(config_handle, PCI_CONF_COMM);
bctrl = pci_config_get16(config_handle, PCI_CBUS_BRIDGE_CTRL);
/*
* Turn off subordinate bus access.
*/
pci_config_put8(config_handle, PCI_BCNF_SECBUS, 0);
pci_config_put8(config_handle, PCI_BCNF_SUBBUS, 0);
/*
* Disable error reporting.
*/
bctrl &= ~(PCI_BCNF_BCNTRL_PARITY_ENABLE | PCI_BCNF_BCNTRL_SERR_ENABLE |
PCI_BCNF_BCNTRL_MAST_AB_MODE);
pci_config_put32(config_handle, PCI_CBUS_MEM_LIMIT0, 0);
pci_config_put32(config_handle, PCI_CBUS_MEM_BASE0, 0);
pci_config_put32(config_handle, PCI_CBUS_IO_LIMIT0, 0);
pci_config_put32(config_handle, PCI_CBUS_IO_BASE0, 0);
pci_config_put16(config_handle, PCI_CONF_COMM, comm);
pci_config_put16(config_handle, PCI_CBUS_BRIDGE_CTRL, bctrl);
cardbus_err(dip, 6,
"disable_cardbus_bridge() stat 0x%04x comm 0x%04x bctrl 0x%04x\n",
pci_config_get16(config_handle, PCI_CONF_STAT), comm, bctrl);
}
static void
enable_cardbus_device(dev_info_t *dip, ddi_acc_handle_t config_handle)
{
uint16_t comm, stat;
stat = pci_config_get16(config_handle, PCI_CONF_STAT);
comm = pci_config_get16(config_handle, PCI_CONF_COMM);
/*
* Enable memory, IO, bus mastership and error detection.
*/
comm |= (PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO |
PCI_COMM_PARITY_DETECT | PCI_COMM_SERR_ENABLE);
if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
"fast-back-to-back"))
comm |= PCI_COMM_BACK2BACK_ENAB;
pci_config_put16(config_handle, PCI_CONF_COMM, comm);
cardbus_err(NULL, 8,
"enable_cardbus_device stat 0x%04x comm 0x%04x\n", stat, comm);
}
static void
disable_cardbus_device(ddi_acc_handle_t config_handle)
{
cardbus_err(NULL, 8, "disable_cardbus_device\n");
/*
* Turn off everything in the command register.
*/
pci_config_put16(config_handle, PCI_CONF_COMM, 0x0);
}
#ifndef _DONT_USE_1275_GENERIC_NAMES
static char *
cardbus_get_class_name(uint32_t classcode)
{
struct cardbus_name_entry *ptr;
for (ptr = &cardbus_class_lookup[0]; ptr->name != NULL; ptr++) {
if (ptr->class_code == classcode) {
return (ptr->name);
}
}
return (NULL);
}
#endif /* _DONT_USE_1275_GENERIC_NAMES */
static void
cardbus_force_boolprop(dev_info_t *dip, char *pname)
{
int ret;
if ((ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, dip,
pname)) != DDI_SUCCESS) {
if (ret == DDI_PROP_NOT_FOUND)
if (ddi_prop_create(DDI_DEV_T_NONE, dip,
DDI_PROP_CANSLEEP, pname,
(caddr_t)NULL, 0) != DDI_SUCCESS)
cardbus_err(dip, 4,
"Failed to set boolean property "
"\"%s\"\n", pname);
}
}
static void
cardbus_force_intprop(dev_info_t *dip, char *pname, int *pval, int len)
{
int ret;
if ((ret = ndi_prop_update_int_array(DDI_DEV_T_NONE, dip,
pname, pval, len)) != DDI_SUCCESS) {
if (ret == DDI_PROP_NOT_FOUND)
if (ddi_prop_create(DDI_DEV_T_NONE, dip,
DDI_PROP_CANSLEEP, pname,
(caddr_t)pval, len*sizeof (int))
!= DDI_SUCCESS)
cardbus_err(dip, 4,
"Failed to set int property \"%s\"\n",
pname);
}
}
static void
cardbus_force_stringprop(dev_info_t *dip, char *pname, char *pval)
{
int ret;
if ((ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
pname, pval)) != DDI_SUCCESS) {
if (ret == DDI_PROP_NOT_FOUND)
if (ddi_prop_create(DDI_DEV_T_NONE, dip,
DDI_PROP_CANSLEEP, pname,
pval, strlen(pval) + 1) != DDI_SUCCESS)
cardbus_err(dip, 4,
"Failed to set string property "
"\"%s\" to \"%s\"\n",
pname, pval);
}
}
static void
split_addr(char *naddr, int *dev, int *func)
{
char c;
int *ip = dev;
*dev = 0;
*func = 0;
while (c = *naddr++) {
if (c == ',') {
ip = func;
continue;
}
if (c >= '0' && c <= '9') {
*ip = (*ip * 16) + (c - '0');
} else if (c >= 'a' && c <= 'f') {
*ip = (*ip * 16) + 10 + (c - 'a');
} else
break;
}
}
#ifdef DEBUG
static void
cardbus_dump_common_config(ddi_acc_handle_t config_handle)
{
cardbus_err(NULL, 1,
" Vendor ID = [0x%04x] "
"Device ID = [0x%04x]\n",
pci_config_get16(config_handle, PCI_CONF_VENID),
pci_config_get16(config_handle, PCI_CONF_DEVID));
cardbus_err(NULL, 1,
" Command REG = [0x%04x] "
"Status REG = [0x%04x]\n",
pci_config_get16(config_handle, PCI_CONF_COMM),
pci_config_get16(config_handle, PCI_CONF_STAT));
cardbus_err(NULL, 1,
" Revision ID = [0x%02x] "
"Prog Class = [0x%02x]\n",
pci_config_get8(config_handle, PCI_CONF_REVID),
pci_config_get8(config_handle, PCI_CONF_PROGCLASS));
cardbus_err(NULL, 1,
" Dev Class = [0x%02x] "
"Base Class = [0x%02x]\n",
pci_config_get8(config_handle, PCI_CONF_SUBCLASS),
pci_config_get8(config_handle, PCI_CONF_BASCLASS));
cardbus_err(NULL, 1,
" Cache LnSz = [0x%02x] "
"Latency Tmr = [0x%02x]\n",
pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ),
pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER));
cardbus_err(NULL, 1,
" Header Type = [0x%02x] "
"BIST = [0x%02x]\n",
pci_config_get8(config_handle, PCI_CONF_HEADER),
pci_config_get8(config_handle, PCI_CONF_BIST));
}
static void
cardbus_dump_device_config(ddi_acc_handle_t config_handle)
{
cardbus_dump_common_config(config_handle);
cardbus_err(NULL, 1,
" BASE 0 = [0x%08x] BASE 1 = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CONF_BASE0),
pci_config_get32(config_handle, PCI_CONF_BASE1));
cardbus_err(NULL, 1,
" BASE 2 = [0x%08x] BASE 3 = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CONF_BASE2),
pci_config_get32(config_handle, PCI_CONF_BASE3));
cardbus_err(NULL, 1,
" BASE 4 = [0x%08x] BASE 5 = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CONF_BASE4),
pci_config_get32(config_handle, PCI_CONF_BASE5));
cardbus_err(NULL, 1,
" Cardbus CIS = [0x%08x] ROM = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CONF_CIS),
pci_config_get32(config_handle, PCI_CONF_ROM));
cardbus_err(NULL, 1,
" Sub VID = [0x%04x] Sub SID = [0x%04x]\n",
pci_config_get16(config_handle, PCI_CONF_SUBVENID),
pci_config_get16(config_handle, PCI_CONF_SUBSYSID));
cardbus_err(NULL, 1,
" I Line = [0x%02x] I Pin = [0x%02x]\n",
pci_config_get8(config_handle, PCI_CONF_ILINE),
pci_config_get8(config_handle, PCI_CONF_IPIN));
cardbus_err(NULL, 1,
" Max Grant = [0x%02x] Max Latent = [0x%02x]\n",
pci_config_get8(config_handle, PCI_CONF_MIN_G),
pci_config_get8(config_handle, PCI_CONF_MAX_L));
}
static void
cardbus_dump_bridge_config(ddi_acc_handle_t config_handle,
uint8_t header_type)
{
if (header_type == PCI_HEADER_PPB) {
cardbus_dump_common_config(config_handle);
cardbus_err(NULL, 1,
"........................................\n");
} else {
cardbus_dump_common_config(config_handle);
cardbus_err(NULL, 1,
" Mem Base = [0x%08x] CBus Status = [0x%04x]\n",
pci_config_get32(config_handle, PCI_CBUS_SOCK_REG),
pci_config_get16(config_handle, PCI_CBUS_SEC_STATUS));
}
cardbus_err(NULL, 1,
" Pri Bus = [0x%02x] Sec Bus = [0x%02x]\n",
pci_config_get8(config_handle, PCI_BCNF_PRIBUS),
pci_config_get8(config_handle, PCI_BCNF_SECBUS));
cardbus_err(NULL, 1,
" Sub Bus = [0x%02x] Sec Latency = [0x%02x]\n",
pci_config_get8(config_handle, PCI_BCNF_SUBBUS),
pci_config_get8(config_handle, PCI_BCNF_LATENCY_TIMER));
switch (header_type) {
case PCI_HEADER_PPB:
cardbus_err(NULL, 1,
" I/O Base LO = [0x%02x] I/O Lim LO = [0x%02x]\n",
pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW),
pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW));
cardbus_err(NULL, 1,
" Sec. Status = [0x%04x]\n",
pci_config_get16(config_handle, PCI_BCNF_SEC_STATUS));
cardbus_err(NULL, 1,
" Mem Base = [0x%04x] Mem Limit = [0x%04x]\n",
pci_config_get16(config_handle, PCI_BCNF_MEM_BASE),
pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT));
cardbus_err(NULL, 1,
" PF Mem Base = [0x%04x] PF Mem Lim = [0x%04x]\n",
pci_config_get16(config_handle, PCI_BCNF_PF_BASE_LOW),
pci_config_get16(config_handle, PCI_BCNF_PF_LIMIT_LOW));
cardbus_err(NULL, 1,
" PF Base HI = [0x%08x] PF Lim HI = [0x%08x]\n",
pci_config_get32(config_handle, PCI_BCNF_PF_BASE_HIGH),
pci_config_get32(config_handle, PCI_BCNF_PF_LIMIT_HIGH));
cardbus_err(NULL, 1,
" I/O Base HI = [0x%04x] I/O Lim HI = [0x%04x]\n",
pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI),
pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI));
cardbus_err(NULL, 1,
" ROM addr = [0x%08x]\n",
pci_config_get32(config_handle, PCI_BCNF_ROM));
break;
case PCI_HEADER_CARDBUS:
cardbus_err(NULL, 1,
" Mem Base 0 = [0x%08x] Mem Limit 0 = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CBUS_MEM_BASE0),
pci_config_get32(config_handle, PCI_CBUS_MEM_LIMIT0));
cardbus_err(NULL, 1,
" Mem Base 1 = [0x%08x] Mem Limit 1 = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CBUS_MEM_BASE1),
pci_config_get32(config_handle, PCI_CBUS_MEM_LIMIT1));
cardbus_err(NULL, 1,
" IO Base 0 = [0x%08x] IO Limit 0 = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CBUS_IO_BASE0),
pci_config_get32(config_handle, PCI_CBUS_IO_LIMIT0));
cardbus_err(NULL, 1,
" IO Base 1 = [0x%08x] IO Limit 1 = [0x%08x]\n",
pci_config_get32(config_handle, PCI_CBUS_IO_BASE1),
pci_config_get32(config_handle, PCI_CBUS_IO_LIMIT1));
break;
}
cardbus_err(NULL, 1,
" Intr Line = [0x%02x] Intr Pin = [0x%02x]\n",
pci_config_get8(config_handle, PCI_BCNF_ILINE),
pci_config_get8(config_handle, PCI_BCNF_IPIN));
cardbus_err(NULL, 1,
" Bridge Ctrl = [0x%04x]\n",
pci_config_get16(config_handle, PCI_BCNF_BCNTRL));
switch (header_type) {
case PCI_HEADER_CARDBUS:
cardbus_err(NULL, 1,
" Sub VID = [0x%04x] Sub SID = [0x%04x]\n",
pci_config_get16(config_handle, PCI_CBUS_SUBVENID),
pci_config_get16(config_handle, PCI_CBUS_SUBSYSID));
/* LATER: TI1250 only */
cardbus_err(NULL, 1,
" Sys Control = [0x%08x]\n",
pci_config_get32(config_handle, 0x80));
}
}
static void
cardbus_dump_config(ddi_acc_handle_t config_handle)
{
uint8_t header_type = pci_config_get8(config_handle,
PCI_CONF_HEADER) & PCI_HEADER_TYPE_M;
if (header_type == PCI_HEADER_PPB || header_type == PCI_HEADER_CARDBUS)
cardbus_dump_bridge_config(config_handle, header_type);
else
cardbus_dump_device_config(config_handle);
}
static void
cardbus_dump_reg(dev_info_t *dip, const pci_regspec_t *regspec, int nelems)
{
/* int rlen = nelems * sizeof(pci_regspec_t); */
cardbus_err(dip, 6,
"cardbus_dump_reg: \"reg\" has %d elements\n", nelems);
#if defined(CARDBUS_DEBUG)
if (cardbus_debug >= 1) {
int i;
uint32_t *regs = (uint32_t *)regspec;
for (i = 0; i < nelems; i++) {
cardbus_err(NULL, 6,
"\t%d:%08x %08x %08x %08x %08x\n",
i, regs[0], regs[1], regs[2], regs[3], regs[4]);
}
}
#endif
}
#endif
#if defined(CARDBUS_DEBUG)
void
cardbus_dump_children(dev_info_t *dip, int level)
{
dev_info_t *next;
cardbus_err(dip, 1,
"\t%d: %s: 0x%p\n", level, ddi_node_name(dip), (void *) dip);
for (next = ddi_get_child(dip); next;
next = ddi_get_next_sibling(next))
cardbus_dump_children(next, level + 1);
}
void
cardbus_dump_family_tree(dev_info_t *dip)
{
cardbus_err(dip, 1, "0x%p family tree:\n", (void *) dip);
cardbus_dump_children(dip, 1);
}
#endif