misc mumblings about if_cs.c card interrupt / card status
Holger Schurig
hs4233 at mail.mn-solutions.de
Mon May 26 03:56:42 EDT 2008
Just writing this as mail in case anybody wants to google it :-)
The 5.0.16 GPL driver from Marvell did the following:
* at interrupt time, disable interrupts (we don't currently do
this) by writing 0x1f into the host-int-mask register.
* get card-int-cause and store it away
* get card-status and store it away
* run callback into what is now libertas.ko
* clear bits in card-int-case
* enable interrupt by writing into the host-in-mask register
* the thread did use the stored away values, e.g. to
call the sbi_host_to_card() function.
We now try to do all of this in the interrupt handler and have
various hickups right now, especially when we execute commands
while transfering lot's of frames.
card-in-cause is a register where I can clear bits by writing
the bitmask of bits-to-clear back.
card-status just tells me what the card allows currently.
When a command response is available, I get an interrupt with
card-int-case 0x0008, meaning IF_CS_RESP_READY. Card-status is
0x000d = (IF_CS_C_S_TX_DNLD_RDY,IF_CS_C_S_CMD_DNLD_RDY,
IF_CS_C_S_CMD_UPLD_RDY). The latter means that I can
* send a TX frame to the card
* send a command to the card
* receive a response from the card.
When I receive a frame, I get an interrupt with card-int-case
0x0002, meaning IF_CS_RX_AVAIL. Card-status is 0x0007 =
(IF_CS_C_S_TX_DNLD_RDY, IF_CS_C_S_RX_UPLD_RDY,
IF_CS_C_S_CMD_DNLD_RDY). So this time I can
* send a TX frame to the card
* get a RX frame from the card
* send a command to the card
When I send a frame, I get an interrupt with card-int-casue
0x0001, meaning IF_CS_TX_DONE. Card-status is 0x0005
(IF_CS_C_S_TX_DNLD_RDY, IF_CS_C_S_CMD_DNLD_RDY). So this time I
can
* send a TX frame to the card
* send a command to the card
When the card has an event for me, I get an interrupt with
card-int-status is 0x0010, meaning IF_CS_C_S_CARDEVENT.
card-status was in my case 0x0815. The high byte contains the
event, here 0x08. This time I can:
* send a TX frame to the card
* send a command to the card
* get? (maybe clear) a card event
cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
if (cause & IF_CS_H_IC_TX_OVER) {
lbs_deb_cs("tx over\n");
lbs_host_to_card_done(priv);
}
is definitely erraneous, because IF_CS_H_IC_TX_OVER is always
set, it just means "Hey, the buffer in the card is free, you can
send a TX frame to the card". It does NOT mean that the card
successfully sent a TX frame.
While I think that card-int-case makes much more sense, I might
need to resort to card-status because of the strange lockups I
notices. If I have to use card-status, then I can really only
use that register for:
* get a command response from the card
* get an rx-frame from the card
* reading card event
I also think that currently I don't really check the card-status
for IF_CS_C_S_TX_DNLD_RDY bit, e.g. I just stuff data down into
the card, no matter if that is OK or not.
More information about the libertas-dev
mailing list