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

📄 mf.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* * The primary partition VSP object is acknowledging the receipt * of a flow we sent to them.  If there are other flows queued * up, we must send another one now... */static void handle_ack(struct io_mf_lp_event *event){	unsigned long flags;	struct pending_event *two = NULL;	unsigned long free_it = 0;	struct ce_msg_data *ce_msg_data;	struct ce_msg_data *pce_msg_data;	struct vsp_rsp_data *rsp;	/* handle current event */	if (pending_event_head == NULL) {		printk(KERN_ERR "mf.c: stack empty for receiving ack\n");		return;	}	switch (event->hp_lp_event.xSubtype) {	case 0:     /* CE msg */		ce_msg_data = &event->data.ce_msg;		if (ce_msg_data->ce_msg[3] != 0x40) {			free_it = 1;			break;		}		if (ce_msg_data->ce_msg[2] == 0)			break;		free_it = 1;		pce_msg_data = &pending_event_head->event.data.ce_msg;		if (pce_msg_data->completion != NULL) {			ce_msg_comp_hdlr handler =				pce_msg_data->completion->handler;			void *token = pce_msg_data->completion->token;			if (handler != NULL)				(*handler)(token, ce_msg_data);		}		break;	case 4:	/* allocate */	case 5:	/* deallocate */		if (pending_event_head->hdlr != NULL)			(*pending_event_head->hdlr)((void *)event->hp_lp_event.xCorrelationToken, event->data.alloc.count);		free_it = 1;		break;	case 6:		free_it = 1;		rsp = (struct vsp_rsp_data *)event->data.vsp_cmd.token;		if (rsp == NULL) {			printk(KERN_ERR "mf.c: no rsp\n");			break;		}		if (rsp->response != NULL)			memcpy(rsp->response, &event->data.vsp_cmd,					sizeof(event->data.vsp_cmd));		complete(&rsp->com);		break;	}	/* remove from queue */	spin_lock_irqsave(&pending_event_spinlock, flags);	if ((pending_event_head != NULL) && (free_it == 1)) {		struct pending_event *oldHead = pending_event_head;		pending_event_head = pending_event_head->next;		two = pending_event_head;		free_pending_event(oldHead);	}	spin_unlock_irqrestore(&pending_event_spinlock, flags);	/* send next waiting event */	if (two != NULL)		signal_event(NULL);}/* * This is the generic event handler we are registering with * the Hypervisor.  Ensure the flows are for us, and then * parse it enough to know if it is an interrupt or an * acknowledge. */static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs){	if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {		switch(event->xFlags.xFunction) {		case HvLpEvent_Function_Ack:			handle_ack((struct io_mf_lp_event *)event);			break;		case HvLpEvent_Function_Int:			handle_int((struct io_mf_lp_event *)event);			break;		default:			printk(KERN_ERR "mf.c: non ack/int event received\n");			break;		}	} else		printk(KERN_ERR "mf.c: alien event received\n");}/* * Global kernel interface to allocate and seed events into the * Hypervisor. */void mf_allocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,		unsigned size, unsigned count, MFCompleteHandler hdlr,		void *user_token){	struct pending_event *ev = new_pending_event();	int rc;	if (ev == NULL) {		rc = -ENOMEM;	} else {		ev->event.hp_lp_event.xSubtype = 4;		ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;		ev->event.hp_lp_event.x.xSubtypeData =			subtype_data('M', 'F', 'M', 'A');		ev->event.data.alloc.target_lp = target_lp;		ev->event.data.alloc.type = type;		ev->event.data.alloc.size = size;		ev->event.data.alloc.count = count;		ev->hdlr = hdlr;		rc = signal_event(ev);	}	if ((rc != 0) && (hdlr != NULL))		(*hdlr)(user_token, rc);}EXPORT_SYMBOL(mf_allocate_lp_events);/* * Global kernel interface to unseed and deallocate events already in * Hypervisor. */void mf_deallocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,		unsigned count, MFCompleteHandler hdlr, void *user_token){	struct pending_event *ev = new_pending_event();	int rc;	if (ev == NULL)		rc = -ENOMEM;	else {		ev->event.hp_lp_event.xSubtype = 5;		ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;		ev->event.hp_lp_event.x.xSubtypeData =			subtype_data('M', 'F', 'M', 'D');		ev->event.data.alloc.target_lp = target_lp;		ev->event.data.alloc.type = type;		ev->event.data.alloc.count = count;		ev->hdlr = hdlr;		rc = signal_event(ev);	}	if ((rc != 0) && (hdlr != NULL))		(*hdlr)(user_token, rc);}EXPORT_SYMBOL(mf_deallocate_lp_events);/* * Global kernel interface to tell the VSP object in the primary * partition to power this partition off. */void mf_power_off(void){	printk(KERN_INFO "mf.c: Down it goes...\n");	signal_ce_msg_simple(0x4d, NULL);	for (;;)		;}/* * Global kernel interface to tell the VSP object in the primary * partition to reboot this partition. */void mf_reboot(void){	printk(KERN_INFO "mf.c: Preparing to bounce...\n");	signal_ce_msg_simple(0x4e, NULL);	for (;;)		;}/* * Display a single word SRC onto the VSP control panel. */void mf_display_src(u32 word){	u8 ce[12];	memset(ce, 0, sizeof(ce));	ce[3] = 0x4a;	ce[7] = 0x01;	ce[8] = word >> 24;	ce[9] = word >> 16;	ce[10] = word >> 8;	ce[11] = word;	signal_ce_msg(ce, NULL);}/* * Display a single word SRC of the form "PROGXXXX" on the VSP control panel. */void mf_display_progress(u16 value){	u8 ce[12];	u8 src[72];	memcpy(ce, "\x00\x00\x04\x4A\x00\x00\x00\x48\x00\x00\x00\x00", 12);	memcpy(src, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"		"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"		"\x00\x00\x00\x00PROGxxxx                        ",		72);	src[6] = value >> 8;	src[7] = value & 255;	src[44] = "0123456789ABCDEF"[(value >> 12) & 15];	src[45] = "0123456789ABCDEF"[(value >> 8) & 15];	src[46] = "0123456789ABCDEF"[(value >> 4) & 15];	src[47] = "0123456789ABCDEF"[value & 15];	dma_and_signal_ce_msg(ce, NULL, src, sizeof(src), 9 * 64 * 1024);}/* * Clear the VSP control panel.  Used to "erase" an SRC that was * previously displayed. */void mf_clear_src(void){	signal_ce_msg_simple(0x4b, NULL);}/* * Initialization code here. */void mf_init(void){	int i;	/* initialize */	spin_lock_init(&pending_event_spinlock);	for (i = 0;	     i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc);	     ++i)		free_pending_event(&pending_event_prealloc[i]);	HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler);	/* virtual continue ack */	signal_ce_msg_simple(0x57, NULL);	/* initialization complete */	printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities "			"initialized\n");}struct rtc_time_data {	struct completion com;	struct ce_msg_data ce_msg;	int rc;};static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg){	struct rtc_time_data *rtc = token;	memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));	rtc->rc = 0;	complete(&rtc->com);}static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm){	tm->tm_wday = 0;	tm->tm_yday = 0;	tm->tm_isdst = 0;	if (rc) {		tm->tm_sec = 0;		tm->tm_min = 0;		tm->tm_hour = 0;		tm->tm_mday = 15;		tm->tm_mon = 5;		tm->tm_year = 52;		return rc;	}	if ((ce_msg[2] == 0xa9) ||	    (ce_msg[2] == 0xaf)) {		/* TOD clock is not set */		tm->tm_sec = 1;		tm->tm_min = 1;		tm->tm_hour = 1;		tm->tm_mday = 10;		tm->tm_mon = 8;		tm->tm_year = 71;		mf_set_rtc(tm);	}	{		u8 year = ce_msg[5];		u8 sec = ce_msg[6];		u8 min = ce_msg[7];		u8 hour = ce_msg[8];		u8 day = ce_msg[10];		u8 mon = ce_msg[11];		BCD_TO_BIN(sec);		BCD_TO_BIN(min);		BCD_TO_BIN(hour);		BCD_TO_BIN(day);		BCD_TO_BIN(mon);		BCD_TO_BIN(year);		if (year <= 69)			year += 100;		tm->tm_sec = sec;		tm->tm_min = min;		tm->tm_hour = hour;		tm->tm_mday = day;		tm->tm_mon = mon;		tm->tm_year = year;	}	return 0;}int mf_get_rtc(struct rtc_time *tm){	struct ce_msg_comp_data ce_complete;	struct rtc_time_data rtc_data;	int rc;	memset(&ce_complete, 0, sizeof(ce_complete));	memset(&rtc_data, 0, sizeof(rtc_data));	init_completion(&rtc_data.com);	ce_complete.handler = &get_rtc_time_complete;	ce_complete.token = &rtc_data;	rc = signal_ce_msg_simple(0x40, &ce_complete);	if (rc)		return rc;	wait_for_completion(&rtc_data.com);	return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);}struct boot_rtc_time_data {	int busy;	struct ce_msg_data ce_msg;	int rc;};static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg){	struct boot_rtc_time_data *rtc = token;	memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));	rtc->rc = 0;	rtc->busy = 0;}int mf_get_boot_rtc(struct rtc_time *tm){	struct ce_msg_comp_data ce_complete;	struct boot_rtc_time_data rtc_data;	int rc;	memset(&ce_complete, 0, sizeof(ce_complete));	memset(&rtc_data, 0, sizeof(rtc_data));	rtc_data.busy = 1;	ce_complete.handler = &get_boot_rtc_time_complete;	ce_complete.token = &rtc_data;	rc = signal_ce_msg_simple(0x40, &ce_complete);	if (rc)		return rc;	/* We need to poll here as we are not yet taking interrupts */	while (rtc_data.busy) {		if (hvlpevent_is_pending())			process_hvlpevents(NULL);	}	return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);}int mf_set_rtc(struct rtc_time *tm){	char ce_time[12];	u8 day, mon, hour, min, sec, y1, y2;	unsigned year;	year = 1900 + tm->tm_year;	y1 = year / 100;	y2 = year % 100;	sec = tm->tm_sec;	min = tm->tm_min;	hour = tm->tm_hour;	day = tm->tm_mday;	mon = tm->tm_mon + 1;	BIN_TO_BCD(sec);	BIN_TO_BCD(min);	BIN_TO_BCD(hour);	BIN_TO_BCD(mon);	BIN_TO_BCD(day);	BIN_TO_BCD(y1);	BIN_TO_BCD(y2);	memset(ce_time, 0, sizeof(ce_time));	ce_time[3] = 0x41;	ce_time[4] = y1;	ce_time[5] = y2;	ce_time[6] = sec;	ce_time[7] = min;	ce_time[8] = hour;	ce_time[10] = day;	ce_time[11] = mon;	return signal_ce_msg(ce_time, NULL);}#ifdef CONFIG_PROC_FSstatic int proc_mf_dump_cmdline(char *page, char **start, off_t off,		int count, int *eof, void *data){	int len;	char *p;	struct vsp_cmd_data vsp_cmd;	int rc;	dma_addr_t dma_addr;

⌨️ 快捷键说明

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