stp4020.c revision 360e6f5e7a29d5950aa1985f56811731715da7e5
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*/
#include <sys/autoconf.h>
#include <sys/ddidmareq.h>
#include <sys/sservice.h>
#include <sys/stp4020_reg.h>
#include <sys/stp4020_var.h>
char _depends_on[] = "misc/pcmcia";
static void drt_ll_reset(drt_dev_t *, int);
static void drt_stop_intr(drt_dev_t *, int);
static void drt_new_card(drt_dev_t *, int);
static void drt_fixprops(dev_info_t *);
static struct stpramap *stpra_alloc_map();
static void stpra_free_map(struct stpramap *);
static kmutex_t stpra_lock;
static
struct bus_ops pcmciabus_ops = {
NULL,
NULL,
NULL,
NULL, /* (*bus_get_eventcookie)(); */
NULL, /* (*bus_add_eventcall)(); */
NULL, /* (*bus_remove_eventcall)(); */
NULL, /* (*bus_post_event)(); */
NULL, /* (*bus_intr_ctl)(); */
NULL, /* (*bus_config)(); */
NULL, /* (*bus_unconfig)(); */
NULL, /* (*bus_fm_init)(); */
NULL, /* (*bus_fm_fini)(); */
NULL, /* (*bus_enter)() */
NULL, /* (*bus_exit)() */
NULL, /* (*bus_power)() */
pcmcia_intr_ops /* (*bus_intr_op)(); */
};
static struct dev_ops drt_devops = {
0,
NULL,
};
#if defined(DEBUG)
#define DRT_DEBUG
#endif
#if defined(DRT_DEBUG)
static void drt_dmp_regs(stp4020_socket_csr_t *);
int drt_debug = 0;
#endif
/* bit patterns to select voltage levels */
int drt_vpp_levels[13] = {
0, 0, 0, 0, 0,
1, /* 5V */
0, 0, 0, 0, 0, 0,
2 /* 12V */
};
{
0, /* off */
},
{
5*10, /* 5Volt */
},
{
12*10, /* 12Volt */
},
};
static int drt_callback(dev_info_t *, int (*)(), int);
static int drt_reset_socket(dev_info_t *, int, int);
/*
* pcmcia interface operations structure
* this is the private interface that is exported to the nexus
*/
NULL,
};
/*
* This is the loadable module wrapper.
*/
extern struct mod_ops mod_driverops;
&mod_driverops, /* Type of module. This one is a driver */
"STP4020 (SUNW,pcmcia) adapter driver %I%", /* Name of the module. */
&drt_devops, /* driver ops */
};
static struct modlinkage modlinkage = {
};
int
_init()
{
int ret;
}
return (ret);
}
int
_fini()
{
int ret;
while (stpra_freelist != NULL) {
sizeof (struct stpramap));
}
}
return (ret);
}
int
{
}
/*
* drt_getinfo()
*/
int
{
int error = DDI_SUCCESS;
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
/* should make independent of SUNW,pcmcia */
break;
case DDI_INFO_DEVT2INSTANCE:
*result = 0;
break;
default:
error = DDI_FAILURE;
break;
}
return (error);
}
/*
* drt_attach()
* attach the DRT (SPARC STP4020) driver
* to the system. This is a child of "sysbus" since that is where
* the hardware lives, but it provides services to the "pcmcia"
* nexus driver. It gives a pointer back via its private data
* structure which contains both the dip and socket services entry
* points
*/
static int
{
struct pcmcia_adapter_nexus_private *drt_nexus;
int i;
int regs[24];
int err;
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
switch (cmd) {
default:
return (DDI_FAILURE);
case DDI_RESUME:
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
/* XXX - why would drt be NULL?? */
int sn;
/* Restore adapter hardware state */
} /* for (sn) */
/* do we want to do anything here??? */
/* this code should do PC Card Standard form */
(void) pcmcia_begin_resume(dip);
/*
* this will do the CARD_INSERTION
* due to needing time for threads to
* run, it must be delayed for a short amount
* of time. pcmcia_wait_insert checks for all
* children to be removed and then triggers insert.
*/
(void) pcmcia_wait_insert(dip);
/*
* for complete implementation need END_RESUME (later)
*/
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
case DDI_ATTACH:
break;
}
return (DDI_FAILURE);
}
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
drt_nexus = (struct pcmcia_adapter_nexus_private *)
kmem_zalloc(sizeof (struct pcmcia_adapter_nexus_private),
return (DDI_FAILURE);
}
/* map everything in we will ultimately need */
(off_t)0, sizeof (stp4020_socket_csr_t),
sizeof (struct pcmcia_adapter_nexus_private *));
return (DDI_FAILURE);
}
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
i = sizeof (regs);
DDI_PROP_CANSLEEP, "reg",
sizeof (struct pcmcia_adapter_nexus_private));
return (DDI_FAILURE);
}
/* allow property to override audio */
/* now enable both interrupt handlers */
/* if it fails, unwind everything */
return (DDI_FAILURE);
}
#if 0
/* if it fails, unwind everything */
return (DDI_FAILURE);
}
#endif
for (i = 0; i < DRSOCKETS; i++) {
/* work around for false status bugs */
/*
* enable the socket as well
* want status change interrupts for all possible events
* We do this even though CS hasn't asked. The system
* wants to manage these and will only tell CS of those
* it asks for
*/
/* identify current state of card */
/* finally, turn it on */
/* now we need per-socket I/O space allocation */
}
/*
* now that the adapter is fully operational
* it is time to pull in the PCMCIA framework
* and let it know we exist and are "ready"
*/
return (err);
}
/*
* drt_detach()
* request to detach from the system
*/
static int
{
int i;
switch (cmd) {
case DDI_DETACH:
/* turn everything off for all sockets and chips */
for (i = 0; i < drt->pc_numsockets; i++) {
}
return (DDI_SUCCESS);
}
break;
case DDI_PM_SUSPEND:
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
/*FALLTHROUGH*/
case DDI_SUSPEND:
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
/* XXX - why is this test necessary here? */
int sn;
/* drt_stop_intr(drt, sn); XXX ?? */
}
/*
* Save the adapter's hardware state here
*/
return (DDI_SUCCESS);
} /* if (drt) */
} /* switch */
return (DDI_FAILURE);
}
{
struct pcmcia_adapter_nexus_private *nexus;
}
/*
* drt_inquire_adapter()
* SocketServices InquireAdapter function
* get characteristics of the physical adapter
*/
static int
{
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
return (SUCCESS);
}
/*
* drt_callback()
* The PCMCIA nexus calls us via this function
* in order to set the callback function we are
* to call the nexus with
*/
static int
{
#if defined(DRT_DEBUG)
if (drt_debug) {
#ifdef XXX
#endif
}
#endif
} else {
}
/*
* we're now registered with the nexus
* it is acceptable to do callbacks at this point.
* don't call back from here though since it could block
*/
return (PC_SUCCESS);
}
/*
* drt_calc_speed()
* determine the bit pattern for speeds to be put in the control register
*/
static int
drt_calc_speed(int speed)
{
int length;
int delay;
/*
* the documented speed determination (25MHZ) is
* 250 + (CMDLNG - 4) * 40 < speed <= 250 + (CMDLNG - 3) * 40
* The value of CMDLNG is roughly determined by
* CMDLNG == ((speed - 250) / 40) + [3|4]
* the calculation is very approximate.
* for speeds <= 250ns, use simple formula
*
* this should really be based on processor speed.
*/
if (speed <= 250) {
if (speed < 100)
speed = 100;
if (speed <= 100)
delay = 1;
else
delay = 2;
} else {
length += 3;
else
length += 4;
delay = 2;
}
#if defined(DRT_DEBUG)
if (drt_debug)
"delay=%x, ret=%x\n",
#endif
}
/*
* drt_set_window
* essentially the same as the Socket Services specification
* We use socket and not adapter since they are identifiable
* but the rest is the same
*
* dip drt driver's device information
* window parameters for the request
*/
static int
{
int prevstate;
struct drt_window *winp;
int windex;
#if defined(DRT_DEBUG)
if (drt_debug) {
"\twindow=%d, socket=%d, WindowSize=%d, speed=%d\n",
}
#endif
/*
* do some basic sanity checking on what we support
* we don't do paged mode
*/
return (BAD_ATTRIBUTE);
/*
* combination
*/
return (BAD_SOCKET);
}
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
return (BAD_SIZE);
}
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
/*
* we don't care about previous mappings.
* Card Services will deal with that so don't
* even check
*/
which = 0; /* no error */
/* disable current settings */
/*
* disable current mapping
* this will handle the case of WS_ENABLED not being set
*/
#ifdef notdef
(WS_IO|WS_EXACT_MAPIN)) {
/* compensate for having to start at 0 */
}
}
#endif
else
if ((prevstate & DRW_MAPPED) &&
#if defined(DRT_DEBUG)
if (drt_debug)
"\tunmapped: base being set to NULL\n");
#endif
}
}
return (BAD_BASE);
}
/* now use the resultant address */
}
&winp->drtw_handle);
if (which != DDI_SUCCESS) {
return (BAD_SIZE);
}
#if defined(DRT_DEBUG)
if (drt_debug)
"\tmapped: handle = 0x%p base = %p, "
"len=%x\n",
(int)window->WindowSize);
#endif
}
} else {
}
} else {
#ifdef XXX
}
#endif /* XXX */
}
}
#if defined(DRT_DEBUG)
if (drt_debug) {
"\tbase now set to %p (->%p), csrp=%p, winreg=%p"
", len=%x\n",
(int)window->WindowSize);
"I/O" : "memory");
if (drt_debug > 1)
}
#endif
return (SUCCESS);
}
/*
* drt_card_state()
* compute the instantaneous Card State information
*/
int
{
#if defined(DRT_DEBUG)
if (drt_debug) {
"\020\1PWRON\2WAIT\3WP\4RDYBSY\5BVD1\6BVD2\7CD1"
"\10CD2\011ACCTO\012WPC\013RBC\014BVD1C\015BVD2C"
"\016CDSC\017STAT");
"\tstat1=%x\n",
}
#endif
if (value & DRSTAT_WPST)
else
result = 0;
switch (value & DRSTAT_BVDST) {
case DRSTAT_BATT_LOW:
break;
case DRSTAT_BATT_OK:
break;
default:
/* battery dead */
break;
}
if (value & DRSTAT_RDYST)
result |= SBM_RDYBSY;
return (result);
}
/*
* drt_set_page()
* SocketServices SetPage function
* set the page of PC Card memory that should be in the mapped
* window
*/
int
{
struct drt_window *winp;
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
return (BAD_WINDOW);
}
#if defined(DRT_DEBUG)
if (drt_debug) {
"drt_set_page: window=%d, socket=%d, page=%d\n",
}
#endif
/* only one page supported (fixed at 1MB) */
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
return (BAD_WINDOW);
}
return (BAD_PAGE);
}
/*
* now map the card's memory pages - we start with page 0
*/
} else {
}
/* if card says Write Protect, enforce it */
/* but we don't have hardware support to do it */
/* The actual PC Card address mapping */
#if defined(DRT_DEBUG)
if (drt_debug)
csrp);
#endif
/* now set the register */
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
/* now */
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
#if defined(DRT_DEBUG)
if (drt_debug) {
"\tpage offset=%x, base=%p (PC addr=%p, sockets=%d)\n",
if (drt_debug > 1)
}
#endif
return (SUCCESS);
}
/*
* drt_set_socket()
* Socket Services SetSocket call
* sets basic socket configuration
*/
static int
{
int irq = 0;
int powerlevel = 0;
int ind;
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
/*
* check VccLevel, etc. before setting mutex
* if this is zero, power is being turned off
* if it is non-zero, power is being turned on.
* the default case is to assume Vcc only.
*/
/* this appears to be very implementation specific */
powerlevel = 0;
/* enable Vcc */
} else {
return (BAD_VCC);
}
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
ind = 0; /* default index to 0 power */
return (BAD_VPP);
}
}
return (BAD_VPP);
}
}
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
/* make sure not still in RESET */
/*
* ctlind processing -- we can ignore this
* there aren't any outputs on the chip for this
* the GUI will display what it thinks is correct
*/
/* handle event mask */
DRT_CHANGE_DEFAULT; /* always want CD */
value |= DRCTL_CDIE;
value |= DRCTL_BVD1IE;
value |= DRCTL_BVD2IE;
value |= DRCTL_WPIE;
value |= DRCTL_RDYIE;
/* irq processing */
/* IRQ only for I/O */
irq = DRCTL_IOIE;
#if 0
irq |= DRCTL_IOILVL_SB1;
} else {
irq |= DRCTL_IOILVL_SB0;
}
#else
irq |= DRCTL_IOILVL_SB1;
#endif
} else {
irq = 0; /* no interrupts */
}
#if defined(DRT_DEBUG)
if (drt_debug) {
"\tsocket type is I/O and irq %x is %s\n", irq,
"enabled" : "not enabled");
}
#endif
else
} else {
/* enforce memory mode */
}
/*
* set power to socket
* note that the powerlevel was calculated earlier
*/
#if defined(DRT_DEBUG)
if (drt_debug) {
"\tpowerlevel (socket->ctl1) = %x\n", powerlevel);
if (drt_debug > 1)
}
#endif
return (SUCCESS);
}
/*
* drt_inquire_socket()
* SocketServices InquireSocket function
* returns basic characteristics of the socket
*/
static int
{
int value;
#ifdef lint
if (value > 0)
panic("lint panic");
#endif
return (SUCCESS);
}
/*
* drt_inquire_window()
* SocketServices InquireWindow function
* returns detailed characteristics of the window
* this is where windows get tied to sockets
*/
static int
{
struct drt_window *winp;
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
/* get correct socket */
/* initialize the socket map - one socket per window */
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
return (SUCCESS);
}
/*
* drt_get_adapter()
* SocketServices GetAdapter function
* this is nearly a no-op.
*/
static int
{
return (SUCCESS);
}
/*
* drt_get_page()
* SocketServices GetPage function
* returns info about the window
*/
static int
{
struct drt_window *winp;
return (BAD_PAGE);
return (SUCCESS);
}
/*
* drt_get_socket()
* SocketServices GetSocket
* returns information about the current socket settings
*/
static int
{
int socknum, irq_enabled;
#if 0
#endif
return (SUCCESS);
}
/*
* drt_get_status()
* SocketServices GetStatus
* returns status information about the PC Card in
* the selected socket
*/
static int
{
int socknum, irq_enabled;
#if defined(DRT_DEBUG)
if (drt_debug) {
}
#endif
return (BAD_ADAPTER);
}
return (SUCCESS);
}
/*
* drt_get_window()
* SocketServices GetWindow function
* returns state information about the specified window
*/
static int
{
struct drt_window *winp;
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
return (BAD_WINDOW);
}
#if defined(DRT_DEBUG)
if (drt_debug) {
"\tsize=%d, speed=%d, base=%x, state=%x\n",
}
#endif
return (SUCCESS);
}
/*
* drt_ll_reset - This function handles the socket RESET signal timing and
* control.
*
* There are two variables that control the RESET timing:
* drt_prereset_time - time in mS before asserting RESET
* drt_reset_time - time in mS to assert RESET
*
* XXX - need to rethink RESET timing delays to avoid using drv_usecwait
*/
int drt_prereset_time = 1;
int drt_reset_time = 5;
static void
{
if (drt_prereset_time > 0)
/* turn reset on then off again */
if (drt_reset_time > 0)
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
}
/*
* drt_new_card()
* put socket into known state on card insertion
*/
static void
{
}
/*
* drt_reset_socket()
* SocketServices ResetSocket function
* puts the PC Card in the socket into the RESET state
* and then takes it out after the the cycle time
* The socket is back to initial state when done
*/
static int
{
int window;
if (mode == RESET_MODE_FULL) {
/* need to unmap windows, etc. */
}
}
return (SUCCESS);
}
/*
* drt_set_interrupt()
* SocketServices SetInterrupt function
*/
static int
{
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
return (BAD_IRQ);
}
} else {
}
/* interrupt handlers for both interrupts already done in attach */
/*
* need to fill in cookies in event of multiple high priority
* interrupt handlers on same IRQ
*/
return (SUCCESS);
}
/*
* drt_clear_interrupt()
* SocketServices ClearInterrupt function
* "What controls the socket interrupt?"
*/
static int
{
int i = 0;
#if defined(DRT_DEBUG)
if (drt_debug)
"pc_handlers = %p\n",
#endif
/* Check if there is only one handler left */
} else {
}
}
break;
}
}
#ifdef lint
if (i > 0)
panic("lint panic");
#endif
return (SUCCESS);
}
static void
{
int done;
}
done++;
}
}
/*ARGSUSED*/
int
{
int result = 0;
#if defined(DRT_DEBUG)
if (drt_debug > 2)
priority);
#endif
/*
* If we're suspended, then we don't need to process
* any more interrupts. We have already (or will
* shortly) be disabling all interrupts on the
* adapter, but we still need to ACK any that
* we receive and that the adapter has generated.
* XXX - do we really want to do this here, or does it
* make more sense to let the clients receive any
* interrupts even as we're in the process of
* suspending?
*/
return (DDI_INTR_CLAIMED);
}
#if defined(DRT_DEBUG)
#endif
#if defined(DRT_DEBUG)
if (drt_debug > 2)
"\tintr-> socket=%d, priority=%d, intr=%p,"
"arg1=%p arg2=%p (drt_flags=%x:%s)\n",
"true":"false");
#endif
#if 0
/* may need to rethink the priority stuff */
}
#else
#endif
}
/* do a round robin adjust */
return (result);
}
{
int i, intr_sockets = 0;
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
/*
* need to change to only ACK and touch the slot that
* actually caused the interrupt. Currently everything
* is acked
*
* we need to look at all known sockets to determine
* what might have happened, so step through the list
* of them
*/
result = 0;
for (i = 0; i < DRSOCKETS; i++) {
int card_type;
else
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
/* ack the interrupts we see */
if (changes & DRSTAT_SCINT) {
#if defined(DRT_DEBUG)
if (drt_debug)
"\tcard status change interrupt"
" on socket %d\n", i);
#endif
/*
* We set the result here mainly for IF_MEMORY cases.
* The drt_do_intr() call at the end of this for loop
* will not be called for IF_MEMORY cases since
* intr_sockets are set ONLY for IF_IO cases.
*/
/* there was a valid interrupt on status change */
/* nothing to do */
continue;
}
if (changes & DRSTAT_CDCHG) {
DRT_CARD_PRESENT) &&
(changes & DRSTAT_CD_MASK) !=
/*
* stop interrupt handler
* then do the callback
*/
drt_stop_intr(drt, i);
/*
* XXX - note that drt_new_card will
* clear sockp->drt_flags
*/
PCE_CARD_REMOVAL, i);
continue;
} else {
if ((changes & DRSTAT_CD_MASK) ==
DRT_CARD_PRESENT)) {
drt_new_card(drt, i);
drt_ll_reset(drt, i);
changes);
i);
continue;
}
}
/*
* since other events may be the result of
* "bounce", don't check them on this pass.
* The insert code will check them anyway.
*/
continue;
}
#if defined(DRT_DEBUG)
"memory" : "I/O");
#endif
changes & DRSTAT_RDYCHG &&
changes & DRSTAT_RDYST) {
}
/* write protect switch moved */
if (changes & DRSTAT_WPST)
else
}
changes & DRSTAT_BVDCHG) {
/*
* there was a change in battery state.
* this could be a false alarm at
* card insertion but could be real.
* The individual change bits aren't
* meaningful so look at the live
* status and latch that
*/
switch (changes & DRSTAT_BVDST) {
case DRSTAT_BATT_LOW:
DRT_BATTERY_LOW)) {
i);
}
break;
case DRSTAT_BATT_OK:
break;
default: /* battery failed */
DRT_BATTERY_DEAD)) {
/* so we only see one of them */
i);
}
}
}
!(changes & DRSTAT_BVD1ST)) {
/*
* Disable status change interrupts. We
* will enable them again later after
* Card Services has processed this
* event.
*/
/* we have an I/O status change */
i);
}
#if 0
/*
* need to reexamine this section to see what really
* needs to be done
*/
/* Battery Warn Detect */
if (changes & DRSTAT_BVD2CHG) {
i);
i);
}
}
/* Battery Fail Detect */
changes & DRSTAT_BVD1CHG &&
/* so we only see one of them */
}
#endif
}
/* now flag any PC Card interrupts */
intr_sockets |= 1 << i;
}
#if defined(DRT_DEBUG)
if (drt_debug)
i,
#endif
}
for (i = 0; i < DRSOCKETS; i++) {
if (intr_sockets & (1 << i))
}
return (DDI_INTR_CLAIMED);
return (DDI_INTR_CLAIMED);
}
return (DDI_INTR_UNCLAIMED);
}
{
int i, result;
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
/*
* we need to look at all known sockets to determine
* what might have happened, so step through the list
* of them
*/
/* XXX is this the lost interrupt problem?? XXX */
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
}
}
if (result)
return (DDI_INTR_CLAIMED);
return (DDI_INTR_UNCLAIMED);
}
/*
* drt_socket_card_id()
* figure out current status of card in socket
* this is used to prevent callbacks at card insertion
*/
/* ARGSUSED */
void
{
/* need to record if a card is present to init state */
/* check battery state to avoid callbacks */
switch (status & DRSTAT_BVDST) {
case DRSTAT_BATT_LOW:
break;
case DRSTAT_BATT_OK:
break;
default:
/* battery dead */
break;
}
/* check write protect status */
if (status & DRSTAT_WPST)
else
if (status & DRSTAT_RDYST)
else
}
#if defined(DRT_DEBUG)
static void
{
int i;
"\020\1IFTYPE\2SFTRST\3SPKREN\4IOILVL\5IOIE\6RSVD"
"\7CTOIE\010WPIE\011RDYIE\012BVD1IE\013BVD2IE\014CDIE"
"\015SCILVL\016PROMEN\017RSVDX");
"\020\1PCIFOE\1MSTPWR\7APWREN"
"\10RSVD\11DIAGEN\12WAITDB\13WPDB\14RDYDB\15BVD1DB\16BVD2DB"
"\17CD1DB\20LPBKEN");
"\020\1PWRON\2WAITST\3WPST"
"\4RDYST\5BVD1ST\6BVD2ST\7CD1ST\10CD2ST\11PCTO\12WPCHG"
"\13RDCHG\14BVD1CHG\15BVD2CHG\16CDCHG\17SCINT\20IOINT");
"\tstat1: types=%x, rev=%x\n",
for (i = 0; i < 3; i++) {
"aspsel=%x, base=%x\n", i,
}
}
#endif
/*
*/
static void
{
switch (cmd) {
case DRT_SAVE_HW_STATE:
}
}
break;
case DRT_RESTORE_HW_STATE:
}
/* work around for false status bugs */
/* XXX - why 0x3FFF and not 0xFFFF?? */
}
break;
} /* switch */
}
/*
* drt_fixprops(dip)
* if the adapter predates 1275 properties, add them.
* We do this by checking presence of the property
* and adding what we know if properties not present
*/
/* ARGSUSED */
static void
{
/*
* note that there are a number of properties that
* should be added here if not present
*/
}
/*
* stpra_alloc_map()
* allocate an stpramap structure.
*/
struct stpramap *
{
if (stpra_freelist != NULL) {
}
KM_SLEEP);
} else {
}
return (new);
}
/*
* stpra_free_map(map)
* return a used map to the freelist.
* Should probably check to see if above
* some threshold and kmem_free() any excess
*/
void
{
}
}
/*
* stpra_free(map, base, len)
* return the specified range (base to base+len)
* to the specified map
*/
void
{
/*
* always allocate a map entry so we can manipulate
* things without blocking inside our lock
*/
newmap = stpra_alloc_map();
/* now find where range lies and fix things up */
if (mapend == 0) {
/*
* special case: sum is larger than 32bit
*/
}
/* simple - on front */
/*
* don't need to check if it merges with
* previous since that would match on on end
*/
break;
/* simple - on end */
/* merge with next node */
}
break;
/* somewhere in between so just an insert */
break;
}
/* else haven't found the spot yet */
}
/* special case of running off the end - stick on end */
}
}
/*
* stpra_alloc(map, reqest, return)
* Allocate a memory-like resource (physical memory, I/O space)
* subject to the constraints defined in the request structure.
*/
int
{
else
type = 0;
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
ret->ra_addr_hi = 0;
ret->ra_addr_lo = 0;
return (DDI_FAILURE);
}
}
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
}
#if defined(DRT_DEBUG)
if (drt_debug)
(void *)mapp);
#endif
lower = 0;
if (type != STP_RA_ALLOC_SPECIFIED) {
/* first fit - not user specified */
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
/* a candidate -- apply constraints */
/* same as the above case */
continue;
}
#if defined(DRT_DEBUG)
if (drt_debug)
"\tbase=%x, ra_base=%x,"
"mask=%x\n",
#endif
/*
* failed a critical constraint
* adjust and see if it still fits
*/
#if defined(DRT_DEBUG)
if (drt_debug)
"\tnew base=%x\n",
base);
#endif
continue;
}
/* we have a fit */
#if defined(DRT_DEBUG)
if (drt_debug)
#endif
#ifdef lint
#endif
/* in the middle or end */
/* on the end */
} else {
}
} else {
/* at the beginning */
/* remove the whole node */
}
}
rval = DDI_SUCCESS;
break;
}
}
} else {
/* this is the node */
/* no match */
base = 0;
} else {
/* this is the one */
/* at the front */
/* used it up */
}
} else {
/* on the end or in middle */
/* on end */
} else {
/* in the middle */
}
}
}
rval = DDI_SUCCESS;
break;
}
}
}
if (old)
if (newmap)
if (rval == DDI_SUCCESS) {
ret->ra_addr_hi = 0;
}
return (rval);
}
/*
* stpra_fix_pow2(value)
* a utility function which rounds up to the
* nearest power of two value.
*/
{
int i;
return (value);
/* not a power of two so round up */
#if defined(DRT_DEBUG)
if (drt_debug) {
1 << i);
}
#endif
return (1 << i);
}