Home | History | Annotate | Line # | Download | only in newsmips
news5000.c revision 1.1
      1 /*	$NetBSD: news5000.c,v 1.1 1999/12/22 05:53:21 tsubai Exp $	*/
      2 
      3 /*-
      4  * Copyright (C) 1999 SHIMIZU Ryo.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. The name of the author may not be used to endorse or promote products
     15  *    derived from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/param.h>
     30 #include <sys/systm.h>
     31 #include <sys/kernel.h>
     32 
     33 #include <machine/adrsmap.h>
     34 #include <machine/cpu.h>
     35 #include <machine/intr.h>
     36 
     37 #include <newsmips/apbus/apbusvar.h>
     38 #include <newsmips/newsmips/machid.h>
     39 
     40 static void level5_interrupt __P((void));
     41 static void level4_interrupt __P((void));
     42 static void level3_interrupt __P((void));
     43 static void level2_interrupt __P((unsigned int, unsigned int));
     44 static void level1_interrupt __P((void));
     45 static void level0_interrupt __P((void));
     46 
     47 static void abif_error4 __P((void));
     48 
     49 /*
     50  * Handle news5000 interrupts.
     51  */
     52 int
     53 news5000_intr(mask, pc, statusReg, causeReg)
     54 	u_int mask;
     55 	u_int pc;		/* program counter where to continue */
     56 	u_int statusReg;	/* status register at time of the exception */
     57 	u_int causeReg;		/* cause register at time of exception */
     58 {
     59 	if (mask & MIPS_INT_MASK_2) {
     60 		level2_interrupt(pc,statusReg);
     61 		apbus_wbflush();
     62 		causeReg &= ~MIPS_INT_MASK_2;
     63 	}
     64 	/* If clock interrupts were enabled, re-enable them ASAP. */
     65 	splx(MIPS_SR_INT_IE | (statusReg & MIPS_INT_MASK_2));
     66 
     67 	if (mask & MIPS_INT_MASK_5) {
     68 		level5_interrupt();
     69 		apbus_wbflush();
     70 		causeReg &= ~MIPS_INT_MASK_5;
     71 	}
     72 
     73 	if (mask & MIPS_INT_MASK_4) {
     74 		level4_interrupt();
     75 		apbus_wbflush();
     76 		causeReg &= ~MIPS_INT_MASK_4;
     77 	}
     78 
     79 	if (mask & MIPS_INT_MASK_3) {
     80 		level3_interrupt();
     81 		apbus_wbflush();
     82 		causeReg &= ~MIPS_INT_MASK_3;
     83 	}
     84 
     85 	if (mask & MIPS_INT_MASK_1) {
     86 		level1_interrupt();
     87 		apbus_wbflush();
     88 		causeReg &= ~MIPS_INT_MASK_1;
     89 	}
     90 
     91 	if (mask & MIPS_INT_MASK_0) {
     92 		level0_interrupt();
     93 		apbus_wbflush();
     94 		causeReg &= ~MIPS_INT_MASK_0;
     95 	}
     96 
     97 	return ((statusReg & ~causeReg & MIPS_HARD_INT_MASK) |  MIPS_SR_INT_IE);
     98 }
     99 
    100 void
    101 level5_interrupt()
    102 {
    103 	printf("level5 interrupt\n");
    104 }
    105 
    106 void
    107 level4_interrupt()
    108 {
    109 	volatile int *intenp = (volatile int *)NEWS5000_INTMASK4;
    110 	int int4stat, saved_inten;
    111 
    112 	int4stat = *(volatile int *)NEWS5000_INTSTAT4;
    113 	saved_inten = *intenp;
    114 	*intenp = 0;
    115 	if (int4stat & NEWS5000_INT4_SBIF) {
    116 printf("SBIF ERROR\n");
    117 		/* sbif_error4(); */
    118 	} else if (int4stat & NEWS5000_INT4_MFBIF) {
    119 printf("MBIF ERROR\n");
    120 /*
    121 		mbif_error4();
    122 		if (fxif_error4)
    123 		    fxif_error4();
    124 */
    125 	} else if (int4stat & NEWS5000_INT4_ABIF) {
    126 /* printf("ABIF ERROR\n"); */
    127 		abif_error4();
    128 	}
    129 	*intenp = saved_inten;
    130 }
    131 
    132 static void
    133 abif_error4()
    134 {
    135 #define	AB_BERRADR	0xb4c00018
    136 #define	AB_BERRDATA	0xb4c00020
    137 #define	AB_BERRPARITY	0xb4c00028
    138 
    139 	int stat;
    140 
    141 printf("abif_error4\n");
    142 
    143 	stat = *(volatile u_int *)NEWS5000_APBUS_INTSTAT &
    144 	       *(volatile u_int *)NEWS5000_APBUS_INTMASK;
    145 
    146 	if (stat & NEWS5000_INTAPBUS_DMAADDRESS) {
    147 		printf("AB I/F: DMA address error\n");
    148 	}
    149 	if (stat & (NEWS5000_INTAPBUS_RDTIMEO|NEWS5000_INTAPBUS_WRTIMEO)) {
    150 		if (stat & NEWS5000_INTAPBUS_RDTIMEO)
    151 			printf("AB I/F: read timeout\n");
    152 		if (stat & NEWS5000_INTAPBUS_WRTIMEO)
    153 			printf("AB I/F: write timeout\n");
    154 
    155 		printf("	address = %x:%x\n",
    156 		    *(volatile u_int *)AB_BERRADR, *(volatile u_int *)(AB_BERRADR + 4));
    157 	}
    158 	*(volatile u_int *)NEWS5000_APBUS_INTSTAT = stat;
    159 }
    160 
    161 void
    162 level3_interrupt()
    163 {
    164 	printf("level3 interrupt\n");
    165 }
    166 
    167 void
    168 level2_interrupt(pc, statusReg)
    169 	unsigned int pc;
    170 	unsigned int statusReg;
    171 {
    172 #ifdef DEBUG
    173 	static int l2cnt = 0;
    174 #endif
    175 	unsigned int int2stat;
    176 	struct clockframe cf;
    177 
    178 	int2stat = *(volatile unsigned int *)NEWS5000_INTSTAT2;
    179 
    180 #ifdef DEBUG
    181 	l2cnt++;
    182 	if (l2cnt == 50) {
    183 		*(volatile unsigned int *)NEWS5000_LED3 = 1;
    184 	}
    185 	if (l2cnt == 100) {
    186 		*(volatile unsigned int *)NEWS5000_LED3 = 0;
    187 		l2cnt = 0;
    188 	}
    189 #endif
    190 
    191 	if (int2stat & NEWS5000_INT2_TIMER0) {
    192 		*(volatile unsigned int *)NEWS5000_TIMER0 = 1;
    193 
    194 		cf.pc = pc;
    195 		cf.sr = statusReg;
    196 
    197 		hardclock(&cf);
    198 		intrcnt[HARDCLOCK_INTR]++;
    199 	}
    200 
    201 	if (int2stat & NEWS5000_INT2_TIMER1) {
    202 		*(volatile unsigned int *)NEWS5000_TIMER1 = 1;
    203 	}
    204 }
    205 
    206 void
    207 level1_interrupt()
    208 {
    209 	unsigned int int1stat;
    210 	int nintcall;
    211 
    212 	int1stat = *(volatile unsigned int *)NEWS5000_INTSTAT1;
    213 
    214 	if (int1stat) {
    215 		/* printf("level1 interrupt (%08x)\n", int1stat); */
    216 		nintcall = apbus_intr_call(1,int1stat);
    217 
    218 		if (!nintcall) {
    219 			printf("level1_interrupt: no match interrupt mask! %04x\n",int1stat);
    220 		}
    221 	} else {
    222 		printf("level1 stray interrupt?\n");
    223 	}
    224 
    225 }
    226 
    227 void
    228 level0_interrupt()
    229 {
    230 	unsigned int int0stat;
    231 	int nintcall;
    232 
    233 	int0stat = *(volatile unsigned int *)NEWS5000_INTSTAT0;
    234 
    235 	if (int0stat) {
    236 		/* printf("level0 interrupt (%08x)\n", int0stat); */
    237 		nintcall = apbus_intr_call(0, int0stat);
    238 
    239 		if (!nintcall) {
    240 			printf("level0_interrupt: no match interrupt mask! %04x\n",int0stat);
    241 		}
    242 
    243 	} else {
    244 		printf("level0 stray interrupt?\n");
    245 	}
    246 
    247 }
    248 
    249 void
    250 enable_intr_5000()
    251 {
    252 	/* APbus Interrupt (DMAC, SONIC, FIFO*, FDC) */
    253 	*(volatile unsigned int *)NEWS5000_INTMASK0 =
    254 		NEWS5000_INTSLOT_ALL|NEWS5000_INT0_ALL;
    255 
    256 	/* APbus Interrupt (KBD, SERIAL, AUDIO*, PARALLEL, FB */
    257 	*(volatile unsigned int *)NEWS5000_INTMASK1 =
    258 		NEWS5000_INTSLOT_ALL|NEWS5000_INT1_ALL;
    259 
    260 	*(volatile unsigned int *)NEWS5000_INTMASK4 =
    261 		NEWS5000_INT4_ALL;
    262 
    263 	*(volatile unsigned int *)NEWS5000_INTCLR5 = 0xffffffff;
    264 	*(volatile unsigned int *)NEWS5000_INTMASK5 =
    265 		NEWS5000_INT5_ABIF|NEWS5000_INT5_MBIF|NEWS5000_INT5_SBIF;
    266 }
    267 
    268 void
    269 disable_intr_5000()
    270 {
    271 	*(volatile unsigned int *)NEWS5000_INTMASK0 = 0;
    272 	*(volatile unsigned int *)NEWS5000_INTMASK1 = 0;
    273 	*(volatile unsigned int *)NEWS5000_INTMASK2 = 0;
    274 	*(volatile unsigned int *)NEWS5000_INTMASK3 = 0;
    275 	*(volatile unsigned int *)NEWS5000_INTMASK4 = 0;
    276 	*(volatile unsigned int *)NEWS5000_INTMASK5 = 0;
    277 }
    278 
    279 void
    280 readidrom_5000(rom)
    281 	u_char *rom;
    282 {
    283 	u_int32_t *p = (void *)NEWS5000_IDROM;
    284 	int i;
    285 
    286 	for (i = 0; i < sizeof (struct idrom); i++, p += 2)
    287 		*rom++ = ((*p & 0x0f) << 4) + (*(p + 1) & 0x0f);
    288 }
    289 
    290 extern struct idrom idrom;
    291 
    292 void
    293 news5000_init()
    294 {
    295 	enable_intr = enable_intr_5000;
    296 	disable_intr = disable_intr_5000;
    297 
    298 	readidrom_5000((u_char *)&idrom);
    299 }
    300