1 /* $NetBSD: pic_prepivr.c,v 1.3 2007/12/11 18:04:20 garbled Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tim Rightnour 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: pic_prepivr.c,v 1.3 2007/12/11 18:04:20 garbled Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/malloc.h> 44 #include <sys/kernel.h> 45 46 #include <uvm/uvm_extern.h> 47 48 #include <machine/pio.h> 49 #include <machine/intr.h> 50 51 #include <arch/powerpc/pic/picvar.h> 52 53 #include <dev/isa/isareg.h> 54 #include <dev/isa/isavar.h> 55 56 static int prepivr_get_irq(struct pic_ops *, int); 57 static int motivr_get_irq(struct pic_ops *, int); 58 static void prepivr_establish_irq(struct pic_ops *, int, int, int); 59 60 vaddr_t prep_intr_reg; /* PReP interrupt vector register */ 61 uint32_t prep_intr_reg_off; /* IVR offset within the mapped page */ 62 63 #define IO_ELCR1 0x4d0 64 #define IO_ELCR2 0x4d1 65 66 /* 67 * Prior to calling init_prepivr, the port is expected to have mapped the 68 * page containing the IVR with mapiodev to prep_intr_reg and set up the 69 * prep_intr_reg_off. 70 */ 71 72 struct pic_ops * 73 setup_prepivr(int ivrtype) 74 { 75 struct i8259_ops *prepivr; 76 struct pic_ops *pic; 77 uint32_t pivr; 78 79 prepivr = malloc(sizeof(struct i8259_ops), M_DEVBUF, M_NOWAIT); 80 KASSERT(prepivr != NULL); 81 pic = &prepivr->pic; 82 83 pivr = prep_intr_reg + prep_intr_reg_off; 84 pic->pic_numintrs = 16; 85 pic->pic_cookie = (void *)pivr; 86 pic->pic_enable_irq = i8259_enable_irq; 87 pic->pic_reenable_irq = i8259_enable_irq; 88 pic->pic_disable_irq = i8259_disable_irq; 89 if (ivrtype == PIC_IVR_MOT) 90 pic->pic_get_irq = motivr_get_irq; 91 else 92 pic->pic_get_irq = prepivr_get_irq; 93 pic->pic_ack_irq = i8259_ack_irq; 94 pic->pic_establish_irq = prepivr_establish_irq; 95 pic->pic_finish_setup = NULL; 96 strcpy(pic->pic_name, "prepivr"); 97 pic_add(pic); 98 prepivr->pending_events = 0; 99 prepivr->enable_mask = 0xffffffff; 100 prepivr->irqs = 0; 101 102 /* initialize the ELCR */ 103 isa_outb(IO_ELCR1, (0 >> 0) & 0xff); 104 isa_outb(IO_ELCR2, (0 >> 8) & 0xff); 105 i8259_initialize(); 106 107 return pic; 108 } 109 110 static void 111 prepivr_establish_irq(struct pic_ops *pic, int irq, int type, int maxlevel) 112 { 113 u_int8_t elcr[2]; 114 int icu, bit; 115 116 icu = irq / 8; 117 bit = irq % 8; 118 elcr[0] = isa_inb(IO_ELCR1); 119 elcr[1] = isa_inb(IO_ELCR2); 120 121 if (type == IST_LEVEL) 122 elcr[icu] |= 1 << bit; 123 else 124 elcr[icu] &= ~(1 << bit); 125 126 isa_outb(IO_ELCR1, elcr[0]); 127 isa_outb(IO_ELCR2, elcr[1]); 128 } 129 130 static int 131 motivr_get_irq(struct pic_ops *pic, int mode) 132 { 133 int irq; 134 135 irq = i8259_get_irq(pic, mode); 136 /* read the IVR to ack it */ 137 (void)inb(pic->pic_cookie); 138 139 /* i8259_get_irq will return 255 by itself, so just pass it on */ 140 return irq; 141 } 142 143 static int 144 prepivr_get_irq(struct pic_ops *pic, int mode) 145 { 146 int irq; 147 148 irq = inb(pic->pic_cookie); 149 150 if (irq == 0 && mode == PIC_GET_IRQ) 151 return 255; 152 if (irq == 7 && mode == PIC_GET_RECHECK) 153 return 255; 154 155 return irq; 156 } 157