struct prom_pmemblock * __init prom_getmdesc(void) { char *memsize_str; unsigned int memsize; char tmp_cmdline[COMMAND_LINE_SIZE]; char *tmp_str; strlcpy(tmp_cmdline, arcs_cmdline, COMMAND_LINE_SIZE); tmp_str = find_args(tmp_cmdline, "debug_ros"); if (tmp_str) { sscanf(tmp_str, "%x", &audio_addr); debug_flag = 1; } if (audio_addr == 0) { audio_addr = *((unsigned int *)0xa00000d8); audio_addr = reverseInt(audio_addr); } if ((audio_addr < 0x81000000) || (audio_addr >= 0x82000000)) { printk("**************************************************************\n"); printk("You didn't specify audio image address, use default instead...\n"); printk("**************************************************************\n"); audio_addr = 0; } memsize_str = prom_getenv("memsize"); if (!memsize_str) { prom_printf("memsize not set in boot prom, set to default (32Mb)\n"); memsize = 0x02000000; } else { #ifdef DEBUG prom_printf("prom_memsize = %s\n", memsize_str); #endif memsize = simple_strtol(memsize_str, NULL, 0); if (memsize < 0x02000000) { panic("memsize cannot be less then 32Mb.\n"); } } memset(mdesc, 0, sizeof(mdesc)); #ifdef CONFIG_REALTEK_MARS_RESERVE_LAST_48MB if (memsize == 0x10000000) memsize -= 0x03000000; #endif // The last page is used to store the DRAM calibration parameter; // Jacky says that this page can be included in his RTOS memory region. // mdesc[4].type = yamon_dontuse; // mdesc[4].base = memsize - 4096; // mdesc[4].size = 4096; #if CONFIG_REALTEK_RTOS_MEMORY_SIZE // If memsize is over 32Mb if(memsize > 0x02000000) { mdesc[4].type = yamon_free; mdesc[4].base = 0x02000000; mdesc[4].size = memsize - 0x02000000; } // This memory region is used by RTOS. mdesc[3].type = yamon_dontuse; // mdesc[3].base = mdesc[4].base - CONFIG_REALTEK_RTOS_MEMORY_SIZE; if (audio_addr != 0) { audio_addr = audio_addr-0x80000000; mdesc[3].base = audio_addr; mdesc[3].size = 0x02000000 - audio_addr; } else { mdesc[3].base = 0x02000000 - CONFIG_REALTEK_RTOS_MEMORY_SIZE; mdesc[3].size = CONFIG_REALTEK_RTOS_MEMORY_SIZE; } printk("audio addr: %x \n", audio_addr); // Kernel image is stored in 0x100000 - CPHYSADDR(PFN_ALIGN(&_end)). mdesc[2].type = yamon_free; mdesc[2].base = CPHYSADDR(PFN_ALIGN(&_end)); mdesc[2].size = mdesc[3].base - CPHYSADDR(PFN_ALIGN(&_end)); #else // Kernel image is stored in 0x100000 - CPHYSADDR(PFN_ALIGN(&_end)). mdesc[2].type = yamon_free; mdesc[2].base = CPHYSADDR(PFN_ALIGN(&_end)); mdesc[2].size = memsize - CPHYSADDR(PFN_ALIGN(&_end)); #endif mdesc[1].type = yamon_dontuse; mdesc[1].base = 0x100000; mdesc[1].size = CPHYSADDR(PFN_ALIGN(&_end))-0x100000; mdesc[0].type = yamon_free; mdesc[0].base = 0x0; mdesc[0].size = 0x100000; return &mdesc[0]; }
/* Pretty sick eh? */ int prom_callback(long *args) { struct console *cons, *saved_console = NULL; unsigned long flags; char *cmd; extern spinlock_t prom_entry_lock; if (!args) return -1; if (!(cmd = (char *)args[0])) return -1; /* * The callback can be invoked on the cpu that first dropped * into prom_cmdline after taking the serial interrupt, or on * a slave processor that was smp_captured() if the * administrator has done a switch-cpu inside obp. In either * case, the cpu is marked as in-interrupt. Drop IRQ locks. */ irq_exit(smp_processor_id(), 0); save_and_cli(flags); spin_unlock(&prom_entry_lock); cons = console_drivers; while (cons) { unregister_console(cons); cons->flags &= ~(CON_PRINTBUFFER); cons->next = saved_console; saved_console = cons; cons = console_drivers; } register_console(&prom_console); if (!strcmp(cmd, "sync")) { prom_printf("PROM `%s' command...\n", cmd); show_free_areas(); if(current->pid != 0) { sti(); sys_sync(); cli(); } args[2] = 0; args[args[1] + 3] = -1; prom_printf("Returning to PROM\n"); } else if (!strcmp(cmd, "va>tte-data")) { unsigned long ctx, va; unsigned long tte = 0; long res = PROM_FALSE; ctx = args[3]; va = args[4]; if (ctx) { /* * Find process owning ctx, lookup mapping. */ struct task_struct *p; struct mm_struct *mm = NULL; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; for_each_task(p) { mm = p->mm; if (CTX_HWBITS(mm->context) == ctx) break; } if (!mm || CTX_HWBITS(mm->context) != ctx) goto done; pgdp = pgd_offset(mm, va); if (pgd_none(*pgdp)) goto done; pmdp = pmd_offset(pgdp, va); if (pmd_none(*pmdp)) goto done; ptep = pte_offset(pmdp, va); if (!pte_present(*ptep)) goto done; tte = pte_val(*ptep); res = PROM_TRUE; goto done; } if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { /* Spitfire Errata #32 workaround */ __asm__ __volatile__("stxa %0, [%1] %2\n\t" "flush %%g6" : /* No outputs */ : "r" (0), "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); /* * Locked down tlb entry. */ if (tlb_type == spitfire) tte = spitfire_get_dtlb_data(SPITFIRE_HIGHEST_LOCKED_TLBENT); else if (tlb_type == cheetah || tlb_type == cheetah_plus) tte = cheetah_get_ldtlb_data(CHEETAH_HIGHEST_LOCKED_TLBENT); res = PROM_TRUE; goto done; }
static __inline__ void promcon_puts(char *buf, int cnt) { prom_printf("%*.*s", cnt, cnt, buf); }
static void dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh) { dr_handle_t *handle; dev_info_t *dip, *next, *last = NULL; major_t major; char *bn; int circ; major = (major_t)-1; /* attach in reverse device tree order */ while (last != start) { dip = start; next = ddi_get_next_sibling(dip); while (next != last && dip != srh->sr_failed_dip) { dip = next; next = ddi_get_next_sibling(dip); } if (dip == srh->sr_failed_dip) { /* release hold acquired in dr_suspend_devices() */ srh->sr_failed_dip = NULL; ndi_rele_devi(dip); } else if (dr_is_real_device(dip) && srh->sr_failed_dip == NULL) { if ((bn = ddi_binding_name(dip)) != NULL) { major = ddi_name_to_major(bn); } else { bn = "<null>"; } if (!dr_bypass_device(bn) && !drmach_verify_sr(dip, 0)) { char d_name[40], d_alias[40], *d_info; d_name[0] = 0; d_info = ddi_get_name_addr(dip); if (d_info == NULL) d_info = "<null>"; if (!dr_resolve_devname(dip, d_name, d_alias)) { if (d_alias[0] != 0) { prom_printf("\tresuming " "%s@%s (aka %s)\n", d_name, d_info, d_alias); } else { prom_printf("\tresuming " "%s@%s\n", d_name, d_info); } } else { prom_printf("\tresuming %s@%s\n", bn, d_info); } if (devi_attach(dip, DDI_RESUME) != DDI_SUCCESS) { /* * Print a console warning, * set an e_code of ESBD_RESUME, * and save the driver major * number in the e_rsc. */ prom_printf("\tFAILED to resume %s@%s", d_name[0] ? d_name : bn, d_info); srh->sr_err_idx = dr_add_int(srh->sr_err_ints, srh->sr_err_idx, DR_MAX_ERR_INT, (uint64_t)major); handle = srh->sr_dr_handlep; dr_op_err(CE_IGNORE, handle, ESBD_RESUME, "%s@%s", d_name[0] ? d_name : bn, d_info); } } } /* Hold parent busy while walking its children */ ndi_devi_enter(dip, &circ); dr_resume_devices(ddi_get_child(dip), srh); ndi_devi_exit(dip, circ); last = dip; } }
int dr_suspend(dr_sr_handle_t *srh) { dr_handle_t *handle; int force; int dev_errs_idx; uint64_t dev_errs[DR_MAX_ERR_INT]; int rc = DDI_SUCCESS; handle = srh->sr_dr_handlep; force = dr_cmd_flags(handle) & SBD_FLAG_FORCE; /* * update the signature block */ CPU_SIGNATURE(OS_SIG, SIGST_QUIESCE_INPROGRESS, SIGSUBST_NULL, CPU->cpu_id); prom_printf("\nDR: suspending user threads...\n"); srh->sr_suspend_state = DR_SRSTATE_USER; if (((rc = dr_stop_user_threads(srh)) != DDI_SUCCESS) && dr_check_user_stop_result) { dr_resume(srh); return (rc); } if (!force) { struct dr_ref drc = {0}; prom_printf("\nDR: checking devices...\n"); dev_errs_idx = 0; drc.arr = dev_errs; drc.idx = &dev_errs_idx; drc.len = DR_MAX_ERR_INT; /* * Since the root node can never go away, it * doesn't have to be held. */ ddi_walk_devs(ddi_root_node(), dr_check_unsafe_major, &drc); if (dev_errs_idx) { handle->h_err = drerr_int(ESBD_UNSAFE, dev_errs, dev_errs_idx, 1); dr_resume(srh); return (DDI_FAILURE); } PR_QR("done\n"); } else { prom_printf("\nDR: dr_suspend invoked with force flag\n"); } #ifndef SKIP_SYNC /* * This sync swap out all user pages */ vfs_sync(SYNC_ALL); #endif /* * special treatment for lock manager */ lm_cprsuspend(); #ifndef SKIP_SYNC /* * sync the file system in case we never make it back */ sync(); #endif /* * now suspend drivers */ prom_printf("DR: suspending drivers...\n"); srh->sr_suspend_state = DR_SRSTATE_DRIVER; srh->sr_err_idx = 0; /* No parent to hold busy */ if ((rc = dr_suspend_devices(ddi_root_node(), srh)) != DDI_SUCCESS) { if (srh->sr_err_idx && srh->sr_dr_handlep) { (srh->sr_dr_handlep)->h_err = drerr_int(ESBD_SUSPEND, srh->sr_err_ints, srh->sr_err_idx, 1); } dr_resume(srh); return (rc); } drmach_suspend_last(); /* * finally, grab all cpus */ srh->sr_suspend_state = DR_SRSTATE_FULL; /* * if watchdog was activated, disable it */ if (watchdog_activated) { mutex_enter(&tod_lock); tod_ops.tod_clear_watchdog_timer(); mutex_exit(&tod_lock); srh->sr_flags |= SR_FLAG_WATCHDOG; } else { srh->sr_flags &= ~(SR_FLAG_WATCHDOG); } /* * Update the signature block. * This must be done before cpus are paused, since on Starcat the * cpu signature update aquires an adaptive mutex in the iosram driver. * Blocking with cpus paused can lead to deadlock. */ CPU_SIGNATURE(OS_SIG, SIGST_QUIESCED, SIGSUBST_NULL, CPU->cpu_id); mutex_enter(&cpu_lock); pause_cpus(NULL, NULL); dr_stop_intr(); return (rc); }
__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 }
static inline void breakout_cerrd(unsigned int val) { switch (val & CP0_CERRD_CAUSES) { case CP0_CERRD_LOAD: prom_printf(" load,"); break; case CP0_CERRD_STORE: prom_printf(" store,"); break; case CP0_CERRD_FILLWB: prom_printf(" fill/wb,"); break; case CP0_CERRD_COHERENCY: prom_printf(" coherency,"); break; case CP0_CERRD_DUPTAG: prom_printf(" duptags,"); break; default: prom_printf(" NO CAUSE,"); break; } if (!(val & CP0_CERRD_TYPES)) prom_printf(" NO TYPE"); else { if (val & CP0_CERRD_MULTIPLE) prom_printf(" multi-err"); if (val & CP0_CERRD_TAG_STATE) prom_printf(" tag-state"); if (val & CP0_CERRD_TAG_ADDRESS) prom_printf(" tag-address"); if (val & CP0_CERRD_DATA_SBE) prom_printf(" data-SBE"); if (val & CP0_CERRD_DATA_DBE) prom_printf(" data-DBE"); if (val & CP0_CERRD_EXTERNAL) prom_printf(" external"); } prom_printf("\n"); }
void __init rt2880_setup(void) { #ifdef CONFIG_KGDB int rs_putDebugChar(char); char rs_getDebugChar(void); int saa9730_putDebugChar(char); char saa9730_getDebugChar(void); extern int (*generic_putDebugChar)(char); extern char (*generic_getDebugChar)(void); #endif char *argptr; iomem_resource.start = 0; iomem_resource.end= ~0; ioport_resource.start= 0; ioport_resource.end = ~0; #ifdef CONFIG_SERIAL_CONSOLE argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "console=ttyS")) == NULL) { int i = 0; char *s = prom_getenv("modetty0"); while(s[i] >= '0' && s[i] <= '9') i++; strcpy(serial_console, "ttyS0,"); strncpy(serial_console + 6, s, i); prom_printf("Config serial console: %s\n", serial_console); console_setup(serial_console, NULL); } #endif #ifdef CONFIG_KGDB argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { int line; argptr += strlen("kgdb=ttyS"); if (*argptr != '0' && *argptr != '1') printk("KGDB: Uknown serial line /dev/ttyS%c, " "falling back to /dev/ttyS1\n", *argptr); line = *argptr == '0' ? 0 : 1; printk("KGDB: Using serial line /dev/ttyS%d for session\n", line ? 1 : 0); if(line == 0) { rs_kgdb_hook(line); generic_putDebugChar = rs_putDebugChar; generic_getDebugChar = rs_getDebugChar; } else { saa9730_kgdb_hook(); generic_putDebugChar = saa9730_putDebugChar; generic_getDebugChar = saa9730_getDebugChar; } prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " "please connect your debugger\n", line ? 1 : 0); remote_debug = 1; /* Breakpoints and stuff are in surfboard_irq_setup() */ } #endif argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "nofpu")) != NULL) cpu_data[0].options &= ~MIPS_CPU_FPU; //rtc_ops = &no_rtc_ops; board_time_init = mips_time_init; //board_timer_setup = mips_timer_setup; mips_reboot_setup(); }
__initfunc(void sgi_setup(void)) { #ifdef CONFIG_SERIAL_CONSOLE char *ctype; #endif #ifdef CONFIG_REMOTE_DEBUG char *kgdb_ttyd; #endif irq_setup = sgi_irq_setup; /* Init the INDY HPC I/O controller. Need to call this before * f*****g with the memory controller because it needs to know the * boardID and whether this is a Guiness or a FullHouse machine. */ sgihpc_init(); /* Init INDY memory controller. */ sgimc_init(); /* Now enable boardcaches, if any. */ indy_sc_init(); #ifdef CONFIG_SERIAL_CONSOLE /* ARCS console environment variable is set to "g?" for * graphics console, it is set to "d" for the first serial * line and "d2" for the second serial line. */ ctype = prom_getenv("console"); if(*ctype == 'd') { if(*(ctype+1)=='2') console_setup ("ttyS1", NULL); else console_setup ("ttyS0", NULL); } #endif #ifdef CONFIG_REMOTE_DEBUG kgdb_ttyd = prom_getcmdline(); if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) { int line; kgdb_ttyd += strlen("kgdb=ttyd"); if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2') printk("KGDB: Uknown serial line /dev/ttyd%c, " "falling back to /dev/ttyd1\n", *kgdb_ttyd); line = *kgdb_ttyd == '2' ? 0 : 1; printk("KGDB: Using serial line /dev/ttyd%d for session\n", line ? 1 : 2); rs_kgdb_hook(line); prom_printf("KGDB: Using serial line /dev/ttyd%d for session, " "please connect your debugger\n", line ? 1 : 2); remote_debug = 1; /* Breakpoints and stuff are in sgi_irq_setup() */ } #endif #ifdef CONFIG_SGI_PROM_CONSOLE console_setup("ttyS0", NULL); #endif sgi_volume_set(simple_strtoul(prom_getenv("volume"), NULL, 10)); #ifdef CONFIG_VT #ifdef CONFIG_SGI_NEWPORT_CONSOLE conswitchp = &newport_con; #else conswitchp = &dummy_con; #endif #endif rtc_ops = &indy_rtc_ops; kbd_ops = &sgi_kbd_ops; #ifdef CONFIG_PSMOUSE aux_device_present = 0xaa; #endif #ifdef CONFIG_VIDEO_VINO init_vino(); #endif }
int fputs(const char *s, FILE *stream) { prom_printf("%s", s); return 0; }
static void __init should_not_happen(void) { prom_printf(shouldnothappen); prom_halt(); }
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]; } } } }
static int pca9556_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { pca9556_unit_t *pcap; int err = 0; int instance = MINOR_TO_INST(getminor(dev)); int port; i2c_gpio_t g_buf; uchar_t temp; boolean_t write_io = B_FALSE; _NOTE(ARGUNUSED(credp, rvalp)) pcap = (pca9556_unit_t *) ddi_get_soft_state(pca9556_soft_statep, instance); if (pcap->pca9555_device) { port = MINOR_TO_PORT(getminor(dev)); } if (pca9556_debug) { prom_printf("pca9556_ioctl: instance=%d\n", instance); } /* * We serialize here and block any pending transacations. */ mutex_enter(&pcap->pca9556_mutex); while ((pcap->pca9556_flags & PCA9556_BUSYFLAG) == PCA9556_BUSYFLAG) { if (cv_wait_sig(&pcap->pca9556_cv, &pcap->pca9556_mutex) <= 0) { mutex_exit(&pcap->pca9556_mutex); return (EINTR); } } pcap->pca9556_flags |= PCA9556_BUSYFLAG; mutex_exit(&pcap->pca9556_mutex); if (ddi_copyin((caddr_t)arg, &g_buf, sizeof (i2c_gpio_t), mode) != DDI_SUCCESS) { err = EFAULT; goto cleanup; } pcap->pca9556_transfer->i2c_flags = I2C_WR_RD; pcap->pca9556_transfer->i2c_wlen = 1; pcap->pca9556_transfer->i2c_rlen = 1; /* * Evaluate which register is to be read or modified */ switch (cmd) { case GPIO_GET_INPUT: if (pcap->pca9555_device) pcap->pca9556_transfer->i2c_wbuf[0] = PCA9555_INPUT_REG + port; else pcap->pca9556_transfer->i2c_wbuf[0] = PCA9556_INPUT_REG; break; case GPIO_SET_OUTPUT: write_io = B_TRUE; /*FALLTHROUGH*/ case GPIO_GET_OUTPUT: if (pcap->pca9555_device) pcap->pca9556_transfer->i2c_wbuf[0] = PCA9555_OUTPUT_REG + port; else pcap->pca9556_transfer->i2c_wbuf[0] = PCA9556_OUTPUT_REG; break; case GPIO_SET_POLARITY: write_io = B_TRUE; /*FALLTHROUGH*/ case GPIO_GET_POLARITY: if (pcap->pca9555_device) pcap->pca9556_transfer->i2c_wbuf[0] = PCA9555_POLARITY_REG + port; else pcap->pca9556_transfer->i2c_wbuf[0] = PCA9556_POLARITY_REG; break; case GPIO_SET_CONFIG: write_io = B_TRUE; /*FALLTHROUGH*/ case GPIO_GET_CONFIG: if (pcap->pca9555_device) pcap->pca9556_transfer->i2c_wbuf[0] = PCA9555_CONFIG_REG + port; else pcap->pca9556_transfer->i2c_wbuf[0] = PCA9556_CONFIG_REG; break; } /* * Read the required register */ if (i2c_transfer(pcap->pca9556_hdl, pcap->pca9556_transfer) != I2C_SUCCESS) { err = EIO; goto cleanup; } /* * Evaluate whether the register is to be read or modified */ if (!write_io) { g_buf.reg_val = g_buf.reg_mask & pcap->pca9556_transfer->i2c_rbuf[0]; err = ddi_copyout(&g_buf, (caddr_t)arg, sizeof (i2c_gpio_t), mode); } else { pcap->pca9556_transfer->i2c_flags = I2C_WR; pcap->pca9556_transfer->i2c_wlen = 2; pcap->pca9556_transfer->i2c_rlen = 0; /* * Modify register without overwriting existing contents */ temp = pcap->pca9556_transfer->i2c_rbuf[0] & (~g_buf.reg_mask); pcap->pca9556_transfer->i2c_wbuf[1] = temp| (g_buf.reg_val & g_buf.reg_mask); if (i2c_transfer(pcap->pca9556_hdl, pcap->pca9556_transfer) != I2C_SUCCESS) { err = EIO; } } cleanup: mutex_enter(&pcap->pca9556_mutex); pcap->pca9556_flags = pcap->pca9556_flags & ~PCA9556_BUSYFLAG; cv_signal(&pcap->pca9556_cv); mutex_exit(&pcap->pca9556_mutex); return (err); }
/* Pretty sick eh? */ int prom_callback(long *args) { struct console *cons, *saved_console = NULL; unsigned long flags; char *cmd; if (!args) return -1; if (!(cmd = (char *)args[0])) return -1; save_and_cli(flags); cons = console_drivers; while (cons) { unregister_console(cons); cons->flags &= ~(CON_PRINTBUFFER); cons->next = saved_console; saved_console = cons; cons = console_drivers; } register_console(&prom_console); if (!strcmp(cmd, "sync")) { prom_printf("PROM `%s' command...\n", cmd); show_free_areas(); if(current->pid != 0) { sti(); sys_sync(); cli(); } args[2] = 0; args[args[1] + 3] = -1; prom_printf("Returning to PROM\n"); } else if (!strcmp(cmd, "va>tte-data")) { unsigned long ctx, va; unsigned long tte = 0; long res = PROM_FALSE; ctx = args[3]; va = args[4]; if (ctx) { /* * Find process owning ctx, lookup mapping. */ struct task_struct *p; pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; for_each_task(p) if (p->tss.ctx == ctx) break; if (p->tss.ctx != ctx) goto done; pgdp = pgd_offset(p->mm, va); if (pgd_none(*pgdp)) goto done; pmdp = pmd_offset(pgdp, va); if (pmd_none(*pmdp)) goto done; ptep = pte_offset(pmdp, va); if (!pte_present(*ptep)) goto done; tte = pte_val(*ptep); res = PROM_TRUE; goto done; } if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { /* * Locked down tlb entry 63. */ tte = spitfire_get_dtlb_data(63); res = PROM_TRUE; goto done; } if (va < PGDIR_SIZE) { /* * vmalloc or prom_inherited mapping. */ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; pgdp = pgd_offset_k(va); if (pgd_none(*pgdp)) goto done; pmdp = pmd_offset(pgdp, va); if (pmd_none(*pmdp)) goto done; ptep = pte_offset(pmdp, va); if (!pte_present(*ptep)) goto done; tte = pte_val(*ptep); res = PROM_TRUE; goto done; } if (va < PAGE_OFFSET) { /* * No mappings here. */ goto done; } if (va & (1UL << 40)) { /* * I/O page. */ tte = (__pa(va) & _PAGE_PADDR) | _PAGE_VALID | _PAGE_SZ4MB | _PAGE_E | _PAGE_P | _PAGE_W; res = PROM_TRUE; goto done; } /* * Normal page. */ tte = (__pa(va) & _PAGE_PADDR) | _PAGE_VALID | _PAGE_SZ4MB | _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W; res = PROM_TRUE; done: if (res == PROM_TRUE) { args[2] = 3; args[args[1] + 3] = 0; args[args[1] + 4] = res; args[args[1] + 5] = tte; } else { args[2] = 2; args[args[1] + 3] = 0; args[args[1] + 4] = res; } } else if (!strcmp(cmd, ".soft1")) {
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 (!pcic_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 (!pcic_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 sgimc_init(void) { unsigned long tmpreg; mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); rpsscounter = (u32 *) (KSEG1 + 0x1fa01004); dmactrlregs = (struct sgimc_dma_ctrl *) (KSEG1+0x1fa02000); printk("MC: SGI memory controller Revision %d\n", (int) mcmisc_regs->systemid & SGIMC_SYSID_MASKREV); #if 0 /* XXX Until I figure out what this bit really indicates XXX */ /* XXX Is this systemid bit reliable? */ if(mcmisc_regs->systemid & SGIMC_SYSID_EPRESENT) { EISA_bus = 1; printk("with EISA\n"); } else { EISA_bus = 0; printk("no EISA\n"); } #endif #ifdef DEBUG_SGIMC prom_printf("sgimc_init: memconfig0<%s> mconfig1<%s>\n", mconfig_string(mcmisc_regs->mconfig0), mconfig_string(mcmisc_regs->mconfig1)); prom_printf("mcdump: cpuctrl0<%08lx> cpuctrl1<%08lx>\n", mcmisc_regs->cpuctrl0, mcmisc_regs->cpuctrl1); prom_printf("mcdump: divider<%08lx>, gioparm<%04x>\n", mcmisc_regs->divider, mcmisc_regs->gioparm); #endif /* Place the MC into a known state. This must be done before * interrupts are first enabled etc. */ /* Step 1: The CPU/GIO error status registers will not latch * up a new error status until the register has been * cleared by the cpu. These status registers are * cleared by writing any value to them. */ mcmisc_regs->cstat = mcmisc_regs->gstat = 0; /* Step 2: Enable all parity checking in cpu control register * zero. */ tmpreg = mcmisc_regs->cpuctrl0; tmpreg |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | SGIMC_CCTRL0_R4KNOCHKPARR); mcmisc_regs->cpuctrl0 = tmpreg; /* Step 3: Setup the MC write buffer depth, this is controlled * in cpu control register 1 in the lower 4 bits. */ tmpreg = mcmisc_regs->cpuctrl1; tmpreg &= ~0xf; tmpreg |= 0xd; mcmisc_regs->cpuctrl1 = tmpreg; /* Step 4: Initialize the RPSS divider register to run as fast * as it can correctly operate. The register is laid * out as follows: * * ---------------------------------------- * | RESERVED | INCREMENT | DIVIDER | * ---------------------------------------- * 31 16 15 8 7 0 * * DIVIDER determines how often a 'tick' happens, * INCREMENT determines by how the RPSS increment * registers value increases at each 'tick'. Thus, * for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101 */ mcmisc_regs->divider = 0x101; /* Step 5: Initialize GIO64 arbitrator configuration register. * * NOTE: If you dork with startup code the HPC init code in * sgihpc_init() must run before us because of how we * need to know Guiness vs. FullHouse and the board * revision on this machine. You have been warned. */ /* First the basic invariants across all gio64 implementations. */ tmpreg = SGIMC_GIOPARM_HPC64; /* All 1st HPC's interface at 64bits. */ tmpreg |= SGIMC_GIOPARM_ONEBUS; /* Only one physical GIO bus exists. */ if(sgi_guiness) { /* Guiness specific settings. */ tmpreg |= SGIMC_GIOPARM_EISA64; /* MC talks to EISA at 64bits */ tmpreg |= SGIMC_GIOPARM_MASTEREISA; /* EISA bus can act as master */ } else { /* Fullhouse specific settings. */ if(sgi_boardid < 2) { tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC at 64bits */ tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp0 pipelines */ tmpreg |= SGIMC_GIOPARM_MASTEREXP1;/* exp1 masters */ tmpreg |= SGIMC_GIOPARM_RTIMEEXP0; /* exp0 is realtime */ } else { tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC 64bits */ tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */ tmpreg |= SGIMC_GIOPARM_PLINEEXP1; tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */ /* someone forgot this poor little guy... */ tmpreg |= SGIMC_GIOPARM_GFX64; /* GFX at 64 bits */ } } mcmisc_regs->gioparm = tmpreg; /* poof */ }
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) { 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; } } else { /* No "intr" node found-- check for "interrupts" node. * This node contains SBus interrupt levels, not IPLs * as in "intr", and no vector values. We convert * SBus interrupt levels to PILs (platform specific). */ len = prom_getproperty(prom_node, "interrupts", (char *)interrupts, sizeof(interrupts)); if (len == -1) { sdev->irqs[0] = 0; sdev->num_irqs = 0; } else { sdev->num_irqs = len / sizeof(int); for (len = 0; len < sdev->num_irqs; len++) { sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]); } } } #endif /* !__sparc_v9__ */ }
static int acebus_config(ebus_devstate_t *ebus_p) { ddi_acc_handle_t conf_handle; uint16_t comm; #ifdef ACEBUS_HOTPLUG int tcr_reg; caddr_t csr_io; ddi_device_acc_attr_t csr_attr = { /* CSR map attributes */ DDI_DEVICE_ATTR_V0, DDI_STRUCTURE_LE_ACC, DDI_STRICTORDER_ACC }; ddi_acc_handle_t csr_handle; #endif /* * Make sure the master enable and memory access enable * bits are set in the config command register. */ if (pci_config_setup(ebus_p->dip, &conf_handle) != DDI_SUCCESS) return (0); comm = pci_config_get16(conf_handle, PCI_CONF_COMM), #ifdef DEBUG DBG1(D_ATTACH, ebus_p, "command register was 0x%x\n", comm); #endif comm |= (PCI_COMM_ME|PCI_COMM_MAE|PCI_COMM_SERR_ENABLE| PCI_COMM_PARITY_DETECT); pci_config_put16(conf_handle, PCI_CONF_COMM, comm), #ifdef DEBUG DBG1(D_MAP, ebus_p, "command register is now 0x%x\n", pci_config_get16(conf_handle, PCI_CONF_COMM)); #endif pci_config_put8(conf_handle, PCI_CONF_CACHE_LINESZ, (uchar_t)acebus_cache_line_size); pci_config_put8(conf_handle, PCI_CONF_LATENCY_TIMER, (uchar_t)acebus_latency_timer); pci_config_teardown(&conf_handle); #ifdef ACEBUS_HOTPLUG if (acebus_update_props(ebus_p) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s%d: Could not update special properties.", ddi_driver_name(ebus_p->dip), ddi_get_instance(ebus_p->dip)); return (0); } if (ddi_regs_map_setup(ebus_p->dip, CSR_IO_RINDEX, (caddr_t *)&csr_io, 0, CSR_SIZE, &csr_attr, &csr_handle) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s%d: Could not map Ebus CSR.", ddi_driver_name(ebus_p->dip), ddi_get_instance(ebus_p->dip)); } #ifdef DEBUG if (acebus_debug_flags) { DBG3(D_ATTACH, ebus_p, "tcr[123] = %x,%x,%x\n", ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF)), ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF)), ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF))); DBG2(D_ATTACH, ebus_p, "pmd-aux=%x, freq-aux=%x\n", ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + PMD_AUX_OFF)), ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + FREQ_AUX_OFF))); #ifdef ACEBUS_DEBUG for (comm = 0; comm < 4; comm++) prom_printf("dcsr%d=%x, dacr%d=%x, dbcr%d=%x\n", comm, ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 0x700000+(0x2000*comm))), comm, ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 0x700000+(0x2000*comm)+4)), comm, ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + 0x700000+(0x2000*comm)+8))); #endif } /* acebus_debug_flags */ #endif /* If TCR registers are not initialized, initialize them here */ tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF)); if ((tcr_reg == 0) || (tcr_reg == -1)) ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF), TCR1_REGVAL); tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF)); if ((tcr_reg == 0) || (tcr_reg == -1)) ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF), TCR2_REGVAL); tcr_reg = ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF)); if ((tcr_reg == 0) || (tcr_reg == -1)) ddi_put32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF), TCR3_REGVAL); #ifdef DEBUG if (acebus_debug_flags) { DBG3(D_ATTACH, ebus_p, "wrote tcr[123] = %x,%x,%x\n", ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR1_OFF)), ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR2_OFF)), ddi_get32(csr_handle, (uint32_t *)((caddr_t)csr_io + TCR3_OFF))); } #endif ddi_regs_map_free(&csr_handle); #endif /* ACEBUS_HOTPLUG */ return (1); /* return success */ }
__initfunc(void sun4m_init_IRQ(void)) { int ie_node,i; struct linux_prom_registers int_regs[PROMREG_MAX]; int num_regs; __cli(); 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; } /* Map the interrupt registers for all possible cpus. */ sun4m_interrupts = sparc_alloc_io(int_regs[0].phys_addr, 0, PAGE_SIZE*NCPUS, "interrupts_percpu", int_regs[0].which_io, 0x0); /* Map the system interrupt control registers. */ sparc_alloc_io(int_regs[4].phys_addr, 0, int_regs[4].reg_size, "interrupts_system", int_regs[4].which_io, 0x0); sun4m_interrupts->set = ~SUN4M_INT_MASKALL; for (i=0; i<linux_num_cpus; i++) sun4m_interrupts->cpu_intregs[i].clear = ~0x17fff; if (linux_num_cpus > 1) { /* 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(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); BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM); init_timers = sun4m_init_timers; #ifdef __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. */ }
static int cfg_set (char *item, char *value) { CONFIG *walk; if (!strncasecmp (item, "image", 5)) { struct IMAGES **p = &images; int ignore = 0; if (item[5] == '[' && item[strlen(item) - 1] == ']') { char *s, *q = item; /* Get rid of braces */ item[strlen(item) - 1] = 0; item[5] = 0; for (s = item + 6; q; s = q) { q = strchr(s, '|'); if (q) *q++ = 0; if (match_arch(s)) goto cfg_set_cont; } /* This just creates an unused table. It will get ignored */ ignore = 1; } else if (item[5]) goto cfg_set_redo; cfg_set_cont: while (*p) p = &((*p)->next); *p = (struct IMAGES *)malloc (sizeof (struct IMAGES)); if (*p == NULL) { prom_printf("malloc error in cfg_set\n"); return -1; } (*p)->next = 0; (*p)->obsolete = ignore; curr_table = ((*p)->table); memcpy (curr_table, cf_image, sizeof (cf_image)); } cfg_set_redo: for (walk = curr_table; walk->type != cft_end; walk++) { if (walk->name && !strcasecmp (walk->name, item)) { if (value && walk->type != cft_strg) cfg_warn ("'%s' doesn't have a value", walk->name); else if (!value && walk->type == cft_strg) cfg_warn ("Value expected for '%s'", walk->name); else { if (!strcasecmp (item, "label")) check_for_obsolete(value); if (walk->data) cfg_warn ("Duplicate entry '%s'", walk->name); if (walk->type == cft_flag) walk->data = &flag_set; else if (walk->type == cft_strg) walk->data = value; } break; } } if (walk->type != cft_end) return 1; //cfg_return (item, value); return 0; }
/* * The "dip" argument's parent (if it exists) must be held busy. */ static int dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh) { dr_handle_t *handle; major_t major; char *dname; int circ; /* * If dip is the root node, it has no siblings and it is * always held. If dip is not the root node, dr_suspend_devices() * will be invoked with the parent held busy. */ for (; dip != NULL; dip = ddi_get_next_sibling(dip)) { char d_name[40], d_alias[40], *d_info; ndi_devi_enter(dip, &circ); if (dr_suspend_devices(ddi_get_child(dip), srh)) { ndi_devi_exit(dip, circ); return (ENXIO); } ndi_devi_exit(dip, circ); if (!dr_is_real_device(dip)) continue; major = (major_t)-1; if ((dname = ddi_binding_name(dip)) != NULL) major = ddi_name_to_major(dname); if (dr_bypass_device(dname)) { PR_QR(" bypassed suspend of %s (major# %d)\n", dname, major); continue; } if (drmach_verify_sr(dip, 1)) { PR_QR(" bypassed suspend of %s (major# %d)\n", dname, major); continue; } if ((d_info = ddi_get_name_addr(dip)) == NULL) d_info = "<null>"; d_name[0] = 0; if (dr_resolve_devname(dip, d_name, d_alias) == 0) { if (d_alias[0] != 0) { prom_printf("\tsuspending %s@%s (aka %s)\n", d_name, d_info, d_alias); } else { prom_printf("\tsuspending %s@%s\n", d_name, d_info); } } else { prom_printf("\tsuspending %s@%s\n", dname, d_info); } if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) { prom_printf("\tFAILED to suspend %s@%s\n", d_name[0] ? d_name : dname, d_info); srh->sr_err_idx = dr_add_int(srh->sr_err_ints, srh->sr_err_idx, DR_MAX_ERR_INT, (uint64_t)major); ndi_hold_devi(dip); srh->sr_failed_dip = dip; handle = srh->sr_dr_handlep; dr_op_err(CE_IGNORE, handle, ESBD_SUSPEND, "%s@%s", d_name[0] ? d_name : dname, d_info); return (DDI_FAILURE); } } return (DDI_SUCCESS); }
void __init plat_setup(void) { int i; char* argptr; board_setup(); /* board specific setup */ _machine_restart = pnx8550_machine_restart; _machine_halt = pnx8550_machine_halt; pm_power_off = pnx8550_machine_power_off; board_time_init = pnx8550_time_init; board_timer_setup = pnx8550_timer_setup; /* Clear the Global 2 Register, PCI Inta Output Enable Registers Bit 1:Enable DAC Powerdown -> 0:DACs are enabled and are working normally 1:DACs are powerdown Bit 0:Enable of PCI inta output -> 0 = Disable PCI inta output 1 = Enable PCI inta output */ PNX8550_GLB2_ENAB_INTA_O = 0; /* IO/MEM resources. */ set_io_port_base(KSEG1); ioport_resource.start = 0; ioport_resource.end = ~0; iomem_resource.start = 0; iomem_resource.end = ~0; /* Request I/O space for devices on this board */ for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, standard_io_resources + i); /* Place the Mode Control bit for GPIO pin 16 in primary function */ /* Pin 16 is used by UART1, UA1_TX */ outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) | (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT), PNX8550_GPIO_MC1); argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "console=ttyS")) != NULL) { argptr += strlen("console=ttyS"); pnx8550_console_port = *argptr == '0' ? 0 : 1; /* We must initialize the UART (console) before prom_printf */ /* Set LCR to 8-bit and BAUD to 38400 (no 5) */ ip3106_lcr(UART_BASE, pnx8550_console_port) = IP3106_UART_LCR_8BIT; ip3106_baud(UART_BASE, pnx8550_console_port) = 5; } #ifdef CONFIG_KGDB argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { int line; argptr += strlen("kgdb=ttyS"); line = *argptr == '0' ? 0 : 1; rs_kgdb_hook(line); prom_printf("KGDB: Using ttyS%i for session, " "please connect your debugger\n", line ? 1 : 0); } #endif return; }
void dr_resume(dr_sr_handle_t *srh) { if (srh->sr_suspend_state < DR_SRSTATE_FULL) { /* * Update the signature block. * If cpus are not paused, this can be done now. * See comments below. */ CPU_SIGNATURE(OS_SIG, SIGST_RESUME_INPROGRESS, SIGSUBST_NULL, CPU->cpu_id); } switch (srh->sr_suspend_state) { case DR_SRSTATE_FULL: ASSERT(MUTEX_HELD(&cpu_lock)); /* * Prevent false alarm in tod_validate() due to tod * value change between suspend and resume */ mutex_enter(&tod_lock); tod_status_set(TOD_DR_RESUME_DONE); mutex_exit(&tod_lock); dr_enable_intr(); /* enable intr & clock */ start_cpus(); mutex_exit(&cpu_lock); /* * Update the signature block. * This must not be done while cpus are paused, since on * Starcat the cpu signature update aquires an adaptive * mutex in the iosram driver. Blocking with cpus paused * can lead to deadlock. */ CPU_SIGNATURE(OS_SIG, SIGST_RESUME_INPROGRESS, SIGSUBST_NULL, CPU->cpu_id); /* * If we suspended hw watchdog at suspend, * re-enable it now. */ if (srh->sr_flags & (SR_FLAG_WATCHDOG)) { mutex_enter(&tod_lock); tod_ops.tod_set_watchdog_timer( watchdog_timeout_seconds); mutex_exit(&tod_lock); } /* * This should only be called if drmach_suspend_last() * was called and state transitioned to DR_SRSTATE_FULL * to prevent resume attempts on device instances that * were not previously suspended. */ drmach_resume_first(); /* FALLTHROUGH */ case DR_SRSTATE_DRIVER: /* * resume drivers */ srh->sr_err_idx = 0; /* no parent dip to hold busy */ dr_resume_devices(ddi_root_node(), srh); if (srh->sr_err_idx && srh->sr_dr_handlep) { (srh->sr_dr_handlep)->h_err = drerr_int(ESBD_RESUME, srh->sr_err_ints, srh->sr_err_idx, 1); } /* * resume the lock manager */ lm_cprresume(); /* FALLTHROUGH */ case DR_SRSTATE_USER: /* * finally, resume user threads */ if (!dr_skip_user_threads) { prom_printf("DR: resuming user threads...\n"); dr_start_user_threads(); } /* FALLTHROUGH */ case DR_SRSTATE_BEGIN: default: /* * let those who care know that we've just resumed */ PR_QR("sending SIGTHAW...\n"); dr_signal_user(SIGTHAW); break; } /* * update the signature block */ CPU_SIGNATURE(OS_SIG, SIGST_RUN, SIGSUBST_NULL, CPU->cpu_id); prom_printf("DR: resume COMPLETED\n"); }
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; if (base >= SUN_SBUS_BVADDR || (sparc_cpu_model != sun4c && sparc_cpu_model != sun4)) { /* OK, we can compute the slot number in a * straightforward manner. */ if (sparc_cpu_model == sun4u || sparc_cpu_model == sun4d) sdev->slot = sdev->reg_addrs[0].which_io; else sdev->slot = sbus_dev_slot(base); } else { int rnum; /* Fixups are needed to compute the slot number. */ sdev->slot = sdev->reg_addrs[0].which_io; sdev->reg_addrs[0].phys_addr = sbus_devaddr(sdev->slot, base); for (rnum = 1; rnum < sdev->num_registers; rnum++) { base = (unsigned long) sdev->reg_addrs[rnum].phys_addr; sdev->reg_addrs[rnum].phys_addr = sbus_devaddr(sdev->slot, base); } } 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__ */ }
static void prom_console_write(struct console *con, const char *s, unsigned n) { prom_printf("%s", s); }
/* 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 = 0; /* 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 = (unsigned long)&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(); }
__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; }
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(); }
//Matt void errorlog(int i){ prom_printf("Task %d Test Errors!" ,i ); cli(); for(;;); }
__initfunc(static void fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev)) { int grrr, len; unsigned long dev_base_addr, base; sbus_dev->prom_node = nd; prom_getstring(nd, "name", lbuf, sizeof(lbuf)); strcpy(sbus_dev->prom_name, lbuf); dev_base_addr = prom_getint(nd, "address"); if(dev_base_addr != -1) sbus_dev->sbus_addr = dev_base_addr; len = prom_getproperty(nd, "reg", (void *) sbus_dev->reg_addrs, sizeof(sbus_dev->reg_addrs)); if(len == -1) goto no_regs; if(len%sizeof(struct linux_prom_registers)) { prom_printf("WHOOPS: proplen for %s was %d, need multiple of %d\n", sbus_dev->prom_name, len, (int) sizeof(struct linux_prom_registers)); panic("fill_sbus_device"); } sbus_dev->num_registers = (len/sizeof(struct linux_prom_registers)); sbus_dev->ranges_applied = 0; base = (unsigned long) sbus_dev->reg_addrs[0].phys_addr; if(base>=SUN_SBUS_BVADDR || (sparc_cpu_model != sun4c && sparc_cpu_model != sun4)) { /* Ahh, we can determine the slot and offset */ if(sparc_cpu_model == sun4u) { /* A bit tricky on the SYSIO. */ sbus_dev->slot = sbus_dev->reg_addrs[0].which_io; sbus_dev->offset = sbus_dev_offset(base); } else if (sparc_cpu_model == sun4d) { sbus_dev->slot = sbus_dev->reg_addrs[0].which_io; sbus_dev->offset = base; } else { sbus_dev->slot = sbus_dev_slot(base); sbus_dev->offset = sbus_dev_offset(base); } } else { /* Grrr, gotta do calculations to fix things up */ sbus_dev->slot = sbus_dev->reg_addrs[0].which_io; sbus_dev->offset = base; sbus_dev->reg_addrs[0].phys_addr = sbus_devaddr(sbus_dev->slot, base); for(grrr=1; grrr<sbus_dev->num_registers; grrr++) { base = (unsigned long) sbus_dev->reg_addrs[grrr].phys_addr; sbus_dev->reg_addrs[grrr].phys_addr = sbus_devaddr(sbus_dev->slot, base); } /* That surely sucked */ } sbus_dev->sbus_addr = (unsigned long) sbus_dev->reg_addrs[0].phys_addr; if(len>(sizeof(struct linux_prom_registers)*PROMREG_MAX)) { prom_printf("WHOOPS: I got too many register addresses for %s len=%d\n", sbus_dev->prom_name, len); panic("sbus device register overflow"); } no_regs: len = prom_getproperty(nd, "address", (void *) sbus_dev->sbus_vaddrs, sizeof(sbus_dev->sbus_vaddrs)); if(len == -1) len=0; if(len&3) { prom_printf("Grrr, I didn't get a multiple of 4 proplen " "for device %s got %d\n", sbus_dev->prom_name, len); len=0; } sbus_dev->num_vaddrs = (len/4); #ifdef __sparc_v9__ len = prom_getproperty(nd, "interrupts", (void *)irqs, sizeof(irqs)); if((len == -1) || (len == 0)) { sbus_dev->irqs[0] = 0; sbus_dev->num_irqs = 0; } else { sbus_dev->num_irqs = 1; if (irqs[0].pri < 0x20) sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, irqs[0].pri + (sbus_dev->slot * 8)); else sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, irqs[0].pri); } #else len = prom_getproperty(nd, "intr", (void *)irqs, sizeof(irqs)); if (len == -1) len=0; if (len&7) { prom_printf("Grrr, I didn't get a multiple of 8 proplen for " "device %s got %d\n", sbus_dev->prom_name, len); len=0; } if (len > 4 * 8) { prom_printf("Device %s has more than 4 interrupts\n", sbus_dev->prom_name); len = 4 * 8; } sbus_dev->num_irqs=(len/8); if(sbus_dev->num_irqs == 0) sbus_dev->irqs[0]=0; else if (sparc_cpu_model != sun4d) for (len = 0; len < sbus_dev->num_irqs; len++) sbus_dev->irqs[len] = irqs[len].pri; else { extern unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq); for (len = 0; len < sbus_dev->num_irqs; len++) sbus_dev->irqs[len] = sun4d_build_irq(sbus_dev, irqs[len].pri); } #endif #ifdef DEBUG_FILL #ifdef __sparc_v9__ prom_printf("Found %s at SBUS slot %x offset %016lx ", sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset); if (sbus_dev->irqs[0]) prom_printf("irq %s\n", __irq_itoa(sbus_dev->irqs[0])); else prom_printf("\n"); prom_printf("Base address %016lx\n", sbus_dev->sbus_addr); #else prom_printf("Found %s at SBUS slot %x offset %08lx irq-level %d\n", sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset, sbus_dev->irqs[0]); prom_printf("Base address %08lx\n", sbus_dev->sbus_addr); #endif prom_printf("REGISTERS: Probed %d register(s)\n", sbus_dev->num_registers); for(len=0; len<sbus_dev->num_registers; len++) #ifdef __sparc_v9__ prom_printf("Regs<%d> at address<%08lx> IO-space<%d> size<%d " "bytes, %d words>\n", (int) len, (unsigned long) sbus_dev->reg_addrs[len].phys_addr, sbus_dev->reg_addrs[len].which_io, sbus_dev->reg_addrs[len].reg_size, (sbus_dev->reg_addrs[len].reg_size/4)); #else prom_printf("Regs<%d> at address<%016lx> IO-space<%d> size<%d " "bytes, %d words>\n", (int) len, (unsigned long) sbus_dev->reg_addrs[len].phys_addr, sbus_dev->reg_addrs[len].which_io, sbus_dev->reg_addrs[len].reg_size, (sbus_dev->reg_addrs[len].reg_size/4)); #endif #endif }