📄 kn220.c
字号:
* needs to be before the ib_config_.... calls which load the * scb; don't want unifind to stomp on the entries after they * are set. */ unifind(qb_ptr,KN220QBUSREG,qmem, 0x14000000,512*8192,0x10000000,QMEMmap,0,0,0); } /* * Configure all the devices. I/O devices include * an on-board Ethernet interface, an on-board DSSI interface, * and a Q22 Bus. * * On board devices sit on a virtual bus called the "ibus". */ config_set_alive("ibus",0,0,0); /* Configure on-board ethernet */ ib_config_dev(PHYS_TO_K1(KN220SGEC_ADDR), KN220SGEC_ADDR,0,"ne",(int)scb+SGEC_OFFSET); /* Initialize NVRAM pseudo-driver */ /* 3rd arg is: mapped?; 4th arg is cached? */ /* Use un-mapped, cached NVRAM */ if (kn220_usenvram) presto_init(NVRAM_ADDR, NVRAM_SIZE, kn220_nvram_mapped, kn220_cache_nvram, kn220_machineid()); /* We need a test nNASC but nNASC is not set up in autoconf_data.c yet * NEED FIXING OR fix the alive bit in the SCSI driver. */ /* Configure on-board SCSI */ ib_config_cont(PHYS_TO_K1(KN220_53C94_REG_ADDR), KN220_53C94_REG_ADDR,0,"asc",(int)scb+SCSI_OFFSET); /* Configure on-board DSSI */ if (nNMSI) { extern int (*msiintv[])(); scb[MSI_OFFSET/4] = msiintv[nummsi]; /* Stuff the SCB */ if (msi_probe(nummsi,PHYS_TO_K1(KN220MSIREG_ADDR), PHYS_TO_K1(KN220SIIBUF_ADDR))) { config_set_alive("msi",0,0,0); printf("msi%d\n",nummsi); } } /* Now is a good time to check the VME bus * to see if it there. If we find the VME, all * its devices should be pulled in now. * * Read content of IOPRES bit to see if a VME is present. */ vmepres = *(int *)KN220IOPRES; if ((vmepres) & KN220_VMEP) { /* We have one slot that can have a VME or a FDDI cadr * but not both. */ if(BADADDR(PHYS_TO_K1(VME_BASE_ADDR),4)){ /* Search adapter table to see if VME is configured. * Compare must be hardwired to "vba" because there * is no configuration database for the RIO like * there is for the TURBOchannel. * If the VME adapter is configured then call the * configuration routine. * */ found = 0; for (i = 0; config_adpt[i].p_name != NULL; i++) { if ((!(strcmp ("vba", config_adpt[i].c_name))) && (config_adpt[i].c_type == 'A')) { xviaconf(PHYS_TO_K1(VME_BASE_ADDR), VME_BASE_ADDR, 0, config_adpt[i].c_num, 0); found = 1; break; } } if(!found) printf("VME not configured\n"); } else if(BADADDR(PHYS_TO_K1(FDDI_BASE_ADDR),4)){ /* Call FDDI config routine * when we have one. For now we will do a print * statement that we found one? */ printf("FDDI\n"); } } /* Now we will work on the Configure of the Q22 bus. * We need to find all devices that are in the config * file and that are on the BUS. */ /* Clear boot flag */ cold = 0; /* Startup the code that clears the Single Bit ECC error * log array every 15 min. */ timeout(kn220_ZSbit,0,15*60*hz); return(0);}/* * Initialization routine for kn220 processor (MIPSFAIR2). */kn220init(){ extern int c0vec_tblsize; extern int (*c0vec_tbl[])(); extern int iplmask[]; extern int splm[]; extern int hz; extern int tick; extern int tickadj; extern struct cpusw *cpup; /* Points to unibus adaptor regs */ qb_ptr = (struct qbm_regs *)(PHYS_TO_K1(KN220QBUSREG)); /* * bcopy()'s must be done very early and must * be done before any interrupt is allowed. */ /* Initialize the interrupt dispatch table c0vec_tbl. */ bcopy((int *)kn220intr_vec, c0vec_tbl, c0vec_tblsize); /* Initialize the spl table for the system we are running on. */ bcopy(kn220iplmask, iplmask, IPLSIZE * sizeof(int)); /* Initialize the interrupt masks for the system we are running on. */ bcopy(kn220splm, splm, (SPLMSIZE) * sizeof(int)); /* Initialize the spl dispatch table and the intr dispatch routine */ spl_init(); /* Change over from console to kernel trap handling; this * is done by changing the BEV bit in the Status Register. */ clear_bev(); /* * Set up the system specific value for "hz", the number of clock * interrupts per second; and corresponding tick and tickadj values. */ hz = cpup->HZ; tick = 1000000 / hz; tickadj = 240000 / (60 * hz); return (0);}/* * Routine to start the 10mS hardclock running. * This is simply to start up the 10mS interval timer so * that it interrupts every 10mS. The interval timer * on KN220 interrupts the R3000 cpu at hardware line 2 (0 being * lowest priority, 5 being highest). When the interrupt handler * reads the vector, the interval timer returns a vector of 0xc0. */kn220startrtclock(){int *tcsr; tcsr = (int *)TCSR; *tcsr = TCSR_IE; return(0);}/* * Routine to stop the 10mS hardclock from interrupting. */kn220stopclocks(){int *tcsr; tcsr = (int *)TCSR; *tcsr = 0; return(0);}/* * The MIPSFAIR2 special register in physical address 0x10084000 * can be read to determine which error condition occurred. Format * of ISR: * bit<3> set if halt requset is posted, * bit<2> set if powerfail, * bit<1> set if CQBIC posts a memory error. * bit<0> Always reads as 1. * * The ISR must have the proper bit cleared to enable subsequent interrupts. * A halt condition is received. This is an interrupt * handler. * */kn220haltintr(ep)int *ep;{ prom_halt(ep);}/* * 1. Memory error by CQBIC or MEM_CTL. * * * Note that multiple bits can be set. For now, arbitrarily handle * the error with the following priority (from high to low): * CQBIC & memory error. * * Parameter: * ep Pointer to exception frame. * */kn220memintr(ep)int *ep;{ int s; /* To clear the memory interrupt we need to write to * locoation 1610005c. The logic on what to do based * on the kind of error is in the general memory error * handler. */ *(int *)PHYS_TO_K1(CLEAR_MEM_INTR) = 0; *(int *)ISR = 0; /* Acknowledge all error */ wbflush(); kn220memerr(ep); /* Clear ISR after returning here */}/* * Pending powerfail, currently ULTRIX has no handling * strategy on VAX and MIPS. Further, there is no restart * parameter block on MIPS. * */kn220powerfail_intr(ep)int *ep;{ printf("Power fail..\n"); DELAY(1000000); /* Delay 1 second, if we are still alive, continue */}/* * Interrupts from Qbus level 7 or 10mS clock. * Level 7 is reserved for Qbus real-time devices. * Currently not used in ULTRIX. */kn220hardintr2(ep)int *ep;{extern int (*(scb[]))();register int vrr;int isr; isr = *(int *)ISR; /* Read content of ISR */ if (isr & ISR_CERR) /* Test for CQBIC mem error */ { kn220_qbus_memerr(ep); } vrr = read_nofault(VRR3); /* Read interrupt vector */ /* 0 = passive release */ vrr &= 0xffff; (*(scb[vrr/4]))(ep,vrr); /* Call the interrupt handler */}/* * Interrupts from NI, DSSI, or Qbus level 6. */kn220hardintr1(ep)int *ep;{extern int (*(scb[]))();register int vrr;int isr; isr = *(int *)ISR; /* Read content of ISR */ if (isr & ISR_CERR) /* Test for CQBIC mem error */ kn220_qbus_memerr(ep); vrr = read_nofault(VRR2); /* Read interrupt vector */ /* 0 = passive release */ vrr &= 0xffff; (*(scb[vrr/4]))(ep,vrr); /* Call the interrupt handler */}/* * Interrupts from the Qbus level 5 and 4, * and from the SSC chip (programmable timers, console). * * VRR0 contains vector for Qbus level 4 & 5, don't read VRR1 for * reason I don't understand. */kn220hardintr0(ep)int *ep;{extern int (*(scb[]))();register int vrr;int isr; isr = *(int *)ISR; /* Read content of ISR */ if (isr & ISR_CERR) /* Test for CQBIC mem errors */ kn220_qbus_memerr(ep); vrr = read_nofault(VRR0); /* Read interrupt vector */ /* 0 = passive release */ vrr &= 0xffff; (*(scb[vrr/4]))(ep,vrr); /* Call the interrupt handler */}/* * Routine to handle trap errors: user-mode ibe & dbe, & all kernel mode traps. * We try to recover from user-mode errors and panic on kernel mode errors. * * A read to non-existent memory will generate an * exception which we need to handle. A write to non-existent * memory location will generate an interupt which we * will need to handle in the interupt routine. */kn220trap_error(ep, code, sr, cause, signo)register u_int *ep; /* exception frame ptr */register u_int code; /* trap code (trap type) */u_int sr, cause; /* status and cause regs */int *signo; /* set if we want to kill process */{ unsigned long pa; /* the physical addr of the error */ int epc; /* the EPC of the error */ int vaddr; /* virt addr of error */ register struct proc *p; /* ptr to current proc struct */ u_long dser; int i; int isr; /* Content of ISR */ isr = *(int *)ISR; /* Read content of ISR */ /* * Log DMA system error register, error address register, ..etc. */ esr[0].esr_dser = * (u_long *)KN220DSER; esr[0].esr_dear = * (u_long *)KN220DEAR; esr[0].esr_qbear = * (u_long *)KN220QBEAR; esr[0].esr_cbtcr = * (u_long *)KN220CBTCR; esr[0].esr_mesr = * (u_long *)KN220MESR; esr[0].esr_mear = * (u_long *)KN220MEAR; /* Clear the error bits */ *(u_long *)KN220DSER = 0xc0bd; *(u_long *)KN220CBTCR = 0xc0000000 | esr[0].esr_cbtcr; /* Compute the physical address. * pa that is load by the R3000 in the execption frame will * be the default address to use. */ pa = vatophys(ep[EF_BADVADDR]); /* If the problem was a memeory error problem the address will be * found in the MEAR register. * * Check the high two bit of the MEAR; if one and only one * of them is set the DESR is invalid but the MESR is valid. * Set the mesr to a valid value to stop us from processing * bad data. * * bit 28 & 29 value meanings * 00 memory space * 11 memory space * 01 I/O space * 10 I/O space * * Also, if bit 1 is set, the address in MEAR is valid. This bit is * needed by the hardware to indicate what kind of cycle it was * processing ... if the contents of the reg. is OK or not. */ if ((esr[0].esr_mear & GOOD_ADDR) == 0) /* DMA Cycle */ { pa = esr[0].esr_mear; if((esr[0].esr_mear & KN220_NXM) == 1) { esr[0].esr_mesr = 0xffffffff; } } else { /* R3000 Cycle */ if((((esr[0].esr_mear & BIT29) == 1)&&((esr[0].esr_mear & BIT28) == 0)) || (((esr[0].esr_mear & BIT29) == 0)&&((esr[0].esr_mear & BIT28) == 1))) { /* I/O Cycle */ esr[0].esr_mesr = 0xffffffff; /* Zap mesr to make ECC Ok*/ } else { /* Memory Cycle */ if((esr[0].esr_mear & KN220_NXM) == 1) esr[0].esr_mesr = 0xffffffff; } } if (USERMODE(sr)) { /* * It is a memory read error: * a) on a private process page, terminate the process * (by setting signo = SIGBUS) * b) on a shared page, crash the system. */ p = u.u_procp; if ( (int)pa != -1 && (btop((int)pa) < physmem) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -