void sunkbd_install_keymaps(ushort **src_key_maps, unsigned int src_keymap_count, char *src_func_buf, char **src_func_table, int src_funcbufsize, int src_funcbufleft, struct kbdiacr *src_accent_table, unsigned int src_accent_table_size) { extern unsigned int keymap_count; int i, j; for (i = 0; i < MAX_NR_KEYMAPS; i++) { if (src_key_maps[i]) { if (!key_maps[i]) { key_maps[i] = (ushort *) sunserial_alloc_bootmem(NR_KEYS * sizeof(ushort)); if (key_maps[i] == NULL) { prom_printf("sunkbd_install_keymaps: " "Cannot alloc key_map(%d).\n", i); prom_halt(); } } for (j = 0; j < NR_KEYS; j++) key_maps[i][j] = src_key_maps[i][j]; } key_maps[i] = src_key_maps[i]; } keymap_count = src_keymap_count; for (i = 0; i < MAX_NR_FUNC; i++) func_table[i] = src_func_table[i]; funcbufptr = src_func_buf; funcbufsize = src_funcbufsize; funcbufleft = src_funcbufleft; for (i = 0; i < MAX_DIACR; i++) accent_table[i] = src_accent_table[i]; accent_table_size = src_accent_table_size; }
static unsigned int sun4c_build_device_irq(struct platform_device *op, unsigned int real_irq) { unsigned int irq; if (real_irq >= 16) { prom_printf("Bogus sun4c IRQ %u\n", real_irq); prom_halt(); } irq = irq_alloc(real_irq, real_irq); if (irq) { unsigned long mask = 0UL; switch (real_irq) { case 1: mask = SUN4C_INT_E1; break; case 8: mask = SUN4C_INT_E8; break; case 10: mask = SUN4C_INT_E10; break; case 14: mask = SUN4C_INT_E14; break; default: break; } irq_set_chip_and_handler_name(irq, &sun4c_irq, handle_level_irq, "level"); irq_set_chip_data(irq, (void *)mask); } return irq; }
static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *)) { int reg_count, irq, cpu; struct linux_prom_registers cnt_regs[PROMREG_MAX]; int obio_node, cnt_node; struct resource r; cnt_node = 0; if((obio_node = prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 || (obio_node = prom_getchild (obio_node)) == 0 || (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) { prom_printf("Cannot find /obio/counter node\n"); prom_halt(); } reg_count = prom_getproperty(cnt_node, "reg", (void *) cnt_regs, sizeof(cnt_regs)); reg_count = (reg_count/sizeof(struct linux_prom_registers)); /* Apply the obio ranges to the timer registers. */ prom_apply_obio_ranges(cnt_regs, reg_count); cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr; cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size; cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io; for(obio_node = 1; obio_node < 4; obio_node++) { cnt_regs[obio_node].phys_addr = cnt_regs[obio_node-1].phys_addr + PAGE_SIZE; cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size; cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io; } memset((char*)&r, 0, sizeof(struct resource)); /* Map the per-cpu Counter registers. */ r.flags = cnt_regs[0].which_io; r.start = cnt_regs[0].phys_addr; sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt"); /* Map the system Counter register. */ /* XXX Here we expect consequent calls to yeld adjusent maps. */ r.flags = cnt_regs[4].which_io; r.start = cnt_regs[4].phys_addr; sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4m_timers->l10_cur_count; master_l10_limit = &sun4m_timers->l10_timer_limit; irq = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); prom_halt(); } if (!cpu_find_by_instance(1, NULL, NULL)) { for(cpu = 0; cpu < 4; cpu++) sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0; sun4m_interrupts->set = SUN4M_INT_E14; } else { sun4m_timers->cpu_timers[0].l14_timer_limit = 0; } #ifdef CONFIG_SMP { unsigned long flags; extern unsigned long lvl14_save[4]; struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; /* For SMP we use the level 14 ticker, however the bootup code * has copied the firmwares level 14 vector into boot cpu's * trap table, we must fix this now or we get squashed. */ local_irq_save(flags); trap_table->inst_one = lvl14_save[0]; trap_table->inst_two = lvl14_save[1]; trap_table->inst_three = lvl14_save[2]; trap_table->inst_four = lvl14_save[3]; local_flush_cache_all(); local_irq_restore(flags); } #endif }
/* * This function does all command procesing for interfacing to gdb. */ void gdb_handle_exception (db_regs_t *raw_regs, int type, int code) { int sigval; long addr, length; char * ptr; struct alpharegs { u_int64_t r[32]; u_int64_t f[32]; u_int64_t pc, vfp; }; static struct alpharegs registers; int i; clear_single_step(raw_regs); bzero(®isters, sizeof registers); /* * Map trapframe to registers. * Ignore float regs for now. */ for (i = 0; i < FRAME_SIZE; i++) if (tf2gdb[i] >= 0) registers.r[tf2gdb[i]] = raw_regs->tf_regs[i]; registers.pc = raw_regs->tf_regs[FRAME_PC]; /* reply to host that an exception has occurred */ sigval = computeSignal (type, code); ptr = remcomOutBuffer; *ptr++ = 'T'; *ptr++ = hexchars[sigval >> 4]; *ptr++ = hexchars[sigval & 0xf]; *ptr++ = hexchars[PC >> 4]; *ptr++ = hexchars[PC & 0xf]; *ptr++ = ':'; ptr = mem2hex ((vm_offset_t)®isters.pc, ptr, 8); *ptr++ = ';'; *ptr++ = hexchars[FP >> 4]; *ptr++ = hexchars[FP & 0xf]; *ptr++ = ':'; ptr = mem2hex ((vm_offset_t)®isters.r[FP], ptr, 8); *ptr++ = ';'; *ptr++ = hexchars[SP >> 4]; *ptr++ = hexchars[SP & 0xf]; *ptr++ = ':'; ptr = mem2hex ((vm_offset_t)®isters.r[SP], ptr, 8); *ptr++ = ';'; *ptr++ = 0; putpacket (remcomOutBuffer); while (1) { remcomOutBuffer[0] = 0; getpacket (remcomInBuffer); switch (remcomInBuffer[0]) { case '?': remcomOutBuffer[0] = 'S'; remcomOutBuffer[1] = hexchars[sigval >> 4]; remcomOutBuffer[2] = hexchars[sigval % 16]; remcomOutBuffer[3] = 0; break; case 'D': /* detach; say OK and turn off gdb */ putpacket(remcomOutBuffer); boothowto &= ~RB_GDB; return; case 'k': prom_halt(); /*NOTREACHED*/ break; case 'g': /* return the value of the CPU registers */ mem2hex ((vm_offset_t)®isters, remcomOutBuffer, NUMREGBYTES); break; case 'G': /* set the value of the CPU registers - return OK */ hex2mem (&remcomInBuffer[1], (vm_offset_t)®isters, NUMREGBYTES); strcpy (remcomOutBuffer, "OK"); break; case 'P': /* Set the value of one register */ { long regno; ptr = &remcomInBuffer[1]; if (hexToInt (&ptr, ®no) && *ptr++ == '=' && regno < NUM_REGS) { hex2mem (ptr, (vm_offset_t)®isters + regno * 8, 8); strcpy(remcomOutBuffer,"OK"); } else strcpy (remcomOutBuffer, "P01"); break; } case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ /* Try to read %x,%x. */ ptr = &remcomInBuffer[1]; if (hexToInt (&ptr, &addr) && *(ptr++) == ',' && hexToInt (&ptr, &length)) { if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL) strcpy (remcomOutBuffer, "E03"); break; } else strcpy (remcomOutBuffer, "E01"); break; case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ /* Try to read '%x,%x:'. */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr,&addr) && *(ptr++) == ',' && hexToInt(&ptr, &length) && *(ptr++) == ':') { if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL) strcpy (remcomOutBuffer, "E03"); else strcpy (remcomOutBuffer, "OK"); } else strcpy (remcomOutBuffer, "E02"); break; /* cAA..AA Continue at address AA..AA(optional) */ /* sAA..AA Step one instruction from AA..AA(optional) */ case 'c' : case 's' : /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcomInBuffer[1]; if (hexToInt(&ptr,&addr)) registers.pc = addr; /* * Map gdb registers back to trapframe (ignoring fp regs). */ for (i = 0; i < NUM_REGS; i++) if (gdb2tf[i] >= 0) raw_regs->tf_regs[gdb2tf[i]] = registers.r[i]; raw_regs->tf_regs[FRAME_PC] = registers.pc; if (remcomInBuffer[0] == 's') if (!set_single_step(raw_regs)) printf("Can't set single step breakpoint\n"); return; } /* switch */ /* reply to the request */ putpacket (remcomOutBuffer); } }
void __init isa_init(void) { struct pci_dev *pdev; unsigned short vendor, device; int index = 0; vendor = PCI_VENDOR_ID_AL; device = PCI_DEVICE_ID_AL_M1533; pdev = NULL; while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) { struct pcidev_cookie *pdev_cookie; struct pci_pbm_info *pbm; struct sparc_isa_bridge *isa_br; int prop_len; pdev_cookie = pdev->sysdata; if (!pdev_cookie) { printk("ISA: Warning, ISA bridge ignored due to " "lack of OBP data.\n"); continue; } pbm = pdev_cookie->pbm; isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL); if (!isa_br) { fatal_err("cannot allocate sparc_isa_bridge"); prom_halt(); } memset(isa_br, 0, sizeof(*isa_br)); /* Link it in. */ isa_br->next = isa_chain; isa_chain = isa_br; isa_br->parent = pbm; isa_br->self = pdev; isa_br->index = index++; isa_br->prom_node = pdev_cookie->prom_node; strncpy(isa_br->prom_name, pdev_cookie->prom_name, sizeof(isa_br->prom_name)); prop_len = prom_getproperty(isa_br->prom_node, "ranges", (char *) isa_br->isa_ranges, sizeof(isa_br->isa_ranges)); if (prop_len <= 0) isa_br->num_isa_ranges = 0; else isa_br->num_isa_ranges = (prop_len / sizeof(struct linux_prom_isa_ranges)); prop_len = prom_getproperty(isa_br->prom_node, "interrupt-map", (char *) isa_br->isa_intmap, sizeof(isa_br->isa_intmap)); if (prop_len <= 0) isa_br->num_isa_intmap = 0; else isa_br->num_isa_intmap = (prop_len / sizeof(struct linux_prom_isa_intmap)); prop_len = prom_getproperty(isa_br->prom_node, "interrupt-map-mask", (char *) &(isa_br->isa_intmask), sizeof(isa_br->isa_intmask)); printk("isa%d:", isa_br->index); isa_fill_devices(isa_br); printk("\n"); } }
void __init sbus_time_init(void) { unsigned int year, mon, day, hour, min, sec; struct mostek48t02 *mregs; #ifdef CONFIG_SUN4 int temp; struct intersil *iregs; #endif BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); if (ARCH_SUN4) sun4_clock_probe(); else clock_probe(); sparc_init_timers(timer_interrupt); #ifdef CONFIG_SUN4 if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { #endif mregs = (struct mostek48t02 *)mstk48t02_regs; if(!mregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } spin_lock_irq(&mostek_lock); mregs->creg |= MSTK_CREG_READ; sec = MSTK_REG_SEC(mregs); min = MSTK_REG_MIN(mregs); hour = MSTK_REG_HOUR(mregs); day = MSTK_REG_DOM(mregs); mon = MSTK_REG_MONTH(mregs); year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); mregs->creg &= ~MSTK_CREG_READ; spin_unlock_irq(&mostek_lock); #ifdef CONFIG_SUN4 } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { /* initialise the intersil on sun4 */ iregs=intersil_clock; if(!iregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } intersil_intr(intersil_clock,INTERSIL_INT_100HZ); disable_pil_irq(10); intersil_stop(iregs); intersil_read_intr(intersil_clock, temp); temp = iregs->clk.int_csec; sec = iregs->clk.int_sec; min = iregs->clk.int_min; hour = iregs->clk.int_hour; day = iregs->clk.int_day; mon = iregs->clk.int_month; year = MSTK_CVT_YEAR(iregs->clk.int_year); enable_pil_irq(10); intersil_start(iregs); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec); } #endif /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */ local_irq_enable(); }
void __init fill_ebus_device(int node, struct linux_ebus_device *dev) { struct linux_prom_registers regs[PROMREG_MAX]; struct linux_ebus_child *child; int irqs[PROMINTR_MAX]; int i, n, len; dev->prom_node = node; prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); printk(" [%s", dev->prom_name); len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", dev->prom_name, len, (int)sizeof(struct linux_prom_registers)); prom_halt(); } dev->num_addrs = len / sizeof(struct linux_prom_registers); for (i = 0; i < dev->num_addrs; i++) { n = (regs[i].which_io - 0x10) >> 2; dev->resource[i].start = dev->bus->self->resource[n].start; dev->resource[i].start += (unsigned long)regs[i].phys_addr; dev->resource[i].end = (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); dev->resource[i].flags = IORESOURCE_MEM; dev->resource[i].name = dev->prom_name; request_resource(&dev->bus->self->resource[n], &dev->resource[i]); } len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); if ((len == -1) || (len == 0)) { dev->num_irqs = 0; } else { dev->num_irqs = len / sizeof(irqs[0]); for (i = 0; i < dev->num_irqs; i++) { struct pci_pbm_info *pbm = dev->bus->parent; struct pci_controller_info *p = pbm->parent; if (ebus_intmap_match(dev->bus, ®s[0], &irqs[i]) != -1) { dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]); } else { /* If we get a bogus interrupt property, just * record the raw value instead of punting. */ dev->irqs[i] = irqs[i]; } } } if ((node = prom_getchild(node))) { printk(" ->"); dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); child = dev->children; child->next = 0; child->parent = dev; child->bus = dev->bus; fill_ebus_child(node, ®s[0], child, child_regs_nonstandard(dev)); while ((node = prom_getsibling(node))) { child->next = ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = 0; child->parent = dev; child->bus = dev->bus; fill_ebus_child(node, ®s[0], child, child_regs_nonstandard(dev)); } } printk("]"); }
void __init iommu_init(int iommund, struct sbus_bus *sbus) { unsigned int impl, vers; unsigned long tmp; struct iommu_struct *iommu; struct linux_prom_registers iommu_promregs[PROMREG_MAX]; struct resource r; unsigned long *bitmap; iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); if (!iommu) { prom_printf("Unable to allocate iommu structure\n"); prom_halt(); } prom_getproperty(iommund, "reg", (void *) iommu_promregs, sizeof(iommu_promregs)); memset(&r, 0, sizeof(r)); r.flags = iommu_promregs[0].which_io; r.start = iommu_promregs[0].phys_addr; iommu->regs = (struct iommu_regs *) sbus_ioremap(&r, 0, PAGE_SIZE * 3, "iommu_regs"); if(!iommu->regs) { prom_printf("Cannot map IOMMU registers\n"); prom_halt(); } impl = (iommu->regs->control & IOMMU_CTRL_IMPL) >> 28; vers = (iommu->regs->control & IOMMU_CTRL_VERS) >> 24; tmp = iommu->regs->control; tmp &= ~(IOMMU_CTRL_RNGE); tmp |= (IOMMU_RNGE_256MB | IOMMU_CTRL_ENAB); iommu->regs->control = tmp; iommu_invalidate(iommu->regs); iommu->start = IOMMU_START; iommu->end = 0xffffffff; /* Allocate IOMMU page table */ /* Stupid alignment constraints give me a headache. We need 256K or 512K or 1M or 2M area aligned to its size and current gfp will fortunately give it to us. */ tmp = __get_free_pages(GFP_KERNEL, IOMMU_ORDER); if (!tmp) { prom_printf("Unable to allocate iommu table [0x%08x]\n", IOMMU_NPTES*sizeof(iopte_t)); prom_halt(); } iommu->page_table = (iopte_t *)tmp; /* Initialize new table. */ memset(iommu->page_table, 0, IOMMU_NPTES*sizeof(iopte_t)); flush_cache_all(); flush_tlb_all(); iommu->regs->base = __pa((unsigned long) iommu->page_table) >> 4; iommu_invalidate(iommu->regs); bitmap = kmalloc(IOMMU_NPTES>>3, GFP_KERNEL); if (!bitmap) { prom_printf("Unable to allocate iommu bitmap [%d]\n", (int)(IOMMU_NPTES>>3)); prom_halt(); }
static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) { unsigned long address, base; int len; sdev->prom_node = prom_node; prom_getstring(prom_node, "name", sdev->prom_name, sizeof(sdev->prom_name)); address = prom_getint(prom_node, "address"); len = prom_getproperty(prom_node, "reg", (char *) sdev->reg_addrs, sizeof(sdev->reg_addrs)); if (len == -1) { sdev->num_registers = 0; goto no_regs; } if (len % sizeof(struct linux_prom_registers)) { prom_printf("fill_sbus_device: proplen for regs of %s " " was %d, need multiple of %d\n", sdev->prom_name, len, (int) sizeof(struct linux_prom_registers)); prom_halt(); } if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) { prom_printf("fill_sbus_device: Too many register properties " "for device %s, len=%d\n", sdev->prom_name, len); prom_halt(); } sdev->num_registers = len / sizeof(struct linux_prom_registers); sdev->ranges_applied = 0; base = (unsigned long) sdev->reg_addrs[0].phys_addr; /* Compute the slot number. */ if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) { sdev->slot = sbus_dev_slot(base); } else { sdev->slot = sdev->reg_addrs[0].which_io; } no_regs: len = prom_getproperty(prom_node, "ranges", (char *)sdev->device_ranges, sizeof(sdev->device_ranges)); if (len == -1) { sdev->num_device_ranges = 0; goto no_ranges; } if (len % sizeof(struct linux_prom_ranges)) { prom_printf("fill_sbus_device: proplen for ranges of %s " " was %d, need multiple of %d\n", sdev->prom_name, len, (int) sizeof(struct linux_prom_ranges)); prom_halt(); } if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) { prom_printf("fill_sbus_device: Too many range properties " "for device %s, len=%d\n", sdev->prom_name, len); prom_halt(); } sdev->num_device_ranges = len / sizeof(struct linux_prom_ranges); no_ranges: /* XXX Unfortunately, IRQ issues are very arch specific. * XXX Pull this crud out into an arch specific area * XXX at some point. -DaveM */ #ifdef __sparc_v9__ len = prom_getproperty(prom_node, "interrupts", (char *) irqs, sizeof(irqs)); if (len == -1 || len == 0) { sdev->irqs[0] = 0; sdev->num_irqs = 0; } else { unsigned int pri = irqs[0].pri; sdev->num_irqs = 1; if (pri < 0x20) pri += sdev->slot * 8; sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); } #else len = prom_getproperty(prom_node, "intr", (char *)irqs, sizeof(irqs)); if (len == -1) len = 0; sdev->num_irqs = len / 8; if (sdev->num_irqs == 0) { sdev->irqs[0] = 0; } else if (sparc_cpu_model == sun4d) { extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); for (len = 0; len < sdev->num_irqs; len++) sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri); } else { for (len = 0; len < sdev->num_irqs; len++) sdev->irqs[len] = irqs[len].pri; } #endif /* !__sparc_v9__ */ }
/* * On sun4ms we have to do some nasty stuff here. We need to map * in the interrupt registers (since we need to find out where * they are from the PROM, since they aren't in a fixed place), and * disable all interrupts. We can't do this easily from locore * since the PROM is ugly to use from assembly. We also need to map * in the counter registers because we can't disable the level 14 * (statclock) interrupt, so we need a handler early on (ugh). * * NOTE: We *demand* the psl to stay at splhigh() at least until * we get here. The system _cannot_ take interrupts until we map * the interrupt registers. */ static void bootstrap4m(void) { int node; int nvaddrs, *vaddrs, vstore[10]; u_int pte; int i; extern void setpte4m(u_int, u_int); if ((node = prom_opennode("/obio/interrupt")) == 0 && (node = prom_finddevice("/obio/interrupt")) == 0) panic("bootstrap: could not get interrupt " "node from prom"); vaddrs = vstore; nvaddrs = sizeof(vstore)/sizeof(vstore[0]); if (prom_getprop(node, "address", sizeof(int), &nvaddrs, &vaddrs) != 0) { printf("bootstrap: could not get interrupt properties"); prom_halt(); } if (nvaddrs < 2 || nvaddrs > 5) { printf("bootstrap: cannot handle %d interrupt regs\n", nvaddrs); prom_halt(); } for (i = 0; i < nvaddrs - 1; i++) { pte = getpte4m((u_int)vaddrs[i]); if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) { panic("bootstrap: PROM has invalid mapping for " "processor interrupt register %d",i); prom_halt(); } pte |= PPROT_S; /* Duplicate existing mapping */ setpte4m(PI_INTR_VA + (_MAXNBPG * i), pte); } cpuinfo.intreg_4m = (struct icr_pi *) (PI_INTR_VA + (_MAXNBPG * CPU_MID2CPUNO(bootmid))); /* * That was the processor register...now get system register; * it is the last returned by the PROM */ pte = getpte4m((u_int)vaddrs[i]); if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) panic("bootstrap: PROM has invalid mapping for system " "interrupt register"); pte |= PPROT_S; setpte4m(SI_INTR_VA, pte); /* Now disable interrupts */ icr_si_bis(SINTR_MA); /* Send all interrupts to primary processor */ *((u_int *)ICR_ITR) = CPU_MID2CPUNO(bootmid); #ifdef DEBUG /* printf("SINTR: mask: 0x%x, pend: 0x%x\n", *(int*)ICR_SI_MASK, *(int*)ICR_SI_PEND); */ #endif }
__initfunc(void auxio_probe(void)) { struct linux_sbus *bus; struct linux_sbus_device *sdev = 0; struct linux_prom_registers auxregs[1]; for_each_sbus(bus) { for_each_sbusdev(sdev, bus) { if(!strcmp(sdev->prom_name, "auxio")) { break; } } } if (!sdev) { #ifdef CONFIG_PCI struct linux_ebus *ebus; struct linux_ebus_device *edev = 0; unsigned long led_auxio; for_each_ebus(ebus) { for_each_ebusdev(edev, ebus) { if (!strcmp(edev->prom_name, "auxio")) goto ebus_done; } } ebus_done: if (edev) { if (check_region(edev->base_address[0], sizeof(unsigned int))) { prom_printf("%s: Can't get region %lx, %d\n", __FUNCTION__, edev->base_address[0], sizeof(unsigned int)); prom_halt(); } request_region(edev->base_address[0], sizeof(unsigned int), "LED auxio"); led_auxio = edev->base_address[0]; outl(0x01, led_auxio); return; } #endif if(central_bus) { auxio_register = NULL; return; } prom_printf("Cannot find auxio node, cannot continue...\n"); prom_halt(); } prom_getproperty(sdev->prom_node, "reg", (char *) auxregs, sizeof(auxregs)); prom_apply_sbus_ranges(sdev->my_bus, auxregs, 0x1, sdev); /* Map the register both read and write */ auxio_register = (unsigned char *) sparc_alloc_io(auxregs[0].phys_addr, 0, auxregs[0].reg_size, "auxiliaryIO", auxregs[0].which_io, 0x0); TURN_ON_LED; }
__initfunc(static void sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *))) { int reg_count, irq, cpu; struct linux_prom_registers cnt_regs[PROMREG_MAX]; int obio_node, cnt_node; cnt_node = 0; if((obio_node = prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 || (obio_node = prom_getchild (obio_node)) == 0 || (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) { prom_printf("Cannot find /obio/counter node\n"); prom_halt(); } reg_count = prom_getproperty(cnt_node, "reg", (void *) cnt_regs, sizeof(cnt_regs)); reg_count = (reg_count/sizeof(struct linux_prom_registers)); /* Apply the obio ranges to the timer registers. */ prom_apply_obio_ranges(cnt_regs, reg_count); cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr; cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size; cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io; for(obio_node = 1; obio_node < 4; obio_node++) { cnt_regs[obio_node].phys_addr = cnt_regs[obio_node-1].phys_addr + PAGE_SIZE; cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size; cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io; } /* Map the per-cpu Counter registers. */ sun4m_timers = sparc_alloc_io(cnt_regs[0].phys_addr, 0, PAGE_SIZE*NCPUS, "counters_percpu", cnt_regs[0].which_io, 0x0); /* Map the system Counter register. */ sparc_alloc_io(cnt_regs[4].phys_addr, 0, cnt_regs[4].reg_size, "counters_system", cnt_regs[4].which_io, 0x0); sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4m_timers->l10_cur_count; master_l10_limit = &sun4m_timers->l10_timer_limit; irq = request_irq(TIMER_IRQ, counter_fn, (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); prom_halt(); } if(linux_num_cpus > 1) { for(cpu = 0; cpu < 4; cpu++) sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0; sun4m_interrupts->set = SUN4M_INT_E14; } else { sun4m_timers->cpu_timers[0].l14_timer_limit = 0; } #ifdef __SMP__ { unsigned long flags; extern unsigned long lvl14_save[4]; struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; /* For SMP we use the level 14 ticker, however the bootup code * has copied the firmwares level 14 vector into boot cpu's * trap table, we must fix this now or we get squashed. */ __save_and_cli(flags); trap_table->inst_one = lvl14_save[0]; trap_table->inst_two = lvl14_save[1]; trap_table->inst_three = lvl14_save[2]; trap_table->inst_four = lvl14_save[3]; local_flush_cache_all(); __restore_flags(flags); } #endif }
__initfunc(static void should_not_happen(void)) { prom_printf(shouldnothappen); prom_halt(); }
static void __init read_obp_memory(const char *property, struct linux_prom64_registers *regs, int *num_ents) { int node = prom_finddevice("/memory"); int prop_size = prom_getproplen(node, property); int ents, ret, i; ents = prop_size / sizeof(struct linux_prom64_registers); if (ents > MAX_BANKS) { prom_printf("The machine has more %s property entries than " "this kernel can support (%d).\n", property, MAX_BANKS); prom_halt(); } ret = prom_getproperty(node, property, (char *) regs, prop_size); if (ret == -1) { prom_printf("Couldn't get %s property from /memory.\n"); prom_halt(); } /* Sanitize what we got from the firmware, by page aligning * everything. */ for (i = 0; i < ents; i++) { unsigned long base, size; base = regs[i].phys_addr; size = regs[i].reg_size; size &= PAGE_MASK; if (base & ~PAGE_MASK) { unsigned long new_base = PAGE_ALIGN(base); size -= new_base - base; if ((long) size < 0L) size = 0UL; base = new_base; } regs[i].phys_addr = base; regs[i].reg_size = size; } for (i = 0; i < ents; i++) { if (regs[i].reg_size == 0UL) { int j; for (j = i; j < ents - 1; j++) { regs[j].phys_addr = regs[j+1].phys_addr; regs[j].reg_size = regs[j+1].reg_size; } ents--; i--; } } *num_ents = ents; sort(regs, ents, sizeof(struct linux_prom64_registers), cmp_p64, NULL); }
void __init sun4m_init_IRQ(void) { int ie_node,i; struct linux_prom_registers int_regs[PROMREG_MAX]; int num_regs; struct resource r; int mid; local_irq_disable(); if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 || (ie_node = prom_getchild (ie_node)) == 0 || (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) { prom_printf("Cannot find /obio/interrupt node\n"); prom_halt(); } num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs, sizeof(int_regs)); num_regs = (num_regs/sizeof(struct linux_prom_registers)); /* Apply the obio ranges to these registers. */ prom_apply_obio_ranges(int_regs, num_regs); int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr; int_regs[4].reg_size = int_regs[num_regs-1].reg_size; int_regs[4].which_io = int_regs[num_regs-1].which_io; for(ie_node = 1; ie_node < 4; ie_node++) { int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE; int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size; int_regs[ie_node].which_io = int_regs[ie_node-1].which_io; } memset((char *)&r, 0, sizeof(struct resource)); /* Map the interrupt registers for all possible cpus. */ r.flags = int_regs[0].which_io; r.start = int_regs[0].phys_addr; sun4m_interrupts = (struct sun4m_intregs *) sbus_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); /* Map the system interrupt control registers. */ r.flags = int_regs[4].which_io; r.start = int_regs[4].phys_addr; sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); sun4m_interrupts->set = ~SUN4M_INT_MASKALL; for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) sun4m_interrupts->cpu_intregs[mid].clear = ~0x17fff; if (!cpu_find_by_instance(1, NULL, NULL)) { /* system wide interrupts go to cpu 0, this should always * be safe because it is guaranteed to be fitted or OBP doesn't * come up * * Not sure, but writing here on SLAVIO systems may puke * so I don't do it unless there is more than 1 cpu. */ irq_rcvreg = (unsigned long *) &sun4m_interrupts->undirected_target; sun4m_interrupts->undirected_target = 0; } BTFIXUPSET_CALL(sbint_to_irq, sun4m_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); sparc_init_timers = sun4m_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM); #endif /* Cannot enable interrupts until OBP ticker is disabled. */ }
void main(void *ofw) { int boothowto, i = 0, isfloppy, kboothowto; char kernel[PROM_MAX_PATH]; char bootline[PROM_MAX_PATH]; /* Initialize OpenFirmware */ romp = ofw; prom_init(); printf("\r>> %s, Revision %s\n", bootprog_name, bootprog_rev); /* Figure boot arguments */ strncpy(bootdev, prom_getbootpath(), sizeof(bootdev) - 1); kboothowto = boothowto = bootoptions(prom_getbootargs(), bootdev, kernel, bootline); isfloppy = bootdev_isfloppy(bootdev); for (;; *kernel = '\0') { if (boothowto & RB_ASKNAME) { char cmdline[PROM_MAX_PATH]; printf("Boot: "); kgets(cmdline, sizeof(cmdline)); if (!strcmp(cmdline,"exit") || !strcmp(cmdline,"halt")) { prom_halt(); } else if (!strcmp(cmdline, "?") || !strcmp(cmdline, "help")) { help(); continue; } boothowto = bootoptions(cmdline, bootdev, kernel, bootline); boothowto |= RB_ASKNAME; i = 0; } if (*kernel == '\0') { if (kernelnames[i] == NULL) { boothowto |= RB_ASKNAME; continue; } strncpy(kernel, kernelnames[i++], PROM_MAX_PATH); } else if (i == 0) { /* * Kernel name was passed via command line -- ask user * again if requested image fails to boot. */ boothowto |= RB_ASKNAME; } check_boot_config(); start_kernel(kernel, bootline, ofw, isfloppy, kboothowto); /* * Try next name from kernel name list if not in askname mode, * enter askname on reaching list's end. */ if ((boothowto & RB_ASKNAME) == 0 && (kernelnames[i] != NULL)) { printf(": trying %s...\n", kernelnames[i]); } else { printf("\n"); boothowto |= RB_ASKNAME; } } (void)printf("Boot failed! Exiting to the Firmware.\n"); prom_halt(); }
void __init sbus_init(void) { int nd, this_sbus, sbus_devs, topnd, iommund; unsigned int sbus_clock; struct sbus_bus *sbus; struct sbus_dev *this_dev; int num_sbus = 0; /* How many did we find? */ #ifndef __sparc_v9__ register_proc_sparc_ioport(); #endif #ifdef CONFIG_SUN4 return sun4_dvma_init(); #endif topnd = prom_getchild(prom_root_node); /* Finding the first sbus is a special case... */ iommund = 0; if(sparc_cpu_model == sun4u) { nd = prom_searchsiblings(topnd, "sbus"); if(nd == 0) { #ifdef CONFIG_PCI if (!pcibios_present()) { prom_printf("Neither SBUS nor PCI found.\n"); prom_halt(); } else { #ifdef __sparc_v9__ firetruck_init(); #endif } return; #else prom_printf("YEEE, UltraSparc sbus not found\n"); prom_halt(); #endif } } else if(sparc_cpu_model == sun4d) { if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 || (nd = prom_getchild(iommund)) == 0 || (nd = prom_searchsiblings(nd, "sbi")) == 0) { panic("sbi not found"); } } else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) { if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 || (nd = prom_getchild(iommund)) == 0 || (nd = prom_searchsiblings(nd, "sbus")) == 0) { #ifdef CONFIG_PCI if (!pcibios_present()) { prom_printf("Neither SBUS nor PCI found.\n"); prom_halt(); } return; #else /* No reason to run further - the data access trap will occur. */ panic("sbus not found"); #endif } } /* Ok, we've found the first one, allocate first SBus struct * and place in chain. */ sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); sbus->next = NULL; sbus->prom_node = nd; this_sbus = nd; if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d) iommu_init(iommund, sbus); /* Loop until we find no more SBUS's */ while(this_sbus) { #ifdef __sparc_v9__ /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */ if(sparc_cpu_model == sun4u) { extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus); sbus_iommu_init(this_sbus, sbus); } #endif #ifndef __sparc_v9__ if (sparc_cpu_model == sun4d) iounit_init(this_sbus, iommund, sbus); #endif printk("sbus%d: ", num_sbus); sbus_clock = prom_getint(this_sbus, "clock-frequency"); if(sbus_clock == -1) sbus_clock = (25*1000*1000); printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), (int) (((sbus_clock/1000)%1000 != 0) ? (((sbus_clock/1000)%1000) + 1000) : 0)); prom_getstring(this_sbus, "name", sbus->prom_name, sizeof(sbus->prom_name)); sbus->clock_freq = sbus_clock; #ifndef __sparc_v9__ if (sparc_cpu_model == sun4d) { sbus->devid = prom_getint(iommund, "device-id"); sbus->board = prom_getint(iommund, "board#"); } #endif sbus_bus_ranges_init(iommund, sbus); sbus_devs = prom_getchild(this_sbus); if (!sbus_devs) { sbus->devices = NULL; goto next_bus; } sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); this_dev = sbus->devices; this_dev->next = NULL; this_dev->bus = sbus; this_dev->parent = NULL; fill_sbus_device(sbus_devs, this_dev); /* Should we traverse for children? */ if(prom_getchild(sbus_devs)) { /* Allocate device node */ this_dev->child = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); /* Fill it */ this_dev->child->bus = sbus; this_dev->child->next = 0; fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); sbus_do_child_siblings(prom_getchild(sbus_devs), this_dev->child, this_dev, sbus); } else { this_dev->child = NULL; } while((sbus_devs = prom_getsibling(sbus_devs)) != 0) { /* Allocate device node */ this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); this_dev = this_dev->next; this_dev->next = NULL; /* Fill it */ this_dev->bus = sbus; this_dev->parent = NULL; fill_sbus_device(sbus_devs, this_dev); /* Is there a child node hanging off of us? */ if(prom_getchild(sbus_devs)) { /* Get new device struct */ this_dev->child = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC); /* Fill it */ this_dev->child->bus = sbus; this_dev->child->next = 0; fill_sbus_device(prom_getchild(sbus_devs), this_dev->child); sbus_do_child_siblings(prom_getchild(sbus_devs), this_dev->child, this_dev, sbus); } else { this_dev->child = NULL; } } /* Walk all devices and apply parent ranges. */ sbus_fixup_all_regs(sbus->devices); dvma_init(sbus); next_bus: num_sbus++; if(sparc_cpu_model == sun4u) { this_sbus = prom_getsibling(this_sbus); if(!this_sbus) break; this_sbus = prom_searchsiblings(this_sbus, "sbus"); } else if(sparc_cpu_model == sun4d) { iommund = prom_getsibling(iommund); if(!iommund) break; iommund = prom_searchsiblings(iommund, "io-unit"); if(!iommund) break; this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi"); } else { this_sbus = prom_getsibling(this_sbus); if(!this_sbus) break; this_sbus = prom_searchsiblings(this_sbus, "sbus"); } if(this_sbus) { sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC); sbus = sbus->next; sbus->next = NULL; sbus->prom_node = this_sbus; } else { break; } } /* while(this_sbus) */ if (sparc_cpu_model == sun4d) { extern void sun4d_init_sbi_irq(void); sun4d_init_sbi_irq(); } rs_init(); #ifdef __sparc_v9__ if (sparc_cpu_model == sun4u) { firetruck_init(); } #endif #ifdef CONFIG_SUN_AUXIO if (sparc_cpu_model == sun4u) auxio_probe (); #endif #ifdef __sparc_v9__ if (sparc_cpu_model == sun4u) { extern void clock_probe(void); clock_probe(); } #endif }
void __init prom_init(void *cif_handler, void *cif_stack) { char buffer[80], *p; int ints[3]; int node; int i = 0; int bufadjust; prom_vers = PROM_P1275; prom_cif_init(cif_handler, cif_stack); prom_root_node = prom_getsibling(0); if((prom_root_node == 0) || (prom_root_node == -1)) prom_halt(); prom_chosen_node = prom_finddevice("/chosen"); if (!prom_chosen_node || prom_chosen_node == -1) prom_halt(); prom_stdin = prom_getint (prom_chosen_node, "stdin"); prom_stdout = prom_getint (prom_chosen_node, "stdout"); node = prom_finddevice("/openprom"); if (!node || node == -1) prom_halt(); prom_getstring (node, "version", buffer, sizeof (buffer)); prom_printf ("\n"); if (strncmp (buffer, "OBP ", 4)) goto strange_version; /* * Version field is expected to be 'OBP xx.yy.zz date...' * However, Sun can't stick to this format very well, so * we need to check for 'OBP xx.yy.zz date...' and adjust * accordingly. -spot */ if (strncmp (buffer, "OBP ", 5)) bufadjust = 4; else bufadjust = 5; p = buffer + bufadjust; while (p && isdigit(*p) && i < 3) { ints[i++] = simple_strtoul(p, NULL, 0); if ((p = strchr(p, '.')) != NULL) p++; } if (i != 3) goto strange_version; prom_rev = ints[1]; prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2]; printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust); prom_meminit(); /* Initialization successful. */ return; strange_version: prom_printf ("Strange OBP version `%s'.\n", buffer); prom_halt (); }
__initfunc(void pcic_probe(void)) { struct linux_prom_registers regs[PROMREG_MAX]; struct linux_pbm_info* pbm; char namebuf[64]; int node; int err; if (pcibios_present()) { prom_printf("PCIC: called twice!\n"); prom_halt(); } node = prom_getchild (prom_root_node); node = prom_searchsiblings (node, "pci"); if (node == 0) return; /* * Map in PCIC register set, config space, and IO base */ err = prom_getproperty(node, "reg", (char*)regs, sizeof(regs)); if (err == 0 || err == -1) { prom_printf("PCIC: Error, cannot get PCIC registers " "from PROM.\n"); prom_halt(); } pcic = &PCIC; pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL, regs[0].reg_size, "PCIC Registers", 0, 0); if (!pcic->pcic_regs) { prom_printf("PCIC: Error, cannot map PCIC registers.\n"); prom_halt(); } pcic->pcic_io_phys = regs[1].phys_addr; pcic->pcic_io = (unsigned long)sparc_alloc_io(regs[1].phys_addr, NULL, regs[1].reg_size, "PCIC IO Base", 0, 0); if (pcic->pcic_io == 0UL) { prom_printf("PCIC: Error, cannot map PCIC IO Base.\n"); prom_halt(); } pcic->pcic_config_space_addr = (unsigned long)sparc_alloc_io (regs[2].phys_addr, NULL, regs[2].reg_size * 2, "PCI Config Space Address", 0, 0); if (pcic->pcic_config_space_addr == 0UL) { prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Address.\n"); prom_halt(); } /* * Docs say three least significant bits in address and data * must be the same. Thus, we need adjust size of data. */ pcic->pcic_config_space_data = (unsigned long)sparc_alloc_io (regs[3].phys_addr, NULL, regs[3].reg_size * 2, "PCI Config Space Data", 0, 0); if (pcic->pcic_config_space_data == 0UL) { prom_printf("PCIC: Error, cannot map" "PCI Configuration Space Data.\n"); prom_halt(); } pbm = &pcic->pbm; pbm->prom_node = node; prom_getstring(node, "name", namebuf, sizeof(namebuf)); strcpy(pbm->prom_name, namebuf); }
__initfunc(void prom_init(struct linux_romvec *rp)) { #ifdef CONFIG_SUN4 extern struct linux_romvec *sun4_prom_init(void); rp = sun4_prom_init(); #endif #if CONFIG_AP1000 extern struct linux_romvec *ap_prom_init(void); rp = ap_prom_init(); #endif romvec = rp; switch(romvec->pv_romvers) { case 0: prom_vers = PROM_V0; break; case 2: prom_vers = PROM_V2; break; case 3: prom_vers = PROM_V3; break; case 40: prom_vers = PROM_SUN4; break; case 42: /* why not :-) */ prom_vers = PROM_AP1000; break; default: prom_printf("PROMLIB: Bad PROM version %d\n", romvec->pv_romvers); prom_halt(); break; }; prom_rev = romvec->pv_plugin_revision; prom_prev = romvec->pv_printrev; prom_nodeops = romvec->pv_nodeops; prom_root_node = prom_getsibling(0); if((prom_root_node == 0) || (prom_root_node == -1)) prom_halt(); if((((unsigned long) prom_nodeops) == 0) || (((unsigned long) prom_nodeops) == -1)) prom_halt(); if(prom_vers == PROM_V2 || prom_vers == PROM_V3) { prom_stdout = *romvec->pv_v2bootargs.fd_stdout; prom_stdin = *romvec->pv_v2bootargs.fd_stdin; } prom_meminit(); prom_ranges_init(); #ifndef CONFIG_SUN4 /* SUN4 prints this in sun4_prom_init */ printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n", romvec->pv_romvers, prom_rev); #endif /* Initialization successful. */ return; }
static void __init should_not_happen(void) { prom_printf(shouldnothappen); prom_halt(); }
void cpu_reboot(volatile int howto, char *bootstr) { /* take a snap shot before clobbering any registers */ savectx(curpcb); #ifdef DEBUG if (panicstr) stacktrace(); #endif /* If system is cold, just halt. */ if (cold) { howto |= RB_HALT; goto haltsys; } /* If "always halt" was specified as a boot flag, obey. */ if ((boothowto & RB_HALT) != 0) howto |= RB_HALT; boothowto = howto; if ((howto & RB_NOSYNC) == 0 && waittime < 0) { /* * Synchronize the disks.... */ waittime = 0; vfs_shutdown(); /* * If we've been adjusting the clock, the todr * will be out of synch; adjust it now. */ resettodr(); } /* Disable interrupts. */ disable_intr(); splhigh(); /* If rebooting and a dump is requested do it. */ #if 0 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) #else if (howto & RB_DUMP) #endif dumpsys(); haltsys: /* run any shutdown hooks */ doshutdownhooks(); pmf_system_shutdown(boothowto); if ((howto & RB_POWERDOWN) == RB_POWERDOWN) prom_halt(0x80); /* rom monitor RB_PWOFF */ /* Finally, halt/reboot the system. */ printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); prom_halt(howto & RB_HALT); /*NOTREACHED*/ }
/* Probe for the mostek real time clock chip. */ static __inline__ void clock_probe(void) { struct linux_prom_registers clk_reg[2]; char model[128]; register int node, cpuunit, bootbus; struct resource r; cpuunit = bootbus = 0; memset(&r, 0, sizeof(r)); /* Determine the correct starting PROM node for the probe. */ node = prom_getchild(prom_root_node); switch (sparc_cpu_model) { case sun4c: break; case sun4m: node = prom_getchild(prom_searchsiblings(node, "obio")); break; case sun4d: node = prom_getchild(bootbus = prom_searchsiblings(prom_getchild(cpuunit = prom_searchsiblings(node, "cpu-unit")), "bootbus")); break; default: prom_printf("CLOCK: Unsupported architecture!\n"); prom_halt(); } /* Find the PROM node describing the real time clock. */ sp_clock_typ = MSTK_INVALID; node = prom_searchsiblings(node,"eeprom"); if (!node) { prom_printf("CLOCK: No clock found!\n"); prom_halt(); } /* Get the model name and setup everything up. */ model[0] = '\0'; prom_getstring(node, "model", model, sizeof(model)); if (strcmp(model, "mk48t02") == 0) { sp_clock_typ = MSTK48T02; if (prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) { prom_printf("clock_probe: FAILED!\n"); prom_halt(); } if (sparc_cpu_model == sun4d) prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); else prom_apply_obio_ranges(clk_reg, 1); /* Map the clock register io area read-only */ r.flags = clk_reg[0].which_io; r.start = clk_reg[0].phys_addr; mstk48t02_regs = sbus_ioremap(&r, 0, sizeof(struct mostek48t02), "mk48t02"); mstk48t08_regs = NULL; /* To catch weirdness */ } else if (strcmp(model, "mk48t08") == 0) { sp_clock_typ = MSTK48T08; if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) { prom_printf("clock_probe: FAILED!\n"); prom_halt(); } if (sparc_cpu_model == sun4d) prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1); else prom_apply_obio_ranges(clk_reg, 1); /* Map the clock register io area read-only */ /* XXX r/o attribute is somewhere in r.flags */ r.flags = clk_reg[0].which_io; r.start = clk_reg[0].phys_addr; mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0, sizeof(struct mostek48t08), "mk48t08"); mstk48t02_regs = &mstk48t08_regs->regs; } else { prom_printf("CLOCK: Unknown model name '%s'\n",model); prom_halt(); } /* Report a low battery voltage condition. */ if (has_low_battery()) printk(KERN_CRIT "NVRAM: Low battery voltage!\n"); /* Kick start the clock if it is completely stopped. */ if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) kick_start_clock(); }
char __init *cgthreefb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; struct sbus_dev *sdev = fb->sbdp; unsigned long phys = sdev->reg_addrs[0].phys_addr; int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL; #ifndef FBCON_HAS_CFB8 return NULL; #endif if (!fb->s.cg3.regs) { fb->s.cg3.regs = (struct cg3_regs *) sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET, sizeof(struct cg3_regs), "cg3 regs"); if (cgRDI) { char buffer[40]; char *p; int ww, hh; *buffer = 0; prom_getstring (fb->prom_node, "params", buffer, sizeof(buffer)); if (*buffer) { ww = simple_strtoul (buffer, &p, 10); if (ww && *p == 'x') { hh = simple_strtoul (p + 1, &p, 10); if (hh && *p == '-') { if (type->fb_width != ww || type->fb_height != hh) { type->fb_width = ww; type->fb_height = hh; return SBUSFBINIT_SIZECHANGE; } } } } } } strcpy(fb->info.modename, "CGthree"); strcpy(fix->id, "CGthree"); fix->line_length = fb->var.xres_virtual; fix->accel = FB_ACCEL_SUN_CGTHREE; disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) { disp->screen_base = (char *) sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET, type->fb_size, "cg3 ram"); } disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->dispsw = fbcon_cfb8; fb->margins = cg3_margins; fb->loadcmap = cg3_loadcmap; fb->blank = cg3_blank; fb->unblank = cg3_unblank; fb->physbase = phys; fb->mmap_map = cg3_mmap_map; #ifdef __sparc_v9__ sprintf(idstring, "%s at %016lx", cgRDI ? "cgRDI" : "cgthree", phys); #else sprintf(idstring, "%s at %x.%08lx", cgRDI ? "cgRDI" : "cgthree", fb->iospace, phys); #endif if (!prom_getbool(fb->prom_node, "width")) { /* Ugh, broken PROM didn't initialize us. * Let's deal with this ourselves. */ enum cg3_type type; u8 *p; if (cgRDI) type = CG3_RDI; else { u8 status = sbus_readb(&fb->s.cg3.regs->status), mon; if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) { mon = status & CG3_SR_RES_MASK; if (mon == CG3_SR_1152_900_76_A || mon == CG3_SR_1152_900_76_B) type = CG3_AT_76HZ; else type = CG3_AT_66HZ; } else { prom_printf("cgthree: can't handle SR %02x\n", status); prom_halt(); return NULL; /* fool gcc. */ } } for (p = cg3_regvals[type]; *p; p += 2) { u8 *regp = &((u8 *)fb->s.cg3.regs)[p[0]]; sbus_writeb(p[1], regp); } for (p = cg3_dacvals; *p; p += 2) { volatile u8 *regp; regp = (volatile u8 *)&fb->s.cg3.regs->cmap.addr; sbus_writeb(p[0], regp); regp = (volatile u8 *)&fb->s.cg3.regs->cmap.control; sbus_writeb(p[1], regp); } } return idstring; }
__initfunc(void ebus_init(void)) { struct linux_prom_pci_registers regs[PROMREG_MAX]; struct linux_pbm_info *pbm; struct linux_ebus_device *dev; struct linux_ebus *ebus; struct pci_dev *pdev; struct pcidev_cookie *cookie; char lbuf[128]; unsigned long addr, *base; unsigned short pci_command; int nd, len, ebusnd; int reg, rng, nreg; int num_ebus = 0; if (!pci_present()) return; pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0); if (!pdev) { printk("ebus: No EBus's found.\n"); #ifdef PROM_DEBUG dprintf("ebus: No EBus's found.\n"); #endif return; } cookie = pdev->sysdata; ebusnd = cookie->prom_node; ebus_chain = ebus = (struct linux_ebus *) ebus_alloc(sizeof(struct linux_ebus)); ebus->next = 0; while (ebusnd) { printk("ebus%d:", num_ebus); #ifdef PROM_DEBUG dprintf("ebus%d:", num_ebus); #endif prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); ebus->prom_node = ebusnd; strcpy(ebus->prom_name, lbuf); ebus->self = pdev; ebus->parent = pbm = cookie->pbm; /* Enable BUS Master. */ pci_read_config_word(pdev, PCI_COMMAND, &pci_command); pci_command |= PCI_COMMAND_MASTER; pci_write_config_word(pdev, PCI_COMMAND, pci_command); len = prom_getproperty(ebusnd, "reg", (void *)regs, sizeof(regs)); if (len == 0 || len == -1) { prom_printf("%s: can't find reg property\n", __FUNCTION__); prom_halt(); } nreg = len / sizeof(struct linux_prom_pci_registers); base = &ebus->self->base_address[0]; for (reg = 0; reg < nreg; reg++) { if (!(regs[reg].phys_hi & 0x03000000)) continue; for (rng = 0; rng < pbm->num_pbm_ranges; rng++) { struct linux_prom_pci_ranges *rp = &pbm->pbm_ranges[rng]; if ((rp->child_phys_hi ^ regs[reg].phys_hi) & 0x03000000) continue; addr = (u64)regs[reg].phys_lo; addr += (u64)regs[reg].phys_mid << 32UL; addr += (u64)rp->parent_phys_lo; addr += (u64)rp->parent_phys_hi << 32UL; *base++ = (unsigned long)__va(addr); printk(" %lx[%x]", (unsigned long)__va(addr), regs[reg].size_lo); #ifdef PROM_DEBUG dprintf(" %lx[%x]", (unsigned long)__va(addr), regs[reg].size_lo); #endif break; } } printk("\n"); #ifdef PROM_DEBUG dprintf("\n"); #endif prom_ebus_ranges_init(ebus); prom_ebus_intmap_init(ebus); nd = prom_getchild(ebusnd); if (!nd) goto next_ebus; ebus->devices = (struct linux_ebus_device *) ebus_alloc(sizeof(struct linux_ebus_device)); dev = ebus->devices; dev->next = 0; dev->children = 0; dev->bus = ebus; fill_ebus_device(nd, dev); while ((nd = prom_getsibling(nd))) { dev->next = (struct linux_ebus_device *) ebus_alloc(sizeof(struct linux_ebus_device)); dev = dev->next; dev->next = 0; dev->children = 0; dev->bus = ebus; fill_ebus_device(nd, dev); } next_ebus: pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, pdev); if (!pdev) break; cookie = pdev->sysdata; ebusnd = cookie->prom_node; ebus->next = (struct linux_ebus *) ebus_alloc(sizeof(struct linux_ebus)); ebus = ebus->next; ebus->next = 0; ++num_ebus; } #ifdef CONFIG_SUN_OPENPROMIO openprom_init(); #endif #ifdef CONFIG_SPARCAUDIO sparcaudio_init(); #endif #ifdef CONFIG_SUN_BPP bpp_init(); #endif #ifdef CONFIG_SUN_AUXIO auxio_probe(); #endif #ifdef CONFIG_ENVCTRL envctrl_init(); #endif #ifdef CONFIG_OBP_FLASH flash_init(); #endif clock_probe(); }
static void __init fill_ebus_child(struct device_node *dp, struct linux_ebus_child *dev, int non_standard_regs) { struct of_device *op; int *regs; int i, len; dev->prom_node = dp; printk(" (%s)", dp->name); regs = of_get_property(dp, "reg", &len); if (!regs) dev->num_addrs = 0; else dev->num_addrs = len / sizeof(regs[0]); if (non_standard_regs) { /* This is to handle reg properties which are not * in the parent relative format. One example are * children of the i2c device on CompactPCI systems. * * So, for such devices we just record the property * raw in the child resources. */ for (i = 0; i < dev->num_addrs; i++) dev->resource[i].start = regs[i]; } else { for (i = 0; i < dev->num_addrs; i++) { int rnum = regs[i]; if (rnum >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", dp->name, len, dev->parent->num_addrs); prom_halt(); } dev->resource[i].start = dev->parent->resource[i].start; dev->resource[i].end = dev->parent->resource[i].end; dev->resource[i].flags = IORESOURCE_MEM; dev->resource[i].name = dp->name; } } op = of_find_device_by_node(dp); if (!op) { dev->num_irqs = 0; } else { dev->num_irqs = op->num_irqs; for (i = 0; i < dev->num_irqs; i++) dev->irqs[i] = op->irqs[i]; } if (!dev->num_irqs) { /* * Oh, well, some PROMs don't export interrupts * property to children of EBus devices... * * Be smart about PS/2 keyboard and mouse. */ if (!strcmp(dev->parent->prom_node->name, "8042")) { if (!strcmp(dev->prom_node->name, "kb_ps2")) { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[0]; } else { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[1]; } } } }
void __init leon_init_timers(irq_handler_t counter_fn) { int irq; leondebug_irq_disable = 0; leon_debug_irqout = 0; master_l10_counter = (unsigned int *)&dummy_master_l10_counter; dummy_master_l10_counter = 0; if (leon3_gptimer_regs && leon3_irqctrl_regs) { LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, (((1000000 / HZ) - 1))); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); #ifdef CONFIG_SMP leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & (1<<LEON3_GPTIMER_SEPIRQ))) { prom_printf("irq timer not configured with separate irqs\n"); BUG(); } LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); # endif } else { printk(KERN_ERR "No Timer/irqctrl found\n"); BUG(); } irq = request_irq(leon3_gptimer_irq, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { printk(KERN_ERR "leon_time_init: unable to attach IRQ%d\n", LEON_INTERRUPT_TIMER1); prom_halt(); } # ifdef CONFIG_SMP { unsigned long flags; struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)]; /* For SMP we use the level 14 ticker, however the bootup code * has copied the firmwares level 14 vector into boot cpu's * trap table, we must fix this now or we get squashed. */ local_irq_save(flags); patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ /* Adjust so that we jump directly to smpleon_ticker */ trap_table->inst_three += smpleon_ticker - real_irq_entry; local_flush_cache_all(); local_irq_restore(flags); } # endif if (leon3_gptimer_regs) { LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, LEON3_GPTIMER_EN | LEON3_GPTIMER_RL | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); #ifdef CONFIG_SMP LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, LEON3_GPTIMER_EN | LEON3_GPTIMER_RL | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); #endif } }
void machine_halt(void) { prom_halt(); panic("Halt failed!"); }