📄 via.c
字号:
printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n", (uint) via2[vPCR], (uint) via2[vIFR], (uint) via2[vIER]); }}/* * This is always executed with interrupts disabled. * * TBI: get time offset between scheduling timer ticks */unsigned long mac_gettimeoffset (void){ unsigned long ticks, offset = 0; /* read VIA1 timer 2 current value */ ticks = via1[vT1CL] | (via1[vT1CH] << 8); /* The probability of underflow is less than 2% */ if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50) /* Check for pending timer interrupt in VIA1 IFR */ if (via1[vIFR] & 0x40) offset = TICK_SIZE; ticks = MAC_CLOCK_TICK - ticks; ticks = ticks * 10000L / MAC_CLOCK_TICK; return ticks + offset;}/* * Flush the L2 cache on Macs that have it by flipping * the system into 24-bit mode for an instant. */void via_flush_cache(void){ via2[gBufB] &= ~VIA2B_vMode32; via2[gBufB] |= VIA2B_vMode32;}/* * Return the status of the L2 cache on a IIci */int via_get_cache_disable(void){ /* Safeguard against being called accidentally */ if (!via2) { printk(KERN_ERR "via_get_cache_disable called on a non-VIA machine!\n"); return 1; } return (int) via2[gBufB] & VIA2B_vCDis;}/* * Initialize VIA2 for Nubus access */void __init via_nubus_init(void){ /* don't set nubus_active = 0 here, it kills the Baboon */ /* interrupt that we've already registered. */ /* unlock nubus transactions */ if (!rbv_present) { /* set the line to be an output on non-RBV machines */ if ((macintosh_config->adb_type != MAC_ADB_PB1) && (macintosh_config->adb_type != MAC_ADB_PB2)) { via2[vDirB] |= 0x02; } } /* this seems to be an ADB bit on PMU machines */ /* according to MkLinux. -- jmt */ if ((macintosh_config->adb_type != MAC_ADB_PB1) && (macintosh_config->adb_type != MAC_ADB_PB2)) { via2[gBufB] |= 0x02; } /* disable nubus slot interrupts. */ if (rbv_present) { via2[rSIER] = 0x7F; via2[rSIER] = nubus_active | 0x80; } else { /* These are ADB bits on PMU */ if ((macintosh_config->adb_type != MAC_ADB_PB1) && (macintosh_config->adb_type != MAC_ADB_PB2)) { switch(macintosh_config->ident) { case MAC_MODEL_II: case MAC_MODEL_IIX: case MAC_MODEL_IICX: case MAC_MODEL_SE30: via2[vBufA] |= 0x3F; via2[vDirA] = ~nubus_active | 0xc0; break; default: via2[vBufA] = 0xFF; via2[vDirA] = ~nubus_active; } } }}/* * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's * via6522.c :-), disable/pending masks added. * * The new interrupt architecture in macints.c takes care of a lot of the * gruntwork for us, including tallying the interrupts and calling the * handlers on the linked list. All we need to do here is basically generate * the machspec interrupt number after clearing the interrupt. */irqreturn_t via1_irq(int irq, void *dev_id, struct pt_regs *regs){ int irq_bit, i; unsigned char events, mask; mask = via1[vIER] & 0x7F; if (!(events = via1[vIFR] & mask)) return IRQ_NONE; for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) if (events & irq_bit) { via1[vIER] = irq_bit; mac_do_irq_list(VIA1_SOURCE_BASE + i, regs); via1[vIFR] = irq_bit; via1[vIER] = irq_bit | 0x80; }#if 0 /* freakin' pmu is doing weird stuff */ if (!oss_present) { /* This (still) seems to be necessary to get IDE working. However, if you enable VBL interrupts, you're screwed... */ /* FIXME: should we check the SLOTIRQ bit before pulling this stunt? */ /* No, it won't be set. that's why we're doing this. */ via_irq_disable(IRQ_MAC_NUBUS); via_irq_clear(IRQ_MAC_NUBUS); mac_do_irq_list(IRQ_MAC_NUBUS, regs); via_irq_enable(IRQ_MAC_NUBUS); }#endif return IRQ_HANDLED;}irqreturn_t via2_irq(int irq, void *dev_id, struct pt_regs *regs){ int irq_bit, i; unsigned char events, mask; mask = via2[gIER] & 0x7F; if (!(events = via2[gIFR] & mask)) return IRQ_NONE; for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) if (events & irq_bit) { via2[gIER] = irq_bit; mac_do_irq_list(VIA2_SOURCE_BASE + i, regs); via2[gIFR] = irq_bit | rbv_clear; via2[gIER] = irq_bit | 0x80; } return IRQ_HANDLED;}/* * Dispatch Nubus interrupts. We are called as a secondary dispatch by the * VIA2 dispatcher as a fast interrupt handler. */irqreturn_t via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs){ int irq_bit, i; unsigned char events; if (!(events = ~via2[gBufA] & nubus_active)) return IRQ_NONE; for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) { if (events & irq_bit) { via_irq_disable(NUBUS_SOURCE_BASE + i); mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs); via_irq_enable(NUBUS_SOURCE_BASE + i); } } return IRQ_HANDLED;}void via_irq_enable(int irq) { int irq_src = IRQ_SRC(irq); int irq_idx = IRQ_IDX(irq); int irq_bit = 1 << irq_idx;#ifdef DEBUG_IRQUSE printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);#endif if (irq_src == 1) { via1[vIER] = irq_bit | 0x80; } else if (irq_src == 2) { /* * Set vPCR for SCSI interrupts (but not on RBV) */ if ((irq_idx == 0) && !rbv_present) { if (macintosh_config->scsi_type == MAC_SCSI_OLD) { /* CB2 (IRQ) indep. input, positive edge */ /* CA2 (DRQ) indep. input, positive edge */ via2[vPCR] = 0x66; } else { /* CB2 (IRQ) indep. input, negative edge */ /* CA2 (DRQ) indep. input, negative edge */ via2[vPCR] = 0x22; } } via2[gIER] = irq_bit | 0x80; } else if (irq_src == 7) { if (rbv_present) { /* enable the slot interrupt. SIER works like IER. */ via2[rSIER] = IER_SET_BIT(irq_idx); } else { /* Make sure the bit is an input, to enable the irq */ /* But not on PowerBooks, that's ADB... */ if ((macintosh_config->adb_type != MAC_ADB_PB1) && (macintosh_config->adb_type != MAC_ADB_PB2)) { switch(macintosh_config->ident) { case MAC_MODEL_II: case MAC_MODEL_IIX: case MAC_MODEL_IICX: case MAC_MODEL_SE30: via2[vDirA] &= (~irq_bit | 0xc0); break; default: via2[vDirA] &= ~irq_bit; } } } nubus_active |= irq_bit; }}void via_irq_disable(int irq) { int irq_src = IRQ_SRC(irq); int irq_idx = IRQ_IDX(irq); int irq_bit = 1 << irq_idx;#ifdef DEBUG_IRQUSE printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);#endif if (irq_src == 1) { via1[vIER] = irq_bit; } else if (irq_src == 2) { via2[gIER] = irq_bit; } else if (irq_src == 7) { if (rbv_present) { /* disable the slot interrupt. SIER works like IER. */ via2[rSIER] = IER_CLR_BIT(irq_idx); } else { /* disable the nubus irq by changing dir to output */ /* except on PMU */ if ((macintosh_config->adb_type != MAC_ADB_PB1) && (macintosh_config->adb_type != MAC_ADB_PB2)) { via2[vDirA] |= irq_bit; } } nubus_active &= ~irq_bit; }}void via_irq_clear(int irq) { int irq_src = IRQ_SRC(irq); int irq_idx = IRQ_IDX(irq); int irq_bit = 1 << irq_idx; if (irq_src == 1) { via1[vIFR] = irq_bit; } else if (irq_src == 2) { via2[gIFR] = irq_bit | rbv_clear; } else if (irq_src == 7) { /* FIXME: hmm.. */ }}/* * Returns nonzero if an interrupt is pending on the given * VIA/IRQ combination. */int via_irq_pending(int irq){ int irq_src = IRQ_SRC(irq); int irq_idx = IRQ_IDX(irq); int irq_bit = 1 << irq_idx; if (irq_src == 1) { return via1[vIFR] & irq_bit; } else if (irq_src == 2) { return via2[gIFR] & irq_bit; } else if (irq_src == 7) { return ~via2[gBufA] & irq_bit; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -