Commit c9b01df3 authored by Solomon Peachy's avatar Solomon Peachy Committed by Greg Kroah-Hartman

Staging: wlan-ng: Remove PCI/PLX/PCMCIA files.

This portion of the driver is not needed at all, so remove it.
Signed-off-by: default avatarSolomon Peachy <pizza@shaftnet.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f02466fc
......@@ -3,6 +3,5 @@ TODO:
- sparse warnings
- Lindent cleanups
- move to use the in-kernel wireless stack
- possible enable the pcmcia and pci portions of the driver
Please send all patches to Greg Kroah-Hartman <greg@kroah.com>
This source diff could not be displayed because it is too large. You can view the blob instead.
#define WLAN_HOSTIF WLAN_PCMCIA
#include "hfa384x.c"
#include "prism2mgmt.c"
#include "prism2mib.c"
#include "prism2sta.c"
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) )
#if (WLAN_CPU_FAMILY == WLAN_Ix86)
#ifndef CONFIG_ISA
#warning "You may need to enable ISA support in your kernel."
#endif
#endif
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
static u_int irq_mask = 0xdeb8; /* Interrupt mask */
static int irq_list[4] = { -1 }; /* Interrupt list */
#endif
static u_int prism2_ignorevcc=1; /* Boolean, if set, we
* ignore what the Vcc
* is set to and what the CIS
* says.
*/
module_param( prism2_ignorevcc, int, 0644);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9))
static int numlist = 4;
module_param_array(irq_list, int, numlist, 0444);
#else
module_param_array(irq_list, int, NULL, 0444);
#endif
module_param( irq_mask, int, 0644);
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
static int prism2_cs_suspend(struct pcmcia_device *pdev);
static int prism2_cs_resume(struct pcmcia_device *pdev);
static void prism2_cs_remove(struct pcmcia_device *pdev);
static int prism2_cs_probe(struct pcmcia_device *pdev);
#else
dev_link_t *prism2sta_attach(void);
static void prism2sta_detach(dev_link_t *link);
static void prism2sta_config(dev_link_t *link);
static void prism2sta_release(u_long arg);
static int prism2sta_event (event_t event, int priority, event_callback_args_t *args);
static dev_link_t *dev_list = NULL; /* head of instance list */
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
/*----------------------------------------------------------------
* cs_error
*
* Utility function to print card services error messages.
*
* Arguments:
* handle client handle identifying this CS client
* func CS function number that generated the error
* ret CS function return code
*
* Returns:
* nothing
* Side effects:
*
* Call context:
* process thread
* interrupt
----------------------------------------------------------------*/
static void cs_error(client_handle_t handle, int func, int ret)
{
#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911))
CardServices(ReportError, dev_info, (void *)func, (void *)ret);
#else
error_info_t err = { func, ret };
pcmcia_report_error(handle, &err);
#endif
}
#else // kernel_version
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
static struct pcmcia_device_id prism2_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), // Intersil PRISM2 Reference Design 11Mb/s 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), // Compaq WL100/200 11Mb/s 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), // Compaq iPaq HNW-100 11Mb/s 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), // Samsung SWL2000-N 11Mb/s 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), // Z-Com XI300 11Mb/s 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), // ZoomAir 4100 11Mb/s 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), // Linksys WPC11 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID123("Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 0xe6ec52ce, 0x8649af2, 0x4b74baa0), // Addtron AWP-100 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID123("D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), // D-Link DWL-650 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID123("SMC", "SMC2632W", "Version 01.02", 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0), // SMC 2632W 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e), // BroMax Freeport 11Mbps 802.11b WLAN Card (Prism 2.5)
PCMCIA_DEVICE_PROD_ID123("U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", 0xc7b8df9d, 0x1700d087, 0x4b74baa0), // U.S. Robotics IEEE 802.11b PC-CARD
PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), // Level-One WPC-0100
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 2.5)
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), // Bromax OEM 11Mbps 802.11b WLAN Card (Prism 3)
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), // corega K.K. Wireless LAN PCC-11
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), // corega K.K. Wireless LAN PCCA-11
PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), // CONTEC FLEXSCAN/FX-DDS110-PCC
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), // PLANEX GeoWave/GW-NS110
PCMCIA_DEVICE_PROD_ID123("OEM", "PRISM2 IEEE 802.11 PC-Card", "Version 01.02", 0xfea54c90, 0x48f2bdd6, 0x4b74baa0), // Ambicom WL1100 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID123("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", "Version 01.02", 0x7e3b326a, 0x49893e92, 0x4b74baa0), // LeArtery SYNCBYAIR 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), // Intermec MobileLAN 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID123("NETGEAR MA401 Wireless PC", "Card", "Version 01.00", 0xa37434e9, 0x9762e8f1, 0xa57adb8c), // NETGEAR MA401 11Mbps 802.11 WLAN Card
PCMCIA_DEVICE_PROD_ID1234("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", "Eval-RevA", 0x4b801a17, 0xf222ec2d, 0x630d52b2, 0xc23adc0e), // Intersil PRISM Freedom 11mbps 802.11 WLAN Card
PCMCIA_DEVICE_PROD_ID123("OTC", "Wireless AirEZY 2411-PCC WLAN Card", "Version 01.02", 0x4ac44287, 0x235a6bed, 0x4b74baa0), // OTC Wireless AirEZY 2411-PCC 11Mbps 802.11 WLAN Card
PCMCIA_DEVICE_PROD_ID1234("802.11", "11Mbps Wireless LAN Card", "v08C1", "" , 0xb67a610e, 0x655aa7b7, 0x264b451a, 0x0), // Dynalink L11HDT 11Mbps 802.11 WLAN Card
PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), // Dynalink L11HDT 11Mbps 802.11 WLAN Card
PCMCIA_DEVICE_PROD_ID12("PROXIM", "RangeLAN-DS/LAN PC CARD", 0xc6536a5e, 0x3f35797d), // PROXIM RangeLAN-DS/LAN PC CARD
PCMCIA_DEVICE_PROD_ID1234("ACTIONTEC", "PRISM Wireless LAN PC Card", "0381", "RevA", 0x393089da, 0xa71e69d5, 0x90471fa9, 0x57a66194), // ACTIONTEC PRISM Wireless LAN PC Card
PCMCIA_DEVICE_MANF_CARD(0x1668, 0x0101), // ACTIONTEC PRISM Wireless LAN PC Card
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), // 3Com AirConnect 3CRWE737A
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE777A AirConnect Wireless LAN PCI Card" , 0x41240e5b, 0xafc7c33e), // 3Com AirConnect 3CRWE777A
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), // ASUS WL-100 802.11b WLAN PC Card
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), // ASUS WL-110 802.11b WLAN CF Card
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), // BUFFALO WLI-CF-S11G 802.11b WLAN Card
PCMCIA_DEVICE_PROD_ID1234("The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", "RevA", 0xa5f472c2, 0x9c05598d, 0xc9049a39, 0x57a66194), // Linksys WCF11 11Mbps 802.11b WLAN Card (Prism 2.5)
PCMCIA_DEVICE_PROD_ID1234("Linksys", "Wireless CompactFlash Card", "", "", 0x733cc81, 0xc52f395, 0x0, 0x0), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3)
PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), // Linksys WCF12 11Mbps 802.11b WLAN Card (Prism 3)
PCMCIA_DEVICE_PROD_ID1234("NETGEAR MA401RA Wireless PC", "Card", "ISL37300P", "Eval-RevA", 0x306467f, 0x9762e8f1, 0xc9049a39, 0xc23adc0e), // NETGEAR MA401RA 11Mbps 802.11 WLAN Card
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), // D-Link DCF-660W 11Mbps 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), // Microsoft Wireless Notebook Adapter MN-520
PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), // AnyPoint(TM) Wireless II PC Card
PCMCIA_DEVICE_PROD_ID1234("D", "Link DRC-650 11Mbps WLAN Card", "Version 01.02", "" , 0x71b18589, 0xf144e3ac, 0x4b74baa0, 0x0), // D-Link DRC-650 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), // Adaptec AWN-8030
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7110), // D-Link DWL-650 rev P 802.11b WLAN card
// PCMCIA_DEVICE_PROD_ID1234("D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", "A3", 0x1a424a1c, 0x6ea57632, 0xdd97a26b, 0x56b21f52), // D-Link DWL-650 rev P 802.11b WLAN card
PCMCIA_DEVICE_PROD_ID123("INTERSIL", "I-GATE 11M PC Card / PC Card plus", "Version 01.02", 0x74c5e40d, 0x8304ff77, 0x4b74baa0), // I-Gate 11M PC Card
PCMCIA_DEVICE_PROD_ID1234("BENQ", "AWL100 PCMCIA ADAPTER", "ISL37300P", "Eval-RevA", 0x35dadc74, 0x1f7fedb, 0xc9049a39, 0xc23adc0e), // benQ AWL100 802.11b WLAN Card
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), // benQ AWL100 802.11b WLAN Card
// PCMCIA_DEVICE_PROD_ID1("INTERSIL", 0x74c5e40d), // Intersil Prism 2 card
// PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), // Intersil Prism 2 card
PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, prism2_cs_ids);
#endif
static struct pcmcia_driver prism2_cs_driver = {
.drv = {
.name = "prism2_cs",
},
.owner = THIS_MODULE,
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
.suspend = prism2_cs_suspend,
.resume = prism2_cs_resume,
.remove = prism2_cs_remove,
.probe = prism2_cs_probe,
.id_table = prism2_cs_ids,
#else
.attach = prism2sta_attach,
.detach = prism2sta_detach,
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
.id_table = prism2_cs_ids,
.event = prism2sta_event,
#endif // > 2.6.12
#endif // <= 2.6.15
};
#endif /* kernel_version */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
#define CFG_CHECK(fn, retf) \
do { int ret = (retf); \
if (ret != 0) { \
WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
cs_error(pdev, fn, ret); \
goto next_entry; \
} \
} while (0)
static void prism2_cs_remove(struct pcmcia_device *pdev)
{
struct wlandevice *wlandev;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
dev_link_t *link = dev_to_instance(pdev);
#endif
DBFENTER;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
wlandev = pdev->priv;
#else
wlandev = link->priv;
#endif
if (wlandev) {
p80211netdev_hwremoved(wlandev);
unregister_wlandev(wlandev);
wlan_unsetup(wlandev);
if (wlandev->priv) {
hfa384x_t *hw = wlandev->priv;
wlandev->priv = NULL;
if (hw) {
hfa384x_destroy(hw);
kfree(hw);
}
}
kfree(wlandev);
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->priv = NULL;
pcmcia_disable_device(pdev);
#else
if (link->state & DEV_CONFIG) {
if (link->win)
pcmcia_release_window(link->win);
pcmcia_release_configuration(link->handle);
if (link->io.NumPorts1)
pcmcia_release_io(link->handle, &link->io);
if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
}
link->priv = NULL;
kfree(link);
#endif
DBFEXIT;
return;
}
static int prism2_cs_suspend(struct pcmcia_device *pdev)
{
struct wlandevice *wlandev;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
dev_link_t *link = dev_to_instance(pdev);
#endif
DBFENTER;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
wlandev = pdev->priv;
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
#else
wlandev = link->priv;
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
pcmcia_release_configuration(link->handle);
}
#endif
DBFEXIT;
return 0;
}
static int prism2_cs_resume(struct pcmcia_device *pdev)
{
struct wlandevice *wlandev;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
dev_link_t *link = dev_to_instance(pdev);
#endif
DBFENTER;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
wlandev = pdev->priv;
// XXX do something here?
#else
wlandev = link->priv;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
// XXX do something here?
}
#endif
DBFEXIT;
return 0;
}
static int prism2_cs_probe(struct pcmcia_device *pdev)
{
int rval = 0;
struct wlandevice *wlandev = NULL;
hfa384x_t *hw = NULL;
config_info_t socketconf;
cisparse_t *parse = NULL;
tuple_t tuple;
uint8_t buf[64];
int last_fn, last_ret;
cistpl_cftable_entry_t dflt = { 0 };
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
dev_link_t *link;
#endif
DBFENTER;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
/* Set up interrupt type */
pdev->conf.IntType = INT_MEMORY_AND_IO;
#else
link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
if (link == NULL)
return -ENOMEM;
memset(link, 0, sizeof(dev_link_t));
link->conf.Vcc = 33;
link->conf.IntType = INT_MEMORY_AND_IO;
link->handle = pdev;
pdev->instance = link;
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
#endif
// VCC crap?
parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL);
wlandev = create_wlan();
if (!wlandev || !parse) {
WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
rval = -EIO;
goto failed;
}
hw = wlandev->priv;
if ( wlan_setup(wlandev) != 0 ) {
WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
rval = -EIO;
goto failed;
}
/* Initialize the hw struct for now */
hfa384x_create(hw, 0, 0, NULL);
hw->wlandev = wlandev;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
hw->pdev = pdev;
pdev->priv = wlandev;
#else
hw->link = link;
link->priv = wlandev;
#endif
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, parse));
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->conf.ConfigBase = parse->config.base;
pdev->conf.Present = parse->config.rmask[0];
#else
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
link->conf.Vcc = socketconf.Vcc;
#endif
CS_CHECK(GetConfigurationInfo,
pcmcia_get_configuration_info(pdev, &socketconf));
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
for (;;) {
cistpl_cftable_entry_t *cfg = &(parse->cftable_entry);
CFG_CHECK(GetTupleData,
pcmcia_get_tuple_data(pdev, &tuple));
CFG_CHECK(ParseTuple,
pcmcia_parse_tuple(pdev, &tuple, parse));
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
if (cfg->index == 0)
goto next_entry;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->conf.ConfigIndex = cfg->index;
#else
link->conf.ConfigIndex = cfg->index;
#endif
/* Does this card need audio output? */
if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->conf.Attributes |= CONF_ENABLE_SPKR;
pdev->conf.Status = CCSR_AUDIO_ENA;
#else
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
#endif
}
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (socketconf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
10000 && !prism2_ignorevcc) {
WLAN_LOG_DEBUG(1, " Vcc mismatch - skipping"
" this entry\n");
goto next_entry;
}
} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (socketconf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] /
10000 && !prism2_ignorevcc) {
WLAN_LOG_DEBUG(1, " Vcc (default) mismatch "
"- skipping this entry\n");
goto next_entry;
}
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
#else
link->conf.Vpp1 = link->conf.Vpp2 =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
#endif
} else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->conf.Vpp =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
#else
link->conf.Vpp1 = link->conf.Vpp2 =
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
#endif
}
/* Do we need to allocate an interrupt? */
/* HACK: due to a bad CIS....we ALWAYS need an interrupt */
/* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->conf.Attributes |= CONF_ENABLE_IRQ;
#else
link->conf.Attributes |= CONF_ENABLE_IRQ;
#endif
/* IO window settings */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->io.NumPorts1 = pdev->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT))
pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
pdev->io.BasePort1 = io->win[0].base;
if ( pdev->io.BasePort1 != 0 ) {
WLAN_LOG_WARNING(
"Brain damaged CIS: hard coded iobase="
"0x%x, try letting pcmcia_cs decide...\n",
pdev->io.BasePort1 );
pdev->io.BasePort1 = 0;
}
pdev->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
pdev->io.Attributes2 = pdev->io.Attributes1;
pdev->io.BasePort2 = io->win[1].base;
pdev->io.NumPorts2 = io->win[1].len;
}
}
/* This reserves IO space but doesn't actually enable it */
CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &pdev->io));
#else
link->io.NumPorts1 = link->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.BasePort1 = io->win[0].base;
if ( link->io.BasePort1 != 0 ) {
WLAN_LOG_WARNING(
"Brain damaged CIS: hard coded iobase="
"0x%x, try letting pcmcia_cs decide...\n",
link->io.BasePort1 );
link->io.BasePort1 = 0;
}
link->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
link->io.Attributes2 = link->io.Attributes1;
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
}
/* This reserves IO space but doesn't actually enable it */
CFG_CHECK(RequestIO, pcmcia_request_io(pdev, &link->io));
#endif
/* If we got this far, we're cool! */
break;
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(pdev, &tuple));
}
/* Let pcmcia know the device name */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->dev_node = &hw->node;
#else
link->dev = &hw->node;
#endif
/* Register the network device and get assigned a name */
SET_MODULE_OWNER(wlandev->netdev);
SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(pdev));
if (register_wlandev(wlandev) != 0) {
WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
goto failed;
}
strcpy(hw->node.dev_name, wlandev->name);
/* Allocate an interrupt line. Note that this does not assign a */
/* handler to the interrupt, unless the 'Handler' member of the */
/* irq structure is initialized. */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
if (pdev->conf.Attributes & CONF_ENABLE_IRQ) {
pdev->irq.IRQInfo1 = IRQ_LEVEL_ID;
pdev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
pdev->irq.Handler = hfa384x_interrupt;
pdev->irq.Instance = wlandev;
CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq));
}
#else
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.Handler = hfa384x_interrupt;
link->irq.Instance = wlandev;
CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &link->irq));
}
#endif
/* This actually configures the PCMCIA socket -- setting up */
/* the I/O windows and the interrupt mapping, and putting the */
/* card and host interface into "Memory and IO" mode. */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf));
#else
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &link->conf));
#endif
/* Fill the netdevice with this info */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
wlandev->netdev->irq = pdev->irq.AssignedIRQ;
wlandev->netdev->base_addr = pdev->io.BasePort1;
#else
wlandev->netdev->irq = link->irq.AssignedIRQ;
wlandev->netdev->base_addr = link->io.BasePort1;
#endif
/* And the rest of the hw structure */
hw->irq = wlandev->netdev->irq;
hw->iobase = wlandev->netdev->base_addr;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
link->state |= DEV_CONFIG;
link->state &= ~DEV_CONFIG_PENDING;
#endif
/* And now we're done! */
wlandev->msdstate = WLAN_MSD_HWPRESENT;
goto done;
cs_failed:
cs_error(pdev, last_fn, last_ret);
failed:
// wlandev, hw, etc etc..
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
pdev->priv = NULL;
#else
pdev->instance = NULL;
if (link) {
link->priv = NULL;
kfree(link);
}
#endif
if (wlandev) {
wlan_unsetup(wlandev);
if (wlandev->priv) {
hw = wlandev->priv;
wlandev->priv = NULL;
if (hw) {
hfa384x_destroy(hw);
kfree(hw);
}
}
kfree(wlandev);
}
done:
if (parse) kfree(parse);
DBFEXIT;
return rval;
}
#else // <= 2.6.15
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
#define CFG_CHECK(fn, retf) \
do { int ret = (retf); \
if (ret != 0) { \
WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
cs_error(link->handle, fn, ret); \
goto next_entry; \
} \
} while (0)
/*----------------------------------------------------------------
* prism2sta_attach
*
* Half of the attach/detach pair. Creates and registers a device
* instance with Card Services. In this case, it also creates the
* wlandev structure and device private structure. These are
* linked to the device instance via its priv member.
*
* Arguments:
* none
*
* Returns:
* A valid ptr to dev_link_t on success, NULL otherwise
*
* Side effects:
*
*
* Call context:
* process thread (insmod/init_module/register_pccard_driver)
----------------------------------------------------------------*/
dev_link_t *prism2sta_attach(void)
{
client_reg_t client_reg;
int result;
dev_link_t *link = NULL;
wlandevice_t *wlandev = NULL;
hfa384x_t *hw = NULL;
DBFENTER;
/* Alloc our structures */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link || ((wlandev = create_wlan()) == NULL)) {
WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
result = -EIO;
goto failed;
}
hw = wlandev->priv;
/* Clear all the structs */
memset(link, 0, sizeof(struct dev_link_t));
if ( wlan_setup(wlandev) != 0 ) {
WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
result = -EIO;
goto failed;
}
/* Initialize the hw struct for now */
hfa384x_create(hw, 0, 0, NULL);
hw->wlandev = wlandev;
/* Initialize the PC card device object. */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
init_timer(&link->release);
link->release.function = &prism2sta_release;
link->release.data = (u_long)link;
#endif
link->conf.IntType = INT_MEMORY_AND_IO;
link->priv = wlandev;
#if (defined(CS_RELEASE_CODE) && (CS_RELEASE_CODE < 0x2911))
link->irq.Instance = wlandev;
#endif
/* Link in to the list of devices managed by this driver */
link->next = dev_list;
dev_list = link;
/* Register with Card Services */
client_reg.dev_info = &dev_info;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) )
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_REQUEST |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.event_handler = &prism2sta_event;
#endif
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
result = pcmcia_register_client(&link->handle, &client_reg);
if (result != 0) {
cs_error(link->handle, RegisterClient, result);
prism2sta_detach(link);
return NULL;
}
goto done;
failed:
if (link) kfree(link);
if (wlandev) kfree(wlandev);
if (hw) kfree(hw);
link = NULL;
done:
DBFEXIT;
return link;
}
/*----------------------------------------------------------------
* prism2sta_detach
*
* Remove one of the device instances managed by this driver.
* Search the list for the given instance,
* check our flags for a waiting timer'd release call
* call release
* Deregister the instance with Card Services
* (netdevice) unregister the network device.
* unlink the instance from the list
* free the link, priv, and priv->priv memory
* Note: the dev_list variable is a driver scoped static used to
* maintain a list of device instances managed by this
* driver.
*
* Arguments:
* link ptr to the instance to detach
*
* Returns:
* nothing
*
* Side effects:
* the link structure is gone, the netdevice is gone
*
* Call context:
* Might be interrupt, don't block.
----------------------------------------------------------------*/
void prism2sta_detach(dev_link_t *link)
{
dev_link_t **linkp;
wlandevice_t *wlandev;
hfa384x_t *hw;
DBFENTER;
/* Locate prev device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
if (*linkp == link) break;
}
if (*linkp != NULL) {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
unsigned long flags;
/* Get rid of any timer'd release call */
save_flags(flags);
cli();
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
if (link->state & DEV_RELEASE_PENDING) {
del_timer_sync(&link->release);
link->state &= ~DEV_RELEASE_PENDING;
}
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
restore_flags(flags);
#endif
/* If link says we're still config'd, call release */
if (link->state & DEV_CONFIG) {
prism2sta_release((u_long)link);
if (link->state & DEV_STALE_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
}
/* Tell Card Services we're not around any more */
if (link->handle) {
pcmcia_deregister_client(link->handle);
}
/* Unlink device structure, free bits */
*linkp = link->next;
if ( link->priv != NULL ) {
wlandev = (wlandevice_t*)link->priv;
p80211netdev_hwremoved(wlandev);
if (link->dev != NULL) {
unregister_wlandev(wlandev);
}
wlan_unsetup(wlandev);
if (wlandev->priv) {
hw = wlandev->priv;
wlandev->priv = NULL;
if (hw) {
hfa384x_destroy(hw);
kfree(hw);
}
}
link->priv = NULL;
kfree(wlandev);
}
kfree(link);
}
DBFEXIT;
return;
}
/*----------------------------------------------------------------
* prism2sta_config
*
* Half of the config/release pair. Usually called in response to
* a card insertion event. At this point, we _know_ there's some
* physical device present. That means we can start poking around
* at the CIS and at any device specific config data we want.
*
* Note the gotos and the macros. I recoded this once without
* them, and it got incredibly ugly. It's actually simpler with
* them.
*
* Arguments:
* link the dev_link_t structure created in attach that
* represents this device instance.
*
* Returns:
* nothing
*
* Side effects:
* Resources (irq, io, mem) are allocated
* The pcmcia dev_link->node->name is set
* (For netcards) The device structure is finished and,
* most importantly, registered. This means that there
* is now a _named_ device that can be configured from
* userland.
*
* Call context:
* May be called from a timer. Don't block!
----------------------------------------------------------------*/
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
#define CFG_CHECK(fn, retf) \
do { int ret = (retf); \
if (ret != 0) { \
WLAN_LOG_DEBUG(1, "CardServices(" #fn ") returned %d\n", ret); \
cs_error(link->handle, fn, ret); \
goto next_entry; \
} \
} while (0)
void prism2sta_config(dev_link_t *link)
{
client_handle_t handle;
wlandevice_t *wlandev;
hfa384x_t *hw;
int last_fn;
int last_ret;
tuple_t tuple;
cisparse_t parse;
config_info_t socketconf;
UINT8 buf[64];
int minVcc = 0;
int maxVcc = 0;
cistpl_cftable_entry_t dflt = { 0 };
DBFENTER;
handle = link->handle;
wlandev = (wlandevice_t*)link->priv;
hw = wlandev->priv;
/* Collect the config register info */
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Configure card */
link->state |= DEV_CONFIG;
/* Acquire the current socket config (need Vcc setting) */
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &socketconf));
/* Loop through the config table entries until we find one that works */
/* Assumes a complete and valid CIS */
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
CFG_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
if (cfg->index == 0) goto next_entry;
link->conf.ConfigIndex = cfg->index;
/* Lets print out the Vcc that the controller+pcmcia-cs set
* for us, cause that's what we're going to use.
*/
WLAN_LOG_DEBUG(1,"Initial Vcc=%d/10v\n", socketconf.Vcc);
if (prism2_ignorevcc) {
link->conf.Vcc = socketconf.Vcc;
goto skipvcc;
}
/* Use power settings for Vcc and Vpp if present */
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
WLAN_LOG_DEBUG(1, "Vcc obtained from curtupl.VNOM\n");
minVcc = maxVcc =
cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
} else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
WLAN_LOG_DEBUG(1, "Vcc set from dflt.VNOM\n");
minVcc = maxVcc =
dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
} else if ((cfg->vcc.present & (1<<CISTPL_POWER_VMAX)) &&
(cfg->vcc.present & (1<<CISTPL_POWER_VMIN)) ) {
WLAN_LOG_DEBUG(1, "Vcc set from curtupl(VMIN,VMAX)\n"); minVcc = cfg->vcc.param[CISTPL_POWER_VMIN]/10000;
maxVcc = cfg->vcc.param[CISTPL_POWER_VMAX]/10000;
} else if ((dflt.vcc.present & (1<<CISTPL_POWER_VMAX)) &&
(dflt.vcc.present & (1<<CISTPL_POWER_VMIN)) ) {
WLAN_LOG_DEBUG(1, "Vcc set from dflt(VMIN,VMAX)\n");
minVcc = dflt.vcc.param[CISTPL_POWER_VMIN]/10000;
maxVcc = dflt.vcc.param[CISTPL_POWER_VMAX]/10000;
}
if ( socketconf.Vcc >= minVcc && socketconf.Vcc <= maxVcc) {
link->conf.Vcc = socketconf.Vcc;
} else {
/* [MSM]: Note that I've given up trying to change
* the Vcc if a change is indicated. It seems the
* system&socketcontroller&card vendors can't seem
* to get it right, so I'm tired of trying to hack
* my way around it. pcmcia-cs does its best using
* the voltage sense pins but sometimes the controller
* lies. Then, even if we have a good read on the VS
* pins, some system designs will silently ignore our
* requests to set the voltage. Additionally, some
* vendors have 3.3v indicated on their sense pins,
* but 5v specified in the CIS or vice-versa. I've
* had it. My only recommendation is "let the buyer
* beware". Your system might supply 5v to a 3v card
* (possibly causing damage) or a 3v capable system
* might supply 5v to a 3v capable card (wasting
* precious battery life).
* My only recommendation (if you care) is to get
* yourself an extender card (I don't know where, I
* have only one myself) and a meter and test it for
* yourself.
*/
goto next_entry;
}
skipvcc:
WLAN_LOG_DEBUG(1, "link->conf.Vcc=%d\n", link->conf.Vcc);
/* Do we need to allocate an interrupt? */
/* HACK: due to a bad CIS....we ALWAYS need an interrupt */
/* if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) */
link->conf.Attributes |= CONF_ENABLE_IRQ;
/* IO window settings */
link->io.NumPorts1 = link->io.NumPorts2 = 0;
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT))
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.BasePort1 = io->win[0].base;
if ( link->io.BasePort1 != 0 ) {
WLAN_LOG_WARNING(
"Brain damaged CIS: hard coded iobase="
"0x%x, try letting pcmcia_cs decide...\n",
link->io.BasePort1 );
link->io.BasePort1 = 0;
}
link->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
link->io.Attributes2 = link->io.Attributes1;
link->io.BasePort2 = io->win[1].base;
link->io.NumPorts2 = io->win[1].len;
}
}
/* This reserves IO space but doesn't actually enable it */
CFG_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
/* If we got this far, we're cool! */
break;
next_entry:
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
dflt = *cfg;
CS_CHECK(GetNextTuple,
pcmcia_get_next_tuple(handle, &tuple));
}
/* Allocate an interrupt line. Note that this does not assign a */
/* handler to the interrupt, unless the 'Handler' member of the */
/* irq structure is initialized. */
if (link->conf.Attributes & CONF_ENABLE_IRQ)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) )
int i;
link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
if (irq_list[0] == -1)
link->irq.IRQInfo2 = irq_mask;
else
for (i=0; i<4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
#else
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
#endif
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.Handler = hfa384x_interrupt;
link->irq.Instance = wlandev;
CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
}
/* This actually configures the PCMCIA socket -- setting up */
/* the I/O windows and the interrupt mapping, and putting the */
/* card and host interface into "Memory and IO" mode. */
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
/* Fill the netdevice with this info */
wlandev->netdev->irq = link->irq.AssignedIRQ;
wlandev->netdev->base_addr = link->io.BasePort1;
/* Report what we've done */
WLAN_LOG_INFO("%s: index 0x%02x: Vcc %d.%d",
dev_info, link->conf.ConfigIndex,
link->conf.Vcc/10, link->conf.Vcc%10);
if (link->conf.Vpp1)
printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
if (link->conf.Attributes & CONF_ENABLE_IRQ)
printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1);
if (link->io.NumPorts2)
printk(" & 0x%04x-0x%04x", link->io.BasePort2, link->io.BasePort2+link->io.NumPorts2-1);
printk("\n");
link->state &= ~DEV_CONFIG_PENDING;
/* Let pcmcia know the device name */
link->dev = &hw->node;
/* Register the network device and get assigned a name */
SET_MODULE_OWNER(wlandev->netdev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) )
SET_NETDEV_DEV(wlandev->netdev, &handle_to_dev(link->handle));
#endif
if (register_wlandev(wlandev) != 0) {
WLAN_LOG_NOTICE("prism2sta_cs: register_wlandev() failed.\n");
goto failed;
}
strcpy(hw->node.dev_name, wlandev->name);
/* Any device custom config/query stuff should be done here */
/* For a netdevice, we should at least grab the mac address */
return;
cs_failed:
cs_error(link->handle, last_fn, last_ret);
WLAN_LOG_ERROR("NextTuple failure? It's probably a Vcc mismatch.\n");
failed:
prism2sta_release((u_long)link);
return;
}
/*----------------------------------------------------------------
* prism2sta_release
*
* Half of the config/release pair. Usually called in response to
* a card ejection event. Checks to make sure no higher layers
* are still (or think they are) using the card via the link->open
* field.
*
* NOTE: Don't forget to increment the link->open variable in the
* device_open method, and decrement it in the device_close
* method.
*
* Arguments:
* arg a generic 32 bit variable. It's the value that
* we assigned to link->release.data in sta_attach().
*
* Returns:
* nothing
*
* Side effects:
* All resources should be released after this function
* executes and finds the device !open.
*
* Call context:
* Possibly in a timer context. Don't do anything that'll
* block.
----------------------------------------------------------------*/
void prism2sta_release(u_long arg)
{
dev_link_t *link = (dev_link_t *)arg;
DBFENTER;
/* First thing we should do is get the MSD back to the
* HWPRESENT state. I.e. everything quiescent.
*/
prism2sta_ifstate(link->priv, P80211ENUM_ifstate_disable);
if (link->open) {
/* TODO: I don't think we're even using this bit of code
* and I don't think it's hurting us at the moment.
*/
WLAN_LOG_DEBUG(1,
"prism2sta_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
pcmcia_release_configuration(link->handle);
pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
DBFEXIT;
}
/*----------------------------------------------------------------
* prism2sta_event
*
* Handler for card services events.
*
* Arguments:
* event The event code
* priority hi/low - REMOVAL is the only hi
* args ptr to card services struct containing info about
* pcmcia status
*
* Returns:
* Zero on success, non-zero otherwise
*
* Side effects:
*
*
* Call context:
* Both interrupt and process thread, depends on the event.
----------------------------------------------------------------*/
static int
prism2sta_event (
event_t event,
int priority,
event_callback_args_t *args)
{
int result = 0;
dev_link_t *link = (dev_link_t *) args->client_data;
wlandevice_t *wlandev = (wlandevice_t*)link->priv;
hfa384x_t *hw = NULL;
DBFENTER;
if (wlandev) hw = wlandev->priv;
switch (event)
{
case CS_EVENT_CARD_INSERTION:
WLAN_LOG_DEBUG(5,"event is INSERTION\n");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
prism2sta_config(link);
if (!(link->state & DEV_CONFIG)) {
wlandev->netdev->irq = 0;
WLAN_LOG_ERROR(
"%s: Initialization failed!\n", dev_info);
wlandev->msdstate = WLAN_MSD_HWFAIL;
break;
}
/* Fill in the rest of the hw struct */
hw->irq = wlandev->netdev->irq;
hw->iobase = wlandev->netdev->base_addr;
hw->link = link;
if (prism2_doreset) {
result = hfa384x_corereset(hw,
prism2_reset_holdtime,
prism2_reset_settletime, 0);
if ( result ) {
WLAN_LOG_ERROR(
"corereset() failed, result=%d.\n",
result);
wlandev->msdstate = WLAN_MSD_HWFAIL;
break;
}
}
#if 0
/*
* TODO: test_hostif() not implemented yet.
*/
result = hfa384x_test_hostif(hw);
if (result) {
WLAN_LOG_ERROR(
"test_hostif() failed, result=%d.\n", result);
wlandev->msdstate = WLAN_MSD_HWFAIL;
break;
}
#endif
wlandev->msdstate = WLAN_MSD_HWPRESENT;
break;
case CS_EVENT_CARD_REMOVAL:
WLAN_LOG_DEBUG(5,"event is REMOVAL\n");
link->state &= ~DEV_PRESENT;
if (wlandev) {
p80211netdev_hwremoved(wlandev);
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
if (link->state & DEV_CONFIG)
{
link->release.expires = jiffies + (HZ/20);
add_timer(&link->release);
}
#endif
break;
case CS_EVENT_RESET_REQUEST:
WLAN_LOG_DEBUG(5,"event is RESET_REQUEST\n");
WLAN_LOG_NOTICE(
"prism2 card reset not supported "
"due to post-reset user mode configuration "
"requirements.\n");
WLAN_LOG_NOTICE(
" From user mode, use "
"'cardctl suspend;cardctl resume' "
"instead.\n");
break;
case CS_EVENT_RESET_PHYSICAL:
case CS_EVENT_CARD_RESET:
WLAN_LOG_WARNING("Rx'd CS_EVENT_RESET_xxx, should not "
"be possible since RESET_REQUEST was denied.\n");
break;
case CS_EVENT_PM_SUSPEND:
WLAN_LOG_DEBUG(5,"event is SUSPEND\n");
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
{
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_PM_RESUME:
WLAN_LOG_DEBUG(5,"event is RESUME\n");
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
}
break;
}
DBFEXIT;
return 0; /* noone else does anthing with the return value */
}
#endif // <= 2.6.15
int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
{
int result = 0;
conf_reg_t reg;
UINT8 corsave;
DBFENTER;
WLAN_LOG_DEBUG(3, "Doing reset via CardServices().\n");
/* Collect COR */
reg.Function = 0;
reg.Action = CS_READ;
reg.Offset = CISREG_COR;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
result = pcmcia_access_configuration_register(hw->pdev, &reg);
#else
result = pcmcia_access_configuration_register(
hw->link->handle,
&reg);
#endif
if (result != CS_SUCCESS ) {
WLAN_LOG_ERROR(
":0: AccessConfigurationRegister(CS_READ) failed,"
"result=%d.\n", result);
result = -EIO;
}
corsave = reg.Value;
/* Write reset bit (BIT7) */
reg.Value |= BIT7;
reg.Action = CS_WRITE;
reg.Offset = CISREG_COR;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
result = pcmcia_access_configuration_register(hw->pdev, &reg);
#else
result = pcmcia_access_configuration_register(
hw->link->handle,
&reg);
#endif
if (result != CS_SUCCESS ) {
WLAN_LOG_ERROR(
":1: AccessConfigurationRegister(CS_WRITE) failed,"
"result=%d.\n", result);
result = -EIO;
}
/* Hold for holdtime */
mdelay(holdtime);
if (genesis) {
reg.Value = genesis;
reg.Action = CS_WRITE;
reg.Offset = CISREG_CCSR;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
result = pcmcia_access_configuration_register(hw->pdev, &reg);
#else
result = pcmcia_access_configuration_register(
hw->link->handle,
&reg);
#endif
if (result != CS_SUCCESS ) {
WLAN_LOG_ERROR(
":1: AccessConfigurationRegister(CS_WRITE) failed,"
"result=%d.\n", result);
result = -EIO;
}
}
/* Hold for holdtime */
mdelay(holdtime);
/* Clear reset bit */
reg.Value &= ~BIT7;
reg.Action = CS_WRITE;
reg.Offset = CISREG_COR;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
result = pcmcia_access_configuration_register(hw->pdev, &reg);
#else
result = pcmcia_access_configuration_register(
hw->link->handle,
&reg);
#endif
if (result != CS_SUCCESS ) {
WLAN_LOG_ERROR(
":2: AccessConfigurationRegister(CS_WRITE) failed,"
"result=%d.\n", result);
result = -EIO;
goto done;
}
/* Wait for settletime */
mdelay(settletime);
/* Set non-reset bits back what they were */
reg.Value = corsave;
reg.Action = CS_WRITE;
reg.Offset = CISREG_COR;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16)
result = pcmcia_access_configuration_register(hw->pdev, &reg);
#else
result = pcmcia_access_configuration_register(
hw->link->handle,
&reg);
#endif
if (result != CS_SUCCESS ) {
WLAN_LOG_ERROR(
":2: AccessConfigurationRegister(CS_WRITE) failed,"
"result=%d.\n", result);
result = -EIO;
goto done;
}
done:
DBFEXIT;
return result;
}
#ifdef MODULE
static int __init prism2cs_init(void)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
servinfo_t serv;
#endif
DBFENTER;
WLAN_LOG_NOTICE("%s Loaded\n", version);
WLAN_LOG_NOTICE("dev_info is: %s\n", dev_info);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
pcmcia_get_card_services_info(&serv);
if ( serv.Revision != CS_RELEASE_CODE )
{
printk(KERN_NOTICE"%s: CardServices release does not match!\n", dev_info);
return -1;
}
/* This call will result in a call to prism2sta_attach */
/* and eventually prism2sta_detach */
register_pccard_driver( &dev_info, &prism2sta_attach, &prism2sta_detach);
#else
pcmcia_register_driver(&prism2_cs_driver);
#endif
DBFEXIT;
return 0;
}
static void __exit prism2cs_cleanup(void)
{
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
dev_link_t *link = dev_list;
dev_link_t *nlink;
DBFENTER;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) )
for (link=dev_list; link != NULL; link = nlink) {
nlink = link->next;
if ( link->state & DEV_CONFIG ) {
prism2sta_release((u_long)link);
}
prism2sta_detach(link); /* remember detach() frees link */
}
#endif
unregister_pccard_driver( &dev_info);
#else
pcmcia_unregister_driver(&prism2_cs_driver);
#endif
printk(KERN_NOTICE "%s Unloaded\n", version);
DBFEXIT;
return;
}
module_init(prism2cs_init);
module_exit(prism2cs_cleanup);
#endif // MODULE
#define WLAN_HOSTIF WLAN_PCI
#include "hfa384x.c"
#include "prism2mgmt.c"
#include "prism2mib.c"
#include "prism2sta.c"
#define PCI_SIZE 0x1000 /* Memory size - 4K bytes */
/* ISL3874A 11Mb/s WLAN controller */
#define PCIVENDOR_INTERSIL 0x1260UL
#define PCIDEVICE_ISL3874 0x3873UL /* [MSM] yeah I know...the ID says
3873. Trust me, it's a 3874. */
/* Samsung SWL-2210P 11Mb/s WLAN controller (uses ISL3874A) */
#define PCIVENDOR_SAMSUNG 0x167dUL
#define PCIDEVICE_SWL_2210P 0xa000UL
#define PCIVENDOR_NETGEAR 0x1385UL /* for MA311 */
/* PCI Class & Sub-Class code, Network-'Other controller' */
#define PCI_CLASS_NETWORK_OTHERS 0x280
/*----------------------------------------------------------------
* prism2sta_probe_pci
*
* Probe routine called when a PCI device w/ matching ID is found.
* The ISL3874 implementation uses the following map:
* BAR0: Prism2.x registers memory mapped, size=4k
* Here's the sequence:
* - Allocate the PCI resources.
* - Read the PCMCIA attribute memory to make sure we have a WLAN card
* - Reset the MAC
* - Initialize the netdev and wlan data
* - Initialize the MAC
*
* Arguments:
* pdev ptr to pci device structure containing info about
* pci configuration.
* id ptr to the device id entry that matched this device.
*
* Returns:
* zero - success
* negative - failed
*
* Side effects:
*
*
* Call context:
* process thread
*
----------------------------------------------------------------*/
static int __devinit
prism2sta_probe_pci(
struct pci_dev *pdev,
const struct pci_device_id *id)
{
int result;
phys_t phymem = 0;
void __iomem *mem = NULL;
wlandevice_t *wlandev = NULL;
hfa384x_t *hw = NULL;
DBFENTER;
/* Enable the pci device */
if (pci_enable_device(pdev)) {
WLAN_LOG_ERROR("%s: pci_enable_device() failed.\n", dev_info);
result = -EIO;
goto fail;
}
/* Figure out our resources */
phymem = pci_resource_start(pdev, 0);
if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) {
printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n");
result = -EIO;
goto fail;
}
mem = ioremap(phymem, PCI_SIZE);
if ( mem == 0 ) {
WLAN_LOG_ERROR("%s: ioremap() failed.\n", dev_info);
result = -EIO;
goto fail;
}
/* Log the device */
WLAN_LOG_INFO("A Prism2.5 PCI device found, "
"phymem:0x%llx, irq:%d, mem:0x%p\n",
(unsigned long long)phymem, pdev->irq, mem);
if ((wlandev = create_wlan()) == NULL) {
WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
result = -EIO;
goto fail;
}
hw = wlandev->priv;
if ( wlan_setup(wlandev) != 0 ) {
WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
result = -EIO;
goto fail;
}
/* Setup netdevice's ability to report resources
* Note: the netdevice was allocated by wlan_setup()
*/
wlandev->netdev->irq = pdev->irq;
wlandev->netdev->mem_start = (unsigned long) mem;
wlandev->netdev->mem_end = wlandev->netdev->mem_start +
pci_resource_len(pdev, 0);
/* Initialize the hw data */
hfa384x_create(hw, wlandev->netdev->irq, 0, mem);
hw->wlandev = wlandev;
/* Register the wlandev, this gets us a name and registers the
* linux netdevice.
*/
SET_MODULE_OWNER(wlandev->netdev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev));
#endif
if ( register_wlandev(wlandev) != 0 ) {
WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info);
result = -EIO;
goto fail;
}
#if 0
/* TODO: Move this and an irq test into an hfa384x_testif() routine.
*/
outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
if ( reg != PRISM2STA_MAGIC ) {
WLAN_LOG_ERROR("MAC register access test failed!\n");
result = -EIO;
goto fail;
}
#endif
/* Do a chip-level reset on the MAC */
if (prism2_doreset) {
result = hfa384x_corereset(hw,
prism2_reset_holdtime,
prism2_reset_settletime, 0);
if (result != 0) {
WLAN_LOG_ERROR(
"%s: hfa384x_corereset() failed.\n",
dev_info);
unregister_wlandev(wlandev);
hfa384x_destroy(hw);
result = -EIO;
goto fail;
}
}
pci_set_drvdata(pdev, wlandev);
/* Shouldn't actually hook up the IRQ until we
* _know_ things are alright. A test routine would help.
*/
request_irq(wlandev->netdev->irq, hfa384x_interrupt,
SA_SHIRQ, wlandev->name, wlandev);
wlandev->msdstate = WLAN_MSD_HWPRESENT;
result = 0;
goto done;
fail:
pci_set_drvdata(pdev, NULL);
if (wlandev) kfree(wlandev);
if (hw) kfree(hw);
if (mem) iounmap(mem);
pci_release_regions(pdev);
pci_disable_device(pdev);
done:
DBFEXIT;
return result;
}
static void __devexit prism2sta_remove_pci(struct pci_dev *pdev)
{
wlandevice_t *wlandev;
hfa384x_t *hw;
wlandev = (wlandevice_t *) pci_get_drvdata(pdev);
hw = wlandev->priv;
p80211netdev_hwremoved(wlandev);
/* reset hardware */
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
if (pdev->irq)
free_irq(pdev->irq, wlandev);
unregister_wlandev(wlandev);
/* free local stuff */
if (hw) {
hfa384x_destroy(hw);
kfree(hw);
}
iounmap((void __iomem *)wlandev->netdev->mem_start);
wlan_unsetup(wlandev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
kfree(wlandev);
}
static struct pci_device_id pci_id_tbl[] = {
{
PCIVENDOR_INTERSIL, PCIDEVICE_ISL3874,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller"
},
{
PCIVENDOR_INTERSIL, 0x3872,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Intersil Prism2.5 ISL3872 11Mb/s WLAN Controller"
},
{
PCIVENDOR_SAMSUNG, PCIDEVICE_SWL_2210P,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Samsung MagicLAN SWL-2210P 11Mb/s WLAN Controller"
},
{ /* for NetGear MA311 */
PCIVENDOR_NETGEAR, 0x3872,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Netgear MA311 WLAN Controller"
},
{
0, 0, 0, 0, 0, 0, 0
}
};
MODULE_DEVICE_TABLE(pci, pci_id_tbl);
/* Function declared here because of ptr reference below */
static int __devinit prism2sta_probe_pci(struct pci_dev *pdev,
const struct pci_device_id *id);
static void __devexit prism2sta_remove_pci(struct pci_dev *pdev);
static struct pci_driver prism2_pci_drv_id = {
.name = "prism2_pci",
.id_table = pci_id_tbl,
.probe = prism2sta_probe_pci,
.remove = prism2sta_remove_pci,
#ifdef CONFIG_PM
.suspend = prism2sta_suspend_pci,
.resume = prism2sta_resume_pci,
#endif
};
#ifdef MODULE
static int __init prism2pci_init(void)
{
WLAN_LOG_NOTICE("%s Loaded\n", version);
return pci_module_init(&prism2_pci_drv_id);
};
static void __exit prism2pci_cleanup(void)
{
pci_unregister_driver(&prism2_pci_drv_id);
};
module_init(prism2pci_init);
module_exit(prism2pci_cleanup);
#endif
int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
{
int result = 0;
unsigned long timeout;
UINT16 reg;
DBFENTER;
/* Assert reset and wait awhile
* (note: these delays are _really_ long, but they appear to be
* necessary.)
*/
hfa384x_setreg(hw, 0xc5, HFA384x_PCICOR);
timeout = jiffies + HZ/4;
while(time_before(jiffies, timeout)) udelay(5);
if (genesis) {
hfa384x_setreg(hw, genesis, HFA384x_PCIHCR);
timeout = jiffies + HZ/4;
while(time_before(jiffies, timeout)) udelay(5);
}
/* Clear the reset and wait some more
*/
hfa384x_setreg(hw, 0x45, HFA384x_PCICOR);
timeout = jiffies + HZ/2;
while(time_before(jiffies, timeout)) udelay(5);
/* Wait for f/w to complete initialization (CMD:BUSY == 0)
*/
timeout = jiffies + 2*HZ;
reg = hfa384x_getreg(hw, HFA384x_CMD);
while ( HFA384x_CMD_ISBUSY(reg) && time_before( jiffies, timeout) ) {
reg = hfa384x_getreg(hw, HFA384x_CMD);
udelay(10);
}
if (HFA384x_CMD_ISBUSY(reg)) {
WLAN_LOG_WARNING("corereset: Timed out waiting for cmd register.\n");
result=1;
}
DBFEXIT;
return result;
}
#define WLAN_HOSTIF WLAN_PLX
#include "hfa384x.c"
#include "prism2mgmt.c"
#include "prism2mib.c"
#include "prism2sta.c"
#define PLX_ATTR_SIZE 0x1000 /* Attribute memory size - 4K bytes */
#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */
#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */
#define PLX_INTCSR 0x4c /* Interrupt Control and Status Register */
#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */
/* 3Com 3CRW777A (PLX) board ID */
#define PCIVENDOR_3COM 0x10B7
#define PCIDEVICE_AIRCONNECT 0x7770
/* Eumitcom PCI WL11000 PCI Adapter (PLX) board device+vendor ID */
#define PCIVENDOR_EUMITCOM 0x1638UL
#define PCIDEVICE_WL11000 0x1100UL
/* Global Sun Tech GL24110P PCI Adapter (PLX) board device+vendor ID */
#define PCIVENDOR_GLOBALSUN 0x16abUL
#define PCIDEVICE_GL24110P 0x1101UL
#define PCIDEVICE_GL24110P_ALT 0x1102UL
/* Netgear MA301 PCI Adapter (PLX) board device+vendor ID */
#define PCIVENDOR_NETGEAR 0x1385UL
#define PCIDEVICE_MA301 0x4100UL
/* US Robotics USR2410 PCI Adapter (PLX) board device+vendor ID */
#define PCIVENDOR_USROBOTICS 0x16ecUL
#define PCIDEVICE_USR2410 0x3685UL
/* Linksys WPC11 card with the WDT11 adapter (PLX) board device+vendor ID */
#define PCIVENDOR_Linksys 0x16abUL
#define PCIDEVICE_Wpc11Wdt11 0x1102UL
/* National Datacomm Corp SOHOware Netblaster II PCI */
#define PCIVENDOR_NDC 0x15e8UL
#define PCIDEVICE_NCP130_PLX 0x0130UL
#define PCIDEVICE_NCP130_ASIC 0x0131UL
/* NDC NCP130_PLX is also sold by Corega. Their name is CGWLPCIA11 */
#define PCIVENDOR_COREGA PCIVENDOR_NDC
#define PCIDEVICE_CGWLPCIA11 PCIDEVICE_NCP130_PLX
/* PCI Class & Sub-Class code, Network-'Other controller' */
#define PCI_CLASS_NETWORK_OTHERS 0x280
/*----------------------------------------------------------------
* prism2sta_probe_plx
*
* Probe routine called when a PCI device w/ matching ID is found.
* This PLX implementation uses the following map:
* BAR0: Unused
* BAR1: ????
* BAR2: PCMCIA attribute memory
* BAR3: PCMCIA i/o space
* Here's the sequence:
* - Allocate the PCI resources.
* - Read the PCMCIA attribute memory to make sure we have a WLAN card
* - Reset the MAC using the PCMCIA COR
* - Initialize the netdev and wlan data
* - Initialize the MAC
*
* Arguments:
* pdev ptr to pci device structure containing info about
* pci configuration.
* id ptr to the device id entry that matched this device.
*
* Returns:
* zero - success
* negative - failed
*
* Side effects:
*
*
* Call context:
* process thread
*
----------------------------------------------------------------*/
static int __devinit
prism2sta_probe_plx(
struct pci_dev *pdev,
const struct pci_device_id *id)
{
int result;
phys_t pccard_ioaddr;
phys_t pccard_attr_mem;
unsigned int pccard_attr_len;
void __iomem *attr_mem = NULL;
UINT32 plx_addr;
wlandevice_t *wlandev = NULL;
hfa384x_t *hw = NULL;
int reg;
u32 regic;
if (pci_enable_device(pdev))
return -EIO;
/* TMC7160 boards are special */
if ((pdev->vendor == PCIVENDOR_NDC) &&
(pdev->device == PCIDEVICE_NCP130_ASIC)) {
unsigned long delay;
pccard_attr_mem = 0;
pccard_ioaddr = pci_resource_start(pdev, 1);
outb(0x45, pccard_ioaddr);
delay = jiffies + 1*HZ;
while (time_before(jiffies, delay));
if (inb(pccard_ioaddr) != 0x45) {
WLAN_LOG_ERROR("Initialize the TMC7160 failed. (0x%x)\n", inb(pccard_ioaddr));
return -EIO;
}
pccard_ioaddr = pci_resource_start(pdev, 2);
prism2_doreset = 0;
WLAN_LOG_INFO("NDC NCP130 with TMC716(ASIC) PCI interface device found at io:0x%x, irq:%d\n", pccard_ioaddr, pdev->irq);
goto init;
}
/* Collect the resource requirements */
pccard_attr_mem = pci_resource_start(pdev, 2);
pccard_attr_len = pci_resource_len(pdev, 2);
if (pccard_attr_len < PLX_MIN_ATTR_LEN)
return -EIO;
pccard_ioaddr = pci_resource_start(pdev, 3);
/* bjoern: We need to tell the card to enable interrupts, in
* case the serial eprom didn't do this already. See the
* PLX9052 data book, p8-1 and 8-24 for reference.
* [MSM]: This bit of code came from the orinoco_cs driver.
*/
plx_addr = pci_resource_start(pdev, 1);
regic = 0;
regic = inl(plx_addr+PLX_INTCSR);
if(regic & PLX_INTCSR_INTEN) {
WLAN_LOG_DEBUG(1,
"%s: Local Interrupt already enabled\n", dev_info);
} else {
regic |= PLX_INTCSR_INTEN;
outl(regic, plx_addr+PLX_INTCSR);
regic = inl(plx_addr+PLX_INTCSR);
if(!(regic & PLX_INTCSR_INTEN)) {
WLAN_LOG_ERROR(
"%s: Couldn't enable Local Interrupts\n",
dev_info);
return -EIO;
}
}
/* These assignments are here in case of future mappings for
* io space and irq that might be similar to ioremap
*/
if (!request_mem_region(pccard_attr_mem, pci_resource_len(pdev, 2), "Prism2")) {
WLAN_LOG_ERROR("%s: Couldn't reserve PCI memory region\n", dev_info);
return -EIO;
}
attr_mem = ioremap(pccard_attr_mem, pccard_attr_len);
WLAN_LOG_INFO("A PLX PCI/PCMCIA interface device found, "
"phymem:0x%llx, phyio=0x%x, irq:%d, "
"mem: 0x%lx\n",
(unsigned long long)pccard_attr_mem, pccard_ioaddr, pdev->irq,
(unsigned long)attr_mem);
/* Verify whether PC card is present.
* [MSM] This needs improvement, the right thing to do is
* probably to walk the CIS looking for the vendor and product
* IDs. It would be nice if this could be tied in with the
* etc/pcmcia/wlan-ng.conf file. Any volunteers? ;-)
*/
if (
readb(attr_mem + 0) != 0x01 || readb(attr_mem + 2) != 0x03 ||
readb(attr_mem + 4) != 0x00 || readb(attr_mem + 6) != 0x00 ||
readb(attr_mem + 8) != 0xFF || readb(attr_mem + 10) != 0x17 ||
readb(attr_mem + 12) != 0x04 || readb(attr_mem + 14) != 0x67) {
WLAN_LOG_ERROR("Prism2 PC card CIS is invalid.\n");
return -EIO;
}
WLAN_LOG_INFO("A PCMCIA WLAN adapter was found.\n");
/* Write COR to enable PC card */
writeb(COR_VALUE, attr_mem + COR_OFFSET);
reg = readb(attr_mem + COR_OFFSET);
init:
/*
* Now do everything the same as a PCI device
* [MSM] TODO: We could probably factor this out of pcmcia/pci/plx
* and perhaps usb. Perhaps a task for another day.......
*/
if ((wlandev = create_wlan()) == NULL) {
WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
result = -EIO;
goto failed;
}
hw = wlandev->priv;
if ( wlan_setup(wlandev) != 0 ) {
WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info);
result = -EIO;
goto failed;
}
/* Setup netdevice's ability to report resources
* Note: the netdevice was allocated by wlan_setup()
*/
wlandev->netdev->irq = pdev->irq;
wlandev->netdev->base_addr = pccard_ioaddr;
wlandev->netdev->mem_start = (unsigned long)attr_mem;
wlandev->netdev->mem_end = (unsigned long)attr_mem + pci_resource_len(pdev, 0);
/* Initialize the hw data */
hfa384x_create(hw, wlandev->netdev->irq, pccard_ioaddr, attr_mem);
hw->wlandev = wlandev;
/* Register the wlandev, this gets us a name and registers the
* linux netdevice.
*/
SET_MODULE_OWNER(wlandev->netdev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
SET_NETDEV_DEV(wlandev->netdev, &(pdev->dev));
#endif
if ( register_wlandev(wlandev) != 0 ) {
WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info);
result = -EIO;
goto failed;
}
#if 0
/* TODO: Move this and an irq test into an hfa384x_testif() routine.
*/
outw(PRISM2STA_MAGIC, HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
reg=inw( HFA384x_SWSUPPORT(wlandev->netdev->base_addr));
if ( reg != PRISM2STA_MAGIC ) {
WLAN_LOG_ERROR("MAC register access test failed!\n");
result = -EIO;
goto failed;
}
#endif
/* Do a chip-level reset on the MAC */
if (prism2_doreset) {
result = hfa384x_corereset(hw,
prism2_reset_holdtime,
prism2_reset_settletime, 0);
if (result != 0) {
unregister_wlandev(wlandev);
hfa384x_destroy(hw);
WLAN_LOG_ERROR(
"%s: hfa384x_corereset() failed.\n",
dev_info);
result = -EIO;
goto failed;
}
}
pci_set_drvdata(pdev, wlandev);
/* Shouldn't actually hook up the IRQ until we
* _know_ things are alright. A test routine would help.
*/
request_irq(wlandev->netdev->irq, hfa384x_interrupt,
SA_SHIRQ, wlandev->name, wlandev);
wlandev->msdstate = WLAN_MSD_HWPRESENT;
result = 0;
goto done;
failed:
pci_set_drvdata(pdev, NULL);
if (wlandev) kfree(wlandev);
if (hw) kfree(hw);
if (attr_mem) iounmap(attr_mem);
pci_release_regions(pdev);
pci_disable_device(pdev);
done:
DBFEXIT;
return result;
}
static void __devexit prism2sta_remove_plx(struct pci_dev *pdev)
{
wlandevice_t *wlandev;
hfa384x_t *hw;
wlandev = (wlandevice_t *) pci_get_drvdata(pdev);
hw = wlandev->priv;
p80211netdev_hwremoved(wlandev);
/* reset hardware */
prism2sta_ifstate(wlandev, P80211ENUM_ifstate_disable);
if (pdev->irq)
free_irq(pdev->irq, wlandev);
unregister_wlandev(wlandev);
/* free local stuff */
if (hw) {
hfa384x_destroy(hw);
kfree(hw);
}
iounmap((void __iomem *)wlandev->netdev->mem_start);
wlan_unsetup(wlandev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
kfree(wlandev);
}
static struct pci_device_id plx_id_tbl[] = {
{
PCIVENDOR_EUMITCOM, PCIDEVICE_WL11000,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Eumitcom WL11000 PCI(PLX) card"
},
{
PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"
},
{
PCIVENDOR_GLOBALSUN, PCIDEVICE_GL24110P_ALT,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"
},
{
PCIVENDOR_NETGEAR, PCIDEVICE_MA301,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Global Sun Tech GL24110P PCI(PLX) card"
},
{
PCIVENDOR_USROBOTICS, PCIDEVICE_USR2410,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"US Robotics USR2410 PCI(PLX) card"
},
{
PCIVENDOR_Linksys, PCIDEVICE_Wpc11Wdt11,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"Linksys WPC11 with WDT11 PCI(PLX) adapter"
},
{
PCIVENDOR_NDC, PCIDEVICE_NCP130_PLX,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"NDC Netblaster II PCI(PLX)"
},
{
PCIVENDOR_NDC, PCIDEVICE_NCP130_ASIC,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"NDC Netblaster II PCI(TMC7160)"
},
{
PCIVENDOR_3COM, PCIDEVICE_AIRCONNECT,
PCI_ANY_ID, PCI_ANY_ID,
0, 0,
/* Driver data, we just put the name here */
(unsigned long)"3Com AirConnect PCI 802.11b 11Mb/s WLAN Controller"
},
{
0, 0, 0, 0, 0, 0, 0
}
};
MODULE_DEVICE_TABLE(pci, plx_id_tbl);
/* Function declared here because of ptr reference below */
static int __devinit prism2sta_probe_plx(struct pci_dev *pdev,
const struct pci_device_id *);
static void __devexit prism2sta_remove_plx(struct pci_dev *pdev);
static struct pci_driver prism2_plx_drv_id = {
.name = "prism2_plx",
.id_table = plx_id_tbl,
.probe = prism2sta_probe_plx,
.remove = prism2sta_remove_plx,
#ifdef CONFIG_PM
.suspend = prism2sta_suspend_pci,
.resume = prism2sta_resume_pci,
#endif
};
#ifdef MODULE
static int __init prism2plx_init(void)
{
WLAN_LOG_NOTICE("%s Loaded\n", version);
return pci_module_init(&prism2_plx_drv_id);
};
static void __exit prism2plx_cleanup(void)
{
pci_unregister_driver(&prism2_plx_drv_id);
};
module_init(prism2plx_init);
module_exit(prism2plx_cleanup);
#endif // MODULE
int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
{
int result = 0;
#define COR_OFFSET 0x3e0 /* COR attribute offset of Prism2 PC card */
#define COR_VALUE 0x41 /* Enable PC card with irq in level trigger */
#define HCR_OFFSET 0x3e2 /* HCR attribute offset of Prism2 PC card */
UINT8 corsave;
DBFENTER;
WLAN_LOG_DEBUG(3, "Doing reset via direct COR access.\n");
/* Collect COR */
corsave = readb(hw->membase + COR_OFFSET);
/* Write reset bit (BIT7) */
writeb(corsave | BIT7, hw->membase + COR_OFFSET);
/* Hold for holdtime */
mdelay(holdtime);
if (genesis) {
writeb(genesis, hw->membase + HCR_OFFSET);
/* Hold for holdtime */
mdelay(holdtime);
}
/* Clear reset bit */
writeb(corsave & ~BIT7, hw->membase + COR_OFFSET);
/* Wait for settletime */
mdelay(settletime);
/* Set non-reset bits back what they were */
writeb(corsave, hw->membase + COR_OFFSET);
DBFEXIT;
return result;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment