bge_main.c revision 8eb6c4f9472d7b6f007c889f8e14385510452918
/*
* 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/bge_impl.h"
/*
* This is the string displayed by modinfo, etc.
* Make sure you keep the version ID up to date!
*/
static char bge_ident[] = "BCM579x driver v0.47";
/*
* Property names
*/
static char debug_propname[] = "bge-debug-flags";
static char clsize_propname[] = "cache-line-size";
static char latency_propname[] = "latency-timer";
static char localmac_boolname[] = "local-mac-address?";
static char localmac_propname[] = "local-mac-address";
static char macaddr_propname[] = "mac-address";
static char subdev_propname[] = "subsystem-id";
static char subven_propname[] = "subsystem-vendor-id";
static char rxrings_propname[] = "bge-rx-rings";
static char txrings_propname[] = "bge-tx-rings";
static char default_mtu[] = "default-mtu";
static int bge_add_intrs(bge_t *, int);
static void bge_rem_intrs(bge_t *);
/*
* Describes the chip's DMA engine
*/
static ddi_dma_attr_t dma_attr = {
DMA_ATTR_V0, /* dma_attr version */
0x0000000000000000ull, /* dma_attr_addr_lo */
0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */
0x00000000FFFFFFFFull, /* dma_attr_count_max */
0x0000000000000001ull, /* dma_attr_align */
0x00000FFF, /* dma_attr_burstsizes */
0x00000001, /* dma_attr_minxfer */
0x000000000000FFFFull, /* dma_attr_maxxfer */
0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
0x00000001, /* dma_attr_granular */
0 /* dma_attr_flags */
};
/*
* PIO access attributes for registers
*/
static ddi_device_acc_attr_t bge_reg_accattr = {
};
/*
* DMA access attributes for descriptors: NOT to be byte swapped.
*/
static ddi_device_acc_attr_t bge_desc_accattr = {
};
/*
* DMA access attributes for data: NOT to be byte swapped.
*/
static ddi_device_acc_attr_t bge_data_accattr = {
};
static ether_addr_t bge_broadcast_addr = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
/*
* Versions of the O/S up to Solaris 8 didn't support network booting
* from any network interface except the first (NET0). Patching this
* flag to a non-zero value will tell the driver to work around this
* limitation by creating an extra (internal) pathname node. To do
* file ON THE ROOT FILESYSTEM SERVER before booting the client:
*
* set bge:bge_net1_boot_support = 1;
*/
/*
* ========== Transmit and receive ring reinitialisation ==========
*/
/*
* These <reinit> routines each reset the specified ring to an initial
* state, assuming that the corresponding <init> routine has already
* been called exactly once.
*/
static void
{
/*
* Reinitialise control variables ...
*/
/*
* Zero and sync all the h/w Send Buffer Descriptors
*/
}
static void
{
/*
* Reinitialise control variables ...
*/
}
static void
{
};
/*
* Zero, initialise and sync all the h/w Receive Buffer Descriptors
* Note: all the remaining fields (<type>, <flags>, <ip_cksum>,
* <tcp_udp_cksum>, <error_flag>, <vlan_tag>, and <reserved>)
* should be zeroed, and so don't need to be set up specifically
* once the whole area has been cleared.
*/
}
/*
* Finally, reinitialise the ring control variables ...
*/
}
/*
* Reinitialize all rings
*/
static void
{
/*
* Send Rings ...
*/
/*
* Receive Return Rings ...
*/
/*
* Receive Producer Rings ...
*/
}
/*
* ========== Internal state management entry points ==========
*/
/*
* These routines provide all the functionality required by the
* corresponding GLD entry points, but don't update the GLD state
* so they can be called internally without disturbing our record
* of what GLD thinks we should be doing ...
*/
/*
* bge_reset() -- reset h/w & rings to initial state
*/
static void
{
/*
* Grab all the other mutexes in the world (this should
* ensure no other threads are manipulating driver state)
*/
/*
* Free the world ...
*/
}
/*
* bge_stop() -- stop processing, don't reset h/w or rings
*/
static void
{
}
/*
* bge_start() -- start transmitting/receiving
*/
static void
{
/*
* Start chip processing, including enabling interrupts
*/
}
/*
* bge_restart - restart transmitting/receiving after error or suspend
*/
void
{
}
}
/*
* ========== Nemo-required management entry points ==========
*/
/*
* bge_m_stop() -- stop transmitting/receiving
*/
static void
bge_m_stop(void *arg)
{
/*
* Just stop processing, then record new GLD state
*/
}
/*
* bge_m_start() -- start transmitting/receiving
*/
static int
bge_m_start(void *arg)
{
/*
* Start processing and record new GLD state
*/
return (0);
}
/*
* bge_m_unicst_set() -- set the physical network address
*/
static int
{
ether_sprintf((void *)macaddr)));
/*
* Remember the new current address in the driver state
* Sync the chip's idea of the address too ...
*/
return (0);
}
/*
* Compute the index of the required bit in the multicast hash map.
* This must mirror the way the hardware actually does it!
* See Broadcom document 570X-PG102-R page 125.
*/
static uint32_t
{
return (hash);
}
/*
*/
static int
{
/*
* Precalculate all required masks, pointers etc ...
*/
BGE_DEBUG(("bge_m_multicst: hash 0x%x index %d (%d:0x%x) = %d",
/*
* We must set the appropriate bit in the hash map (and the
* corresponding h/w register) when the refcount goes from 0
* to >0, and clear it when the last ref goes away (refcount
* goes from >0 back to 0). If we change the hash map, we
* must also update the chip's hardware map registers.
*/
if (add) {
if ((*refp)++ == 0) {
}
} else {
if (--(*refp) == 0) {
}
}
return (0);
}
/*
* bge_m_promisc() -- set or reset promiscuous mode on the board
*
* receive-all-multicast modes.
*/
static int
{
/*
* Store MAC layer specified mode and pass to chip layer to update h/w
*/
return (0);
}
/*
* Loopback ioctl code
*/
static lb_property_t loopmodes[] = {
};
static enum ioc_reply
{
const char *msg;
/*
* If the mode isn't being changed, there's nothing to do ...
*/
return (IOC_ACK);
/*
* Validate the requested mode and prepare a suitable message
* probably induce ...
*/
switch (mode) {
default:
return (IOC_INVAL);
case BGE_LOOP_NONE:
msg = " (loopback disabled)";
break;
case BGE_LOOP_EXTERNAL_1000:
case BGE_LOOP_EXTERNAL_100:
case BGE_LOOP_EXTERNAL_10:
msg = " (external loopback selected)";
break;
case BGE_LOOP_INTERNAL_PHY:
msg = " (PHY internal loopback selected)";
break;
case BGE_LOOP_INTERNAL_MAC:
msg = " (MAC internal loopback selected)";
break;
}
/*
* All OK; tell the caller to reprogram
*/
return (IOC_RESTART_ACK);
}
static enum ioc_reply
{
int cmd;
/*
* Validate format of ioctl
*/
return (IOC_INVAL);
switch (cmd) {
default:
/* NOTREACHED */
return (IOC_INVAL);
case LB_GET_INFO_SIZE:
return (IOC_INVAL);
return (IOC_REPLY);
case LB_GET_INFO:
return (IOC_INVAL);
return (IOC_REPLY);
case LB_GET_MODE:
return (IOC_INVAL);
return (IOC_REPLY);
case LB_SET_MODE:
return (IOC_INVAL);
}
}
/*
* Specific bge IOCTLs, the gld module handles the generic ones.
*/
static void
{
int err;
int cmd;
/*
* Validate the command before bothering with the mutex ...
*/
switch (cmd) {
default:
return;
case BGE_MII_READ:
case BGE_MII_WRITE:
case BGE_SEE_READ:
case BGE_SEE_WRITE:
case BGE_DIAG:
case BGE_PEEK:
case BGE_POKE:
case BGE_PHY_RESET:
case BGE_SOFT_RESET:
case BGE_HARD_RESET:
break;
case LB_GET_INFO_SIZE:
case LB_GET_INFO:
case LB_GET_MODE:
/* FALLTHRU */
case LB_SET_MODE:
break;
case ND_GET:
/* FALLTHRU */
case ND_SET:
break;
}
if (need_privilege) {
/*
* Check for specific net_config privilege on Solaris 10+.
* Otherwise just check for root access ...
*/
if (secpolicy_net_config != NULL)
else
if (err != 0) {
return;
}
}
switch (cmd) {
default:
break;
case BGE_MII_READ:
case BGE_MII_WRITE:
case BGE_SEE_READ:
case BGE_SEE_WRITE:
case BGE_DIAG:
case BGE_PEEK:
case BGE_POKE:
case BGE_PHY_RESET:
case BGE_SOFT_RESET:
case BGE_HARD_RESET:
break;
case LB_GET_INFO_SIZE:
case LB_GET_INFO:
case LB_GET_MODE:
case LB_SET_MODE:
break;
case ND_GET:
case ND_SET:
break;
}
/*
* Do it now, while we still have the mutex.
*
* Note: update the PHY first, 'cos it controls the
*/
switch (status) {
case IOC_RESTART_REPLY:
case IOC_RESTART_ACK:
break;
}
/*
* Finally, decide how to reply
*/
switch (status) {
default:
case IOC_INVAL:
/*
* Error, reply with a NAK and EINVAL or the specified error
*/
break;
case IOC_DONE:
/*
* OK, reply already sent
*/
break;
case IOC_RESTART_ACK:
case IOC_ACK:
/*
* OK, reply with an ACK
*/
break;
case IOC_RESTART_REPLY:
case IOC_REPLY:
/*
* OK, send prepared reply as ACK or NAK
*/
break;
}
}
static void
bge_m_resources(void *arg)
{
int ring;
/*
* Register Rx rings as resources and save mac
* resource id for future reference
*/
(mac_resource_t *)&mrf);
}
}
/*
*/
/*
* Utility routine to carve a slice off a chunk of allocated memory,
* updating the chunk descriptor accordingly. The size of the slice
* is given by the product of the <qty> and <size> parameters.
*/
static void
{
}
/*
* Initialise the specified Receive Producer (Buffer) Ring, using
* the information in the <dma_area> descriptors that it contains
* to set up all the other fields. This routine should be called
* only once for each ring.
*/
static void
{
};
};
};
BGE_TRACE(("bge_init_buff_ring($%p, %d)",
/*
* Set up the copy of the h/w RCB
*
* Note: unlike Send & Receive Return Rings, (where the max_len
* field holds the number of slots), in a Receive Buffer Ring
* this field indicates the size of each buffer in the ring.
*/
/*
* Other one-off initialisation of per-ring data
*/
/*
* Allocate the array of s/w Receive Buffer Descriptors
*/
/*
* Now initialise each array element once and for all
*/
}
}
/*
* Clean up initialisation done above before the memory is freed
*/
static void
{
BGE_TRACE(("bge_fini_buff_ring($%p, %d)",
}
/*
* Initialise the specified Receive (Return) Ring, using the
* information in the <dma_area> descriptors that it contains
* to set up all the other fields. This routine should be called
* only once for each ring.
*/
static void
{
BGE_TRACE(("bge_init_recv_ring($%p, %d)",
/*
* The chip architecture requires that receive return rings have
* 512 or 1024 or 2048 elements per ring. See 570X-PG108-R page 103.
*/
/*
* Set up the copy of the h/w RCB
*/
/*
* Other one-off initialisation of per-ring data
*/
}
/*
* Clean up initialisation done above before the memory is freed
*/
static void
{
BGE_TRACE(("bge_fini_recv_ring($%p, %d)",
if (rrp->rx_softint)
}
/*
* Initialise the specified Send Ring, using the information in the
* <dma_area> descriptors that it contains to set up all the other
* fields. This routine should be called only once for each ring.
*/
static void
{
BGE_TRACE(("bge_init_send_ring($%p, %d)",
/*
* The chip architecture requires that host-based send rings
* have 512 elements per ring. See 570X-PG102-R page 56.
*/
/*
* Set up the copy of the h/w RCB
*/
/*
* Other one-off initialisation of per-ring data
*/
/*
* Allocate the array of s/w Send Buffer Descriptors
*/
/*
* Now initialise each array element once and for all
*/
sizeof (bge_sbd_t));
}
}
}
/*
* Clean up initialisation done above before the memory is freed
*/
static void
{
BGE_TRACE(("bge_fini_send_ring($%p, %d)",
}
/*
* Initialise all transmit, receive, and buffer rings.
* (also a few top-level mutexen that can't be done until
* the h/w interrupt handler has been registered 'cos we
* need the cookie).
*/
static void
{
/*
* Perform one-off initialisation of each ring ...
*/
}
/*
* Undo the work of bge_init_rings() above before the memory is freed
*/
static void
{
}
/*
* Allocate an area of memory and a DMA handle for accessing it
*/
static int
{
int err;
BGE_TRACE(("bge_alloc_dma_mem($%p, %ld, $%p, 0x%x, $%p)",
/*
* Allocate handle
*/
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
/*
* Allocate memory
*/
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
/*
* Bind the two together
*/
BGE_DEBUG(("bge_alloc_dma_mem(): bind %d bytes; err %d, %d cookies",
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
/*
* Free one allocated area of DMAable memory
*/
static void
{
}
}
}
}
/*
* This function allocates all the transmit and receive buffers
* and descriptors, in four chunks (or one, if MONOLITHIC).
*/
static int
{
int split;
int err;
BGE_TRACE(("bge_alloc_bufs($%p)",
(void *)bgep));
txbuffsize *= tx_rings;
rxdescsize *= sizeof (bge_rbd_t);
rxbuffdescsize *= sizeof (bge_rbd_t);
txdescsize *= sizeof (bge_sbd_t);
txdescsize += sizeof (bge_statistics_t);
txdescsize += sizeof (bge_status_t);
#if BGE_MONOLITHIC
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
BGE_DEBUG(("allocated range $%p-$%p (0x%lx-0x%lx)",
#else
/*
* Allocate memory & handles for RX buffers
*/
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
/*
* Allocate memory & handles for TX buffers
*/
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
/*
* Allocate memory & handles for receive return rings
*/
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
/*
* Allocate memory & handles for buffer (producer) descriptor rings
*/
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
/*
* Allocate memory & handles for TX descriptor rings,
* status block, and statistics area
*/
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
#endif /* BGE_MONOLITHIC */
/*
* Now carve up each of the allocated areas ...
*/
}
}
0, sizeof (bge_rbd_t));
BGE_STD_SLOTS_USED, sizeof (bge_rbd_t));
BGE_MINI_SLOTS_USED, sizeof (bge_rbd_t));
BGE_SEND_SLOTS_USED, sizeof (bge_sbd_t));
0, sizeof (bge_sbd_t));
return (DDI_SUCCESS);
}
/*
* This routine frees the transmit and receive buffers and descriptors.
* Make sure the chip is stopped before calling it!
*/
static void
{
int split;
BGE_TRACE(("bge_free_bufs($%p)",
(void *)bgep));
#if BGE_MONOLITHIC
#else
#endif /* BGE_MONOLITHIC */
}
/*
* Determine (initial) MAC address ("BIA") to use for this interface
*/
static void
{
struct ether_addr sysaddr;
int *ints;
int err;
BGE_TRACE(("bge_find_mac_address($%p)",
(void *)bgep));
BGE_DEBUG(("bge_find_mac_address: hw_mac_addr %012llx, => %s (%sset)",
/*
* The "vendor's factory-set address" may already have
* been extracted from the chip, but if the property
* "local-mac-address" is set we use that instead. It
* will normally be set by OBP, but it could also be
* specified in a .conf file(!)
*
* There doesn't seem to be a way to define byte-array
* properties in a .conf, so we check whether it looks
* like an array of 6 ints instead.
*
* Then, we check whether it looks like an array of 6
* bytes (which it should, if OBP set it). If we can't
* make sense of it either way, we'll ignore it.
*/
if (err == DDI_PROP_SUCCESS) {
if (nelts == ETHERADDRL) {
while (nelts--)
}
}
if (err == DDI_PROP_SUCCESS) {
if (nelts == ETHERADDRL) {
while (nelts--)
}
}
BGE_DEBUG(("bge_find_mac_address: +local %s (%sset)",
/*
* Look up the OBP property "local-mac-address?". Note that even
* though its value is a string (which should be "true" or "false"),
* it can't be decoded by ddi_prop_lookup_string(9F). So, we zero
* the buffer first and then fetch the property as an untyped array;
* this may or may not include a final NUL, but since there will
* always be one left at the end of the buffer we can now treat it
* as a string anyway.
*/
/*
* Now, if the address still isn't set from the hardware (SEEPROM)
* or the OBP or .conf property, OR if the user has foolishly set
* 'local-mac-address? = false', use "the system address" instead
* (but only if it's non-null i.e. has been set from the IDPROM).
*/
}
BGE_DEBUG(("bge_find_mac_address: +system %s (%sset)",
/*
* Finally(!), if there's a valid "mac-address" property (created
* if we netbooted from this interface), we must use this instead
* get confused by the address changing as Solaris takes over!
*/
if (err == DDI_PROP_SUCCESS) {
if (nelts == ETHERADDRL) {
while (nelts--)
}
}
BGE_DEBUG(("bge_find_mac_address: =final %s (%sset)",
}
static void
{
BGE_TRACE(("bge_unattach($%p)",
(void *)bgep));
/*
* Flag that no more activity may be initiated
*/
/*
* Quiesce the PHY and MAC (leave it reset but still powered).
* Clean up and free all BGE data structures
*/
}
}
}
}
static int
{
return (DDI_FAILURE);
/*
* Refuse to resume if the data structures aren't consistent
*/
return (DDI_FAILURE);
/*
* Read chip ID & set up config space command register(s)
* Refuse to resume if the chip has changed its identity!
*/
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_FAILURE);
/*
* All OK, reinitialise h/w & kick off GLD scheduling
*/
return (DDI_SUCCESS);
}
/*
* attach(9E) -- Attach a device to the system
*
* Called once for each board successfully probed.
*/
static int
{
int instance;
int err;
int intr_types;
int i;
BGE_GTRACE(("bge_attach($%p, %d) instance %d",
switch (cmd) {
default:
return (DDI_FAILURE);
case DDI_RESUME:
return (bge_resume(devinfo));
case DDI_ATTACH:
break;
}
/*
* Allocate mac_t and BGE private structures, and
* cross-link them so that given either one of these or
* the devinfo the others can be derived.
*/
/*
* Initialize more fields in BGE private data
*/
/*
* Look up the IOMMU's page size for DVMA mappings (must be
* a power of 2) and convert to a mask. This can be used to
* determine whether a message buffer crosses a page boundary.
* Note: in 2s complement binary notation, if X is a power of
* 2, then -X has the representation "11...1100...00".
*/
/*
* Map config space registers
* Read chip ID & set up config space command register(s)
*
* Note: this leaves the chip accessible by Memory Space
* accesses, but with interrupts and Bus Mastering off.
* This should ensure that nothing untoward will happen
* if it has been left active by the (net-)bootloader.
* We'll re-enable Bus Mastering once we've reset the chip,
* and allow interrupts only when everything else is set up.
*/
if (err != DDI_SUCCESS) {
goto attach_fail;
}
/*
* Update those parts of the chip ID derived from volatile
* registers with the values seen by OBP (in case the chip
* has been reset externally and therefore lost them).
*/
if (bge_jumbo_enable == B_TRUE) {
}
}
/*
* Map operating registers
*/
if (err != DDI_SUCCESS) {
goto attach_fail;
}
/*
* Characterise the device, so we know its requirements.
* Then allocate the appropriate TX and RX descriptors & buffers.
*/
if (err != DDI_SUCCESS) {
goto attach_fail;
}
/*
* Add the softint handlers:
*
* Both of these handlers are used to avoid restrictions on the
* particular, the hardware interrupt handler and its subfunctions
* can detect a number of conditions that we don't want to handle
* in that context or with that set of mutexes held. So, these
* softints are triggered instead:
*
* the <resched> softint is triggered if if we have previously
* had to refuse to send a packet because of resource shortage
* (we've run out of transmit buffers), but the send completion
* interrupt handler has now detected that more buffers have
* become available.
*
* the <factotum> is triggered if the h/w interrupt handler
* sees the <link state changed> or <error> bits in the status
* block. It's also triggered periodically to poll the link
* state, just in case we aren't getting link status change
* interrupts ...
*/
if (err != DDI_SUCCESS) {
goto attach_fail;
}
if (err != DDI_SUCCESS) {
goto attach_fail;
}
/* Get supported interrupt types */
goto attach_fail;
}
"trying FIXED interrupt type\n");
} else {
}
}
(intr_types & DDI_INTR_TYPE_FIXED)) {
"registration failed\n");
goto attach_fail;
}
}
goto attach_fail;
}
/*
* Note that interrupts are not enabled yet as
* mutex locks are not initialized.
* Initialize rings and mutex locks.
*/
/*
* Now that mutex locks are initialized, enable interrupts.
*/
/* Call ddi_intr_block_enable() for MSI interrupts */
} else {
/* Call ddi_intr_enable for MSI or FIXED interrupts */
}
}
/*
* Initialise link state variables
* Stop, reset & reinitialise the chip.
* Initialise the (internal) PHY.
*/
/*
* Reset chip & rings to initial state; also reset address
* filtering, promiscuity, loopback mode.
*/
/*
* Register NDD-tweakable parameters
*/
if (bge_nd_init(bgep)) {
goto attach_fail;
}
/*
* Create & initialise named kstats
*/
/*
* Determine whether to override the chip's own MAC address
*/
/*
* Initialize pointers to device specific functions which
* will be used by the generic layer.
*/
mip->mi_sdu_min = 0;
/*
* Finally, we're ready to register ourselves with the MAC layer
* interface; if this succeeds, we're all ready to start()
*/
if (mac_register(macp) != 0)
goto attach_fail;
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
/*
*/
static int
{
/*
* Stop processing and idle (powerdown) the PHY ...
*/
return (DDI_SUCCESS);
}
/*
* detach(9E) -- Detach a device from the system
*/
static int
{
switch (cmd) {
default:
return (DDI_FAILURE);
case DDI_SUSPEND:
return (bge_suspend(bgep));
case DDI_DETACH:
break;
}
/*
* Unregister from the GLD subsystem. This can fail, in
* particular if there are DLPI style-2 streams still open -
* in which case we just return failure without shutting
* down chip operations.
*/
return (DDI_FAILURE);
/*
* All activity stopped, so we can clean up & exit
*/
return (DDI_SUCCESS);
}
/*
* ========== Module Loading Data & Entry Points ==========
*/
static struct modldrv bge_modldrv = {
&mod_driverops, /* Type of module. This one is a driver */
bge_ident, /* short description */
&bge_dev_ops /* driver specific ops */
};
static struct modlinkage modlinkage = {
};
int
{
}
int
_init(void)
{
int status;
if (status == DDI_SUCCESS)
else
return (status);
}
int
_fini(void)
{
int status;
if (status == DDI_SUCCESS) {
}
return (status);
}
/*
* bge_add_intrs:
*
* Register FIXED or MSI interrupts.
*/
static int
{
/* Get number of interrupts */
return (DDI_FAILURE);
}
/* Get number of available interrupts */
return (DDI_FAILURE);
}
}
/*
* BGE hardware generates only single MSI even though it claims
* to support multiple MSIs. So, hard code MSI count value to 1.
*/
if (intr_type == DDI_INTR_TYPE_MSI) {
count = 1;
} else {
}
/* Allocate an array of interrupt handles */
/* Call ddi_intr_alloc() */
return (DDI_FAILURE);
}
}
/*
* Get priority for first msi, assume remaining are all the same
*/
DDI_SUCCESS) {
/* Free already allocated intr */
for (i = 0; i < actual; i++) {
}
return (DDI_FAILURE);
}
/* Call ddi_intr_add_handler() */
for (i = 0; i < actual; i++) {
"failed %d\n", ret);
/* Free already allocated intr */
for (i = 0; i < actual; i++) {
}
return (DDI_FAILURE);
}
}
!= DDI_SUCCESS) {
for (i = 0; i < actual; i++) {
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* bge_rem_intrs:
*
* Unregister FIXED or MSI interrupts
*/
static void
{
int i;
/* Disable all interrupts */
/* Call ddi_intr_block_disable() */
} else {
}
}
/* Call ddi_intr_remove_handler() */
}
}