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

📄 consolemap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * * A font has at most 512 chars, usually 256. * But one font position may represent several Unicode chars. * A hashtable is somewhat of a pain to deal with, so use a * "paged table" instead.  Simulation has shown the memory cost of * this 3-level paged table scheme to be comparable to a hash table. */extern u8 dfont_unicount[];	/* Defined in console_defmap.c */extern u16 dfont_unitable[];static void con_release_unimap(struct uni_pagedir *p){	u16 **p1;	int i, j;	if (p == dflt) dflt = NULL;  	for (i = 0; i < 32; i++) {		if ((p1 = p->uni_pgdir[i]) != NULL) {			for (j = 0; j < 32; j++)				kfree(p1[j]);			kfree(p1);		}		p->uni_pgdir[i] = NULL;	}	for (i = 0; i < 4; i++) {		kfree(p->inverse_translations[i]);		p->inverse_translations[i] = NULL;	}	if (p->inverse_trans_unicode) {		kfree(p->inverse_trans_unicode);		p->inverse_trans_unicode = NULL;	}}void con_free_unimap(struct vc_data *vc){	struct uni_pagedir *p;	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;	if (!p)		return;	*vc->vc_uni_pagedir_loc = 0;	if (--p->refcount)		return;	con_release_unimap(p);	kfree(p);}  static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p){	int i, j, k;	struct uni_pagedir *q;		for (i = 0; i < MAX_NR_CONSOLES; i++) {		if (!vc_cons_allocated(i))			continue;		q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;		if (!q || q == p || q->sum != p->sum)			continue;		for (j = 0; j < 32; j++) {			u16 **p1, **q1;			p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];			if (!p1 && !q1)				continue;			if (!p1 || !q1)				break;			for (k = 0; k < 32; k++) {				if (!p1[k] && !q1[k])					continue;				if (!p1[k] || !q1[k])					break;				if (memcmp(p1[k], q1[k], 64*sizeof(u16)))					break;			}			if (k < 32)				break;		}		if (j == 32) {			q->refcount++;			*conp->vc_uni_pagedir_loc = (unsigned long)q;			con_release_unimap(p);			kfree(p);			return 1;		}	}	return 0;}static intcon_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos){	int i, n;	u16 **p1, *p2;	if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {		p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);		if (!p1) return -ENOMEM;		for (i = 0; i < 32; i++)			p1[i] = NULL;	}	if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {		p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);		if (!p2) return -ENOMEM;		memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */	}	p2[unicode & 0x3f] = fontpos;		p->sum += (fontpos << 20) + unicode;	return 0;}/* ui is a leftover from using a hashtable, but might be used again */int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui){	struct uni_pagedir *p, *q;  	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;	if (p && p->readonly) return -EIO;	if (!p || --p->refcount) {		q = kzalloc(sizeof(*p), GFP_KERNEL);		if (!q) {			if (p) p->refcount++;			return -ENOMEM;		}		q->refcount=1;		*vc->vc_uni_pagedir_loc = (unsigned long)q;	} else {		if (p == dflt) dflt = NULL;		p->refcount++;		p->sum = 0;		con_release_unimap(p);	}	return 0;}int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list){	int err = 0, err1, i;	struct uni_pagedir *p, *q;	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;	if (p->readonly) return -EIO;		if (!ct) return 0;		if (p->refcount > 1) {		int j, k;		u16 **p1, *p2, l;				err1 = con_clear_unimap(vc, NULL);		if (err1) return err1;				q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;		for (i = 0, l = 0; i < 32; i++)		if ((p1 = p->uni_pgdir[i]))			for (j = 0; j < 32; j++)			if ((p2 = p1[j]))				for (k = 0; k < 64; k++, l++)				if (p2[k] != 0xffff) {					err1 = con_insert_unipair(q, l, p2[k]);					if (err1) {						p->refcount++;						*vc->vc_uni_pagedir_loc = (unsigned long)p;						con_release_unimap(q);						kfree(q);						return err1; 					}              			}              	p = q;	} else if (p == dflt)		dflt = NULL;		while (ct--) {		unsigned short unicode, fontpos;		__get_user(unicode, &list->unicode);		__get_user(fontpos, &list->fontpos);		if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)			err = err1;			list++;	}		if (con_unify_unimap(vc, p))		return err;	for (i = 0; i <= 3; i++)		set_inverse_transl(vc, p, i); /* Update all inverse translations */	set_inverse_trans_unicode(vc, p);  	return err;}/* Loads the unimap for the hardware font, as defined in uni_hash.tbl.   The representation used was the most compact I could come up   with.  This routine is executed at sys_setup time, and when the   PIO_FONTRESET ioctl is called. */int con_set_default_unimap(struct vc_data *vc){	int i, j, err = 0, err1;	u16 *q;	struct uni_pagedir *p;	if (dflt) {		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;		if (p == dflt)			return 0;		dflt->refcount++;		*vc->vc_uni_pagedir_loc = (unsigned long)dflt;		if (p && --p->refcount) {			con_release_unimap(p);			kfree(p);		}		return 0;	}		/* The default font is always 256 characters */	err = con_clear_unimap(vc, NULL);	if (err) return err;    	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;	q = dfont_unitable;		for (i = 0; i < 256; i++)		for (j = dfont_unicount[i]; j; j--) {			err1 = con_insert_unipair(p, *(q++), i);			if (err1)				err = err1;		}				if (con_unify_unimap(vc, p)) {		dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;		return err;	}	for (i = 0; i <= 3; i++)		set_inverse_transl(vc, p, i);	/* Update all inverse translations */	set_inverse_trans_unicode(vc, p);	dflt = p;	return err;}EXPORT_SYMBOL(con_set_default_unimap);int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc){	struct uni_pagedir *q;	if (!*src_vc->vc_uni_pagedir_loc)		return -EINVAL;	if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)		return 0;	con_free_unimap(dst_vc);	q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;	q->refcount++;	*dst_vc->vc_uni_pagedir_loc = (long)q;	return 0;}int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list){	int i, j, k, ect;	u16 **p1, *p2;	struct uni_pagedir *p;	ect = 0;	if (*vc->vc_uni_pagedir_loc) {		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;		for (i = 0; i < 32; i++)		if ((p1 = p->uni_pgdir[i]))			for (j = 0; j < 32; j++)			if ((p2 = *(p1++)))				for (k = 0; k < 64; k++) {					if (*p2 < MAX_GLYPH && ect++ < ct) {						__put_user((u_short)((i<<11)+(j<<6)+k),							   &list->unicode);						__put_user((u_short) *p2, 							   &list->fontpos);						list++;					}					p2++;				}	}	__put_user(ect, uct);	return ((ect <= ct) ? 0 : -ENOMEM);}void con_protect_unimap(struct vc_data *vc, int rdonly){	struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;		if (p)		p->readonly = rdonly;}/* * Always use USER_MAP. These functions are used by the keyboard, * which shouldn't be affected by G0/G1 switching, etc. * If the user map still contains default values, i.e. the * direct-to-font mapping, then assume user is using Latin1. *//* may be called during an interrupt */u32 conv_8bit_to_uni(unsigned char c){	unsigned short uni = translations[USER_MAP][c];	return uni == (0xf000 | c) ? c : uni;}int conv_uni_to_8bit(u32 uni){	int c;	for (c = 0; c < 0x100; c++)		if (translations[USER_MAP][c] == uni ||		   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))			return c;	return -1;}intconv_uni_to_pc(struct vc_data *conp, long ucs) {	int h;	u16 **p1, *p2;	struct uni_pagedir *p;  	/* Only 16-bit codes supported at this time */	if (ucs > 0xffff)		return -4;		/* Not found */	else if (ucs < 0x20)		return -1;		/* Not a printable character */	else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))		return -2;			/* Zero-width space */	/*	 * UNI_DIRECT_BASE indicates the start of the region in the User Zone	 * which always has a 1:1 mapping to the currently loaded font.  The	 * UNI_DIRECT_MASK indicates the bit span of the region.	 */	else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)		return ucs & UNI_DIRECT_MASK;  	if (!*conp->vc_uni_pagedir_loc)		return -3;	p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;  	if ((p1 = p->uni_pgdir[ucs >> 11]) &&	    (p2 = p1[(ucs >> 6) & 0x1f]) &&	    (h = p2[ucs & 0x3f]) < MAX_GLYPH)		return h;	return -4;		/* not found */}/* * This is called at sys_setup time, after memory and the console are * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL) * from this function, hence the call from sys_setup. */void __init console_map_init(void){	int i;		for (i = 0; i < MAX_NR_CONSOLES; i++)		if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)			con_set_default_unimap(vc_cons[i].d);}EXPORT_SYMBOL(con_copy_unimap);

⌨️ 快捷键说明

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