⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pseries_lpar.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
字号:
/* * pSeries_lpar.c * Copyright (C) 2001 Todd Inglett, IBM Corporation * * pSeries LPAR support. *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */#include <linux/config.h>#include <linux/kernel.h>#include <linux/fs.h>#include <asm/processor.h>#include <asm/semaphore.h>#include <asm/mmu.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/machdep.h>#include <asm/abs_addr.h>#include <asm/mmu_context.h>#include <asm/ppcdebug.h>#include <asm/pci_dma.h>#include <linux/pci.h>#include <asm/naca.h>#include <asm/hvcall.h>long plpar_tce_get(unsigned long liobn,		   unsigned long ioba,		   unsigned long *tce_ret){	unsigned long dummy;	return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0,			   tce_ret, &dummy, &dummy);}long plpar_tce_put(unsigned long liobn,		   unsigned long ioba,		   unsigned long tceval){	return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval);}long plpar_get_term_char(unsigned long termno,			 unsigned long *len_ret,			 char *buf_ret){	unsigned long *lbuf = (unsigned long *)buf_ret;  /* ToDo: alignment? */	return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0,			   len_ret, lbuf+0, lbuf+1);}long plpar_put_term_char(unsigned long termno,			 unsigned long len,			 const char *buffer){	unsigned long dummy;	unsigned long *lbuf = (unsigned long *)buffer;  /* ToDo: alignment? */	return plpar_hcall(H_PUT_TERM_CHAR, termno, len,			   lbuf[0], lbuf[1], &dummy, &dummy, &dummy);}long plpar_eoi(unsigned long xirr){	return plpar_hcall_norets(H_EOI, xirr);}long plpar_cppr(unsigned long cppr){	return plpar_hcall_norets(H_CPPR, cppr);}long plpar_ipi(unsigned long servernum,	       unsigned long mfrr){	return plpar_hcall_norets(H_IPI, servernum, mfrr);}long plpar_xirr(unsigned long *xirr_ret){	unsigned long dummy;	return plpar_hcall(H_XIRR, 0, 0, 0, 0,			   xirr_ret, &dummy, &dummy);}long plpar_ipoll(unsigned long servernum, unsigned long* xirr_ret, unsigned long* mfrr_ret){	unsigned long dummy;	return plpar_hcall(H_IPOLL, servernum, 0, 0, 0,			   xirr_ret, mfrr_ret, &dummy);}static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, 				unsigned long uaddr, int direction ){	u64 set_tce_rc;	union Tce tce;		PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr);	PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n", 	       tcenum, tbl, tbl->index);	tce.wholeTce = 0;	tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT;	tce.tceBits.readWrite = 1;	if ( direction != PCI_DMA_TODEVICE ) tce.tceBits.pciWrite = 1;	set_tce_rc = plpar_tce_put((u64)tbl->index, 				 (u64)tcenum << 12, 				 tce.wholeTce );	if(set_tce_rc) {		printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", set_tce_rc);		printk("\tindex   = 0x%lx\n", (u64)tbl->index);		printk("\ttcenum  = 0x%lx\n", (u64)tcenum);		printk("\ttce val = 0x%lx\n", tce.wholeTce );	}}static void tce_free_one_pSeriesLP(struct TceTable *tbl, long tcenum){	u64 set_tce_rc;	union Tce tce;	tce.wholeTce = 0;	set_tce_rc = plpar_tce_put((u64)tbl->index, 				 (u64)tcenum << 12,				 tce.wholeTce );	if ( set_tce_rc ) {		printk("tce_free_one_pSeriesLP: plpar_tce_put failed\n");		printk("\trc      = %ld\n", set_tce_rc);		printk("\tindex   = 0x%lx\n", (u64)tbl->index);		printk("\ttcenum  = 0x%lx\n", (u64)tcenum);		printk("\ttce val = 0x%lx\n", tce.wholeTce );	}}/* PowerPC Interrupts for lpar. *//* NOTE: this typedef is duplicated (for now) from xics.c! */typedef struct {	int (*xirr_info_get)(int cpu);	void (*xirr_info_set)(int cpu, int val);	void (*cppr_info)(int cpu, u8 val);	void (*qirr_info)(int cpu, u8 val);} xics_ops;static int pSeriesLP_xirr_info_get(int n_cpu){	unsigned long lpar_rc;	unsigned long return_value; 	lpar_rc = plpar_xirr(&return_value);	if (lpar_rc != H_Success) {		panic(" bad return code xirr - rc = %lx \n", lpar_rc); 	}	return ((int)(return_value));}static void pSeriesLP_xirr_info_set(int n_cpu, int value){	unsigned long lpar_rc;	unsigned long val64 = value & 0xffffffff;	lpar_rc = plpar_eoi(val64);	if (lpar_rc != H_Success) {		panic(" bad return code EOI - rc = %ld, value=%lx \n", lpar_rc, val64); 	}}static void pSeriesLP_cppr_info(int n_cpu, u8 value){	unsigned long lpar_rc;	lpar_rc = plpar_cppr(value);	if (lpar_rc != H_Success) {		panic(" bad return code cppr - rc = %lx \n", lpar_rc); 	}}static void pSeriesLP_qirr_info(int n_cpu , u8 value){	unsigned long lpar_rc;	lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu),value);	if (lpar_rc != H_Success) {    udbg_printf("pSeriesLP_qirr_info - plpar_ipi failed!!!!!!!! \n");		panic(" bad return code qirr -ipi  - rc = %lx \n", lpar_rc); 	}}xics_ops pSeriesLP_ops = {	pSeriesLP_xirr_info_get,	pSeriesLP_xirr_info_set,	pSeriesLP_cppr_info,	pSeriesLP_qirr_info};/* end TAI-LPAR */int vtermno;	/* virtual terminal# for udbg  */static void udbg_putcLP(unsigned char c){	char buf[16];	unsigned long rc;	if (c == '\n')		udbg_putcLP('\r');	buf[0] = c;	do {		rc = plpar_put_term_char(vtermno, 1, buf);	} while(rc == H_Busy);}/* Buffered chars getc */static long inbuflen;static long inbuf[2];	/* must be 2 longs */static int udbg_getc_pollLP(void){	/* The interface is tricky because it may return up to 16 chars.	 * We save them statically for future calls to udbg_getc().	 */	char ch, *buf = (char *)inbuf;	int i;	long rc;	if (inbuflen == 0) {		/* get some more chars. */		inbuflen = 0;		rc = plpar_get_term_char(vtermno, &inbuflen, buf);		if (rc != H_Success)			inbuflen = 0;	/* otherwise inbuflen is garbage */	}	if (inbuflen <= 0 || inbuflen > 16) {		/* Catch error case as well as other oddities (corruption) */		inbuflen = 0;		return -1;	}	ch = buf[0];	for (i = 1; i < inbuflen; i++)	/* shuffle them down. */		buf[i-1] = buf[i];	inbuflen--;	return ch;}static unsigned char udbg_getcLP(void){	int ch;	for (;;) {		ch = udbg_getc_pollLP();		if (ch == -1) {			/* This shouldn't be needed...but... */			volatile unsigned long delay;			for (delay=0; delay < 2000000; delay++)				;		} else {			return ch;		}	}}/* Code for hvc_console.  Should move it back eventually. */int hvc_get_chars(int index, char *buf, int count){	unsigned long got;	if (plpar_hcall(H_GET_TERM_CHAR, index, 0, 0, 0, &got,		(unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {		/*		 * Work around a HV bug where it gives us a null		 * after every \r.  -- paulus		 */		if (got > 0) {			int i;			for (i = 1; i < got; ++i) {				if (buf[i] == 0 && buf[i-1] == '\r') {					--got;					if (i < got)						memmove(&buf[i], &buf[i+1],							got - i);				}			}		}		return got;	}	return 0;}int hvc_put_chars(int index, const char *buf, int count){	unsigned long dummy;	unsigned long *lbuf = (unsigned long *) buf;	long ret;	ret = plpar_hcall(H_PUT_TERM_CHAR, index, count, lbuf[0], lbuf[1],			  &dummy, &dummy, &dummy);	if (ret == H_Success)		return count;	if (ret == H_Busy)		return 0;	return -1;}int hvc_count(int *start_termno){	u32 *termno;	struct device_node *dn;	if ((dn = find_path_device("/rtas")) != NULL) {		if ((termno = (u32 *)get_property(dn, "ibm,termno", 0)) != NULL) {			if (start_termno)				*start_termno = termno[0];			return termno[1];		}	}	return 0;}#ifndef CONFIG_PPC_ISERIESvoid pSeries_lpar_mm_init(void);/* This is called early in setup.c. * Use it to setup page table ppc_md stuff as well as udbg. */void pSeriesLP_init_early(void){	pSeries_lpar_mm_init();	ppc_md.tce_build	 = tce_build_pSeriesLP;	ppc_md.tce_free_one	 = tce_free_one_pSeriesLP;#ifdef CONFIG_SMP	smp_init_pSeries();#endif	pSeries_pcibios_init_early();	/* The keyboard is not useful in the LPAR environment.	 * Leave all the interfaces NULL.	 */	/* lookup the first virtual terminal number in case we don't have a com port.	 * Zero is probably correct in case someone calls udbg before the init.	 * The property is a pair of numbers.  The first is the starting termno (the	 * one we use) and the second is the number of terminals.	 */	u32 *termno;	struct device_node *np = find_path_device("/rtas");	if (np) {		termno = (u32 *)get_property(np, "ibm,termno", 0);		if (termno)			vtermno = termno[0];	}	ppc_md.udbg_putc = udbg_putcLP;	ppc_md.udbg_getc = udbg_getcLP;	ppc_md.udbg_getc_poll = udbg_getc_pollLP;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -