示例#1
0
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];
}
示例#2
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;
		}
示例#3
0
文件: promcon.c 项目: wxlong/Test
static __inline__ void
promcon_puts(char *buf, int cnt)
{
	prom_printf("%*.*s", cnt, cnt, buf);
}
示例#4
0
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;
	}
}
示例#5
0
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);
}
示例#6
0
__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
}
示例#7
0
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");
}
示例#8
0
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();
}
示例#9
0
__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
}
示例#10
0
int fputs(const char *s, FILE *stream)
{
	prom_printf("%s", s);

	return 0;
}
示例#11
0
static void __init should_not_happen(void)
{
	prom_printf(shouldnothappen);
	prom_halt();
}
示例#12
0
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];
			}
		}
	}
}
示例#13
0
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);
	}
示例#14
0
/* 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")) {
示例#15
0
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
}
示例#16
0
文件: ip22-mc.c 项目: TitaniumBoy/lin
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 */
}
示例#17
0
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__ */
}
示例#18
0
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 */
}
示例#19
0
__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. */
}
示例#20
0
文件: cfg.c 项目: arnew/yaboot
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;
}
示例#21
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);
}
示例#22
0
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;
}
示例#23
0
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");
}
示例#24
0
文件: sbus.c 项目: dmgerman/original
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__ */
}
示例#25
0
static void
prom_console_write(struct console *con, const char *s, unsigned n)
{
	prom_printf("%s", s);
}
示例#26
0
文件: time.c 项目: sarnobat/knoppix
/* 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();
}
示例#27
0
__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;
}
示例#28
0
文件: time.c 项目: sarnobat/knoppix
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();
}
示例#29
0
//Matt
void errorlog(int i){
	prom_printf("Task %d Test Errors!" ,i );
	cli();
	for(;;);
}
示例#30
0
__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
}