struct if_cs_card {
struct pcmcia_device *p_dev;
- wlan_private *priv;
+ struct lbs_private *priv;
void __iomem *iobase;
};
{
int i;
- for (i = 0; i < 500; i++) {
+ for (i = 0; i < 1000; i++) {
u8 val = if_cs_read8(card, addr);
if (val == reg)
return i;
- udelay(100);
+ udelay(500);
}
return -ETIME;
}
#define IF_CS_H_IC_TX_OVER 0x0001
#define IF_CS_H_IC_RX_OVER 0x0002
#define IF_CS_H_IC_DNLD_OVER 0x0004
-#define IF_CS_H_IC_HOST_EVENT 0x0008
+#define IF_CS_H_IC_POWER_DOWN 0x0008
+#define IF_CS_H_IC_HOST_EVENT 0x0010
#define IF_CS_H_IC_MASK 0x001f
#define IF_CS_H_INT_MASK 0x00000004
static irqreturn_t if_cs_interrupt(int irq, void *data)
{
- struct if_cs_card *card = (struct if_cs_card *)data;
+ struct if_cs_card *card = data;
u16 int_cause;
lbs_deb_enter(LBS_DEB_CS);
int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
- switch (int_cause) {
- case 0x0000:
- /* not for us */
+ if (int_cause == 0x0) {
+ /* Not for us */
return IRQ_NONE;
- case 0xffff:
- /* if one reads junk, then probably the card was removed */
- card->priv->adapter->surpriseremoved = 1;
- break;
- case IF_CS_H_IC_TX_OVER:
- if (card->priv->adapter->connect_status == LIBERTAS_CONNECTED)
- netif_wake_queue(card->priv->dev);
- /* fallthrought */
- default:
+
+ } else if (int_cause == 0xffff) {
+ /* Read in junk, the card has probably been removed */
+ card->priv->surpriseremoved = 1;
+ return IRQ_HANDLED;
+ } else {
+ if (int_cause & IF_CS_H_IC_TX_OVER)
+ lbs_host_to_card_done(card->priv);
+
/* clear interrupt */
if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK);
- if_cs_disable_ints(card);
}
-
- libertas_interrupt(card->priv->dev);
+ spin_lock(&card->priv->driver_lock);
+ lbs_interrupt(card->priv);
+ spin_unlock(&card->priv->driver_lock);
return IRQ_HANDLED;
}
/*
* Called from if_cs_host_to_card to send a command to the hardware
*/
-static int if_cs_send_cmd(wlan_private *priv, u8 *buf, u16 nb)
+static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
{
struct if_cs_card *card = (struct if_cs_card *)priv->card;
int ret = -1;
/*
* Called from if_cs_host_to_card to send a data to the hardware
*/
-static void if_cs_send_data(wlan_private *priv, u8 *buf, u16 nb)
+static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
{
struct if_cs_card *card = (struct if_cs_card *)priv->card;
/*
* Get the command result out of the card.
*/
-static int if_cs_receive_cmdres(wlan_private *priv, u8* data, u32 *len)
+static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
{
int ret = -1;
u16 val;
}
*len = if_cs_read16(priv->card, IF_CS_C_CMD_LEN);
- if ((*len == 0) || (*len > MRVDRV_SIZE_OF_CMD_BUFFER)) {
+ if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) {
lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len);
goto out;
}
if (*len & 1)
data[*len-1] = if_cs_read8(priv->card, IF_CS_C_CMD);
+ /* This is a workaround for a firmware that reports too much
+ * bytes */
+ *len -= 8;
ret = 0;
out:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
}
-static struct sk_buff *if_cs_receive_data(wlan_private *priv)
+static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
{
struct sk_buff *skb = NULL;
u16 len;
}
//TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN);
- skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+ skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
if (!skb)
goto out;
- data = skb_put(skb, len);
+ skb_put(skb, len);
+ skb_reserve(skb, 2);/* 16 byte align */
+ data = skb->data;
/* read even number of bytes, then odd byte if necessary */
if_cs_read16_rep(priv->card, IF_CS_H_READ, data, len/sizeof(u16));
ret = -ENODEV;
goto done;
}
- lbs_deb_cs("helper size %d\n", fw->size);
+ lbs_deb_cs("helper size %td\n", fw->size);
/* "Set the 5 bytes of the helper image to 0" */
/* Not needed, this contains an ARM branch instruction */
ret = -ENODEV;
goto done;
}
- lbs_deb_cs("fw size %d\n", fw->size);
+ lbs_deb_cs("fw size %td\n", fw->size);
ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK);
if (ret < 0) {
/* Callback functions for libertas.ko */
/********************************************************************/
-static int if_cs_register_dev(wlan_private *priv)
-{
- struct if_cs_card *card = (struct if_cs_card *)priv->card;
-
- lbs_deb_enter(LBS_DEB_CS);
-
- card->priv = priv;
-
- return 0;
-}
-
-
-static int if_cs_unregister_dev(wlan_private *priv)
-{
- lbs_deb_enter(LBS_DEB_CS);
-
- /*
- * Nothing special here. Because the device's power gets turned off
- * anyway, there's no need to send a RESET command like in if_usb.c
- */
-
- return 0;
-}
-
-
-/*
- * This callback is a dummy. The reason is that the USB code needs
- * to have various things set up in order to be able to download the
- * firmware. That's not needed in our case.
- *
- * On the contrary, if libertas_add_card() has been called and we're
- * then later called via libertas_activate_card(), but without a valid
- * firmware, then it's quite tedious to tear down the half-installed
- * card. Therefore, we download the firmware before calling adding/
- * activating the card in the first place. If that doesn't work, we
- * won't call into libertas.ko at all.
- */
-
-static int if_cs_prog_firmware(wlan_private *priv)
-{
- priv->adapter->fw_ready = 1;
- return 0;
-}
-
-
/* Send commands or data packets to the card */
-static int if_cs_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb)
+static int if_cs_host_to_card(struct lbs_private *priv,
+ u8 type,
+ u8 *buf,
+ u16 nb)
{
int ret = -1;
switch (type) {
case MVMS_DAT:
- priv->dnld_sent = DNLD_CMD_SENT;
+ priv->dnld_sent = DNLD_DATA_SENT;
if_cs_send_data(priv, buf, nb);
ret = 0;
break;
case MVMS_CMD:
+ priv->dnld_sent = DNLD_CMD_SENT;
ret = if_cs_send_cmd(priv, buf, nb);
break;
default:
}
-static int if_cs_get_int_status(wlan_private *priv, u8 *ireg)
+static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg)
{
struct if_cs_card *card = (struct if_cs_card *)priv->card;
- //wlan_adapter *adapter = priv->adapter;
int ret = 0;
u16 int_cause;
- u8 *cmdbuf;
*ireg = 0;
lbs_deb_enter(LBS_DEB_CS);
- if (priv->adapter->surpriseremoved)
+ if (priv->surpriseremoved)
goto out;
int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK;
if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause);
*ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
- if_cs_enable_ints(card);
if (!*ireg)
goto sbi_get_int_status_exit;
/* is there a data packet for us? */
if (*ireg & IF_CS_C_S_RX_UPLD_RDY) {
struct sk_buff *skb = if_cs_receive_data(priv);
- libertas_process_rxed_packet(priv, skb);
+ lbs_process_rxed_packet(priv, skb);
*ireg &= ~IF_CS_C_S_RX_UPLD_RDY;
}
/* Card has a command result for us */
if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) {
- spin_lock(&priv->adapter->driver_lock);
- if (!priv->adapter->cur_cmd) {
- cmdbuf = priv->upld_buf;
- priv->adapter->hisregcpy &= ~IF_CS_C_S_RX_UPLD_RDY;
- } else {
- cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr;
- }
-
- ret = if_cs_receive_cmdres(priv, cmdbuf, &priv->upld_len);
- spin_unlock(&priv->adapter->driver_lock);
+ ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len);
if (ret < 0)
lbs_pr_err("could not receive cmd from card\n");
}
out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->adapter->hisregcpy);
+ lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy);
return ret;
}
-static int if_cs_read_event_cause(wlan_private *priv)
+static int if_cs_read_event_cause(struct lbs_private *priv)
{
lbs_deb_enter(LBS_DEB_CS);
- priv->adapter->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
+ priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT);
return 0;
lbs_deb_enter(LBS_DEB_CS);
- pcmcia_disable_device(p_dev);
free_irq(p_dev->irq.AssignedIRQ, card);
+ pcmcia_disable_device(p_dev);
if (card->iobase)
ioport_unmap(card->iobase);
static int if_cs_probe(struct pcmcia_device *p_dev)
{
int ret = -ENOMEM;
- wlan_private *priv;
+ struct lbs_private *priv;
struct if_cs_card *card;
/* CIS parsing */
tuple_t tuple;
p_dev->irq.AssignedIRQ, p_dev->io.BasePort1,
p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1);
- if_cs_enable_ints(card);
/* Load the firmware early, before calling into libertas.ko */
ret = if_cs_prog_helper(card);
goto out2;
/* Make this card known to the libertas driver */
- priv = libertas_add_card(card, &p_dev->dev);
+ priv = lbs_add_card(card, &p_dev->dev);
if (!priv) {
ret = -ENOMEM;
goto out2;
}
/* Store pointers to our call-back functions */
+ card->priv = priv;
priv->card = card;
- priv->hw_register_dev = if_cs_register_dev;
- priv->hw_unregister_dev = if_cs_unregister_dev;
- priv->hw_prog_firmware = if_cs_prog_firmware;
priv->hw_host_to_card = if_cs_host_to_card;
priv->hw_get_int_status = if_cs_get_int_status;
priv->hw_read_event_cause = if_cs_read_event_cause;
+ priv->fw_ready = 1;
+
/* Now actually get the IRQ */
ret = request_irq(p_dev->irq.AssignedIRQ, if_cs_interrupt,
IRQF_SHARED, DRV_NAME, card);
goto out3;
}
+ /* Clear any interrupt cause that happend while sending
+ * firmware/initializing card */
+ if_cs_write16(card, IF_CS_C_INT_CAUSE, IF_CS_C_IC_MASK);
+ if_cs_enable_ints(card);
+
/* And finally bring the card up */
- if (libertas_activate_card(priv) != 0) {
+ if (lbs_start_card(priv) != 0) {
lbs_pr_err("could not activate card\n");
goto out3;
}
goto out;
out3:
- libertas_remove_card(priv);
+ lbs_remove_card(priv);
out2:
ioport_unmap(card->iobase);
out1:
lbs_deb_enter(LBS_DEB_CS);
- libertas_remove_card(card->priv);
+ lbs_stop_card(card->priv);
+ lbs_remove_card(card->priv);
+ if_cs_disable_ints(card);
if_cs_release(p_dev);
kfree(card);
MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
-static struct pcmcia_driver libertas_driver = {
+static struct pcmcia_driver lbs_driver = {
.owner = THIS_MODULE,
.drv = {
.name = DRV_NAME,
int ret;
lbs_deb_enter(LBS_DEB_CS);
- ret = pcmcia_register_driver(&libertas_driver);
+ ret = pcmcia_register_driver(&lbs_driver);
lbs_deb_leave(LBS_DEB_CS);
return ret;
}
static void __exit if_cs_exit(void)
{
lbs_deb_enter(LBS_DEB_CS);
- pcmcia_unregister_driver(&libertas_driver);
+ pcmcia_unregister_driver(&lbs_driver);
lbs_deb_leave(LBS_DEB_CS);
}