drivers/net/can/sja1000/ems_pcmcia.c
Source file repositories/reference/linux-study-clean/drivers/net/can/sja1000/ems_pcmcia.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/can/sja1000/ems_pcmcia.c- Extension
.c- Size
- 7868 bytes
- Lines
- 317
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kernel.hlinux/module.hlinux/interrupt.hlinux/netdevice.hlinux/delay.hlinux/io.hpcmcia/cistpl.hpcmcia/ds.hlinux/can.hlinux/can/dev.hsja1000.h
Detected Declarations
struct ems_pcmcia_cardfunction ems_pcmcia_read_regfunction ems_pcmcia_write_regfunction ems_pcmcia_interruptfunction ems_pcmcia_check_chanfunction ems_pcmcia_del_cardfunction ems_pcmcia_add_cardfunction ems_pcmcia_probefunction ems_pcmcia_remove
Annotated Snippet
struct ems_pcmcia_card {
int channels;
struct pcmcia_device *pcmcia_dev;
struct net_device *net_dev[EMS_PCMCIA_MAX_CHAN];
void __iomem *base_addr;
};
#define EMS_PCMCIA_CAN_CLOCK (16000000 / 2)
/*
* The board configuration is probably following:
* RX1 is connected to ground.
* TX1 is not connected.
* CLKO is not connected.
* Setting the OCR register to 0xDA is a good idea.
* This means normal output mode , push-pull and the correct polarity.
*/
#define EMS_PCMCIA_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
/*
* In the CDR register, you should set CBP to 1.
* You will probably also want to set the clock divider value to 7
* (meaning direct oscillator output) because the second SJA1000 chip
* is driven by the first one CLKOUT output.
*/
#define EMS_PCMCIA_CDR (CDR_CBP | CDR_CLKOUT_MASK)
#define EMS_PCMCIA_MEM_SIZE 4096 /* Size of the remapped io-memory */
#define EMS_PCMCIA_CAN_BASE_OFFSET 0x100 /* Offset where controllers starts */
#define EMS_PCMCIA_CAN_CTRL_SIZE 0x80 /* Memory size for each controller */
#define EMS_CMD_RESET 0x00 /* Perform a reset of the card */
#define EMS_CMD_MAP 0x03 /* Map CAN controllers into card' memory */
#define EMS_CMD_UMAP 0x02 /* Unmap CAN controllers from card' memory */
static struct pcmcia_device_id ems_pcmcia_tbl[] = {
PCMCIA_DEVICE_PROD_ID123("EMS_T_W", "CPC-Card", "V2.0", 0xeab1ea23,
0xa338573f, 0xe4575800),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, ems_pcmcia_tbl);
static u8 ems_pcmcia_read_reg(const struct sja1000_priv *priv, int port)
{
return readb(priv->reg_base + port);
}
static void ems_pcmcia_write_reg(const struct sja1000_priv *priv, int port,
u8 val)
{
writeb(val, priv->reg_base + port);
}
static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id)
{
struct ems_pcmcia_card *card = dev_id;
struct net_device *dev;
irqreturn_t retval = IRQ_NONE;
int i, again;
/* Card not present */
if (readw(card->base_addr) != 0xAA55)
return IRQ_HANDLED;
do {
again = 0;
/* Check interrupt for each channel */
for (i = 0; i < card->channels; i++) {
dev = card->net_dev[i];
if (!dev)
continue;
if (sja1000_interrupt(irq, dev) == IRQ_HANDLED)
again = 1;
}
/* At least one channel handled the interrupt */
if (again)
retval = IRQ_HANDLED;
} while (again);
return retval;
}
/*
* Check if a CAN controller is present at the specified location
* by trying to set 'em into the PeliCAN mode
*/
static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv)
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/module.h`, `linux/interrupt.h`, `linux/netdevice.h`, `linux/delay.h`, `linux/io.h`, `pcmcia/cistpl.h`, `pcmcia/ds.h`.
- Detected declarations: `struct ems_pcmcia_card`, `function ems_pcmcia_read_reg`, `function ems_pcmcia_write_reg`, `function ems_pcmcia_interrupt`, `function ems_pcmcia_check_chan`, `function ems_pcmcia_del_card`, `function ems_pcmcia_add_card`, `function ems_pcmcia_probe`, `function ems_pcmcia_remove`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.