arch/mips/sni/rm200.c

Source file repositories/reference/linux-study-clean/arch/mips/sni/rm200.c

File Facts

System
Linux kernel
Corpus path
arch/mips/sni/rm200.c
Extension
.c
Size
12584 bytes
Lines
486
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

device_initcall(snirm_setup_devinit);

/*
 * RM200 has an ISA and an EISA bus. The iSA bus is only used
 * for onboard devices and also has twi i8259 PICs. Since these
 * PICs are no accessible via inb/outb the following code uses
 * readb/writeb to access them
 */

static DEFINE_RAW_SPINLOCK(sni_rm200_i8259A_lock);
#define PIC_CMD	   0x00
#define PIC_IMR	   0x01
#define PIC_ISR	   PIC_CMD
#define PIC_POLL   PIC_ISR
#define PIC_OCW3   PIC_ISR

/* i8259A PIC related value */
#define PIC_CASCADE_IR		2
#define MASTER_ICW4_DEFAULT	0x01
#define SLAVE_ICW4_DEFAULT	0x01

/*
 * This contains the irq mask for both 8259A irq controllers,
 */
static unsigned int rm200_cached_irq_mask = 0xffff;
static __iomem u8 *rm200_pic_master;
static __iomem u8 *rm200_pic_slave;

#define cached_master_mask	(rm200_cached_irq_mask)
#define cached_slave_mask	(rm200_cached_irq_mask >> 8)

static void sni_rm200_disable_8259A_irq(struct irq_data *d)
{
	unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE;
	unsigned long flags;

	mask = 1 << irq;
	raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
	rm200_cached_irq_mask |= mask;
	if (irq & 8)
		writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
	else
		writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
	raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
}

static void sni_rm200_enable_8259A_irq(struct irq_data *d)
{
	unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE;
	unsigned long flags;

	mask = ~(1 << irq);
	raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
	rm200_cached_irq_mask &= mask;
	if (irq & 8)
		writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR);
	else
		writeb(cached_master_mask, rm200_pic_master + PIC_IMR);
	raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
}

static inline int sni_rm200_i8259A_irq_real(unsigned int irq)
{
	int value;
	int irqmask = 1 << irq;

	if (irq < 8) {
		writeb(0x0B, rm200_pic_master + PIC_CMD);
		value = readb(rm200_pic_master + PIC_CMD) & irqmask;
		writeb(0x0A, rm200_pic_master + PIC_CMD);
		return value;
	}
	writeb(0x0B, rm200_pic_slave + PIC_CMD); /* ISR register */
	value = readb(rm200_pic_slave + PIC_CMD) & (irqmask >> 8);
	writeb(0x0A, rm200_pic_slave + PIC_CMD);
	return value;
}

/*
 * Careful! The 8259A is a fragile beast, it pretty
 * much _has_ to be done exactly like this (mask it
 * first, _then_ send the EOI, and the order of EOI
 * to the two 8259s is important!
 */
void sni_rm200_mask_and_ack_8259A(struct irq_data *d)
{
	unsigned int irqmask, irq = d->irq - RM200_I8259A_IRQ_BASE;
	unsigned long flags;

	irqmask = 1 << irq;

Annotation

Implementation Notes