📄 mf.c
字号:
if (ev == NULL) { rc = -ENOMEM; } else { union safe_cast mine; mine.ptr = userToken; ev->event.hp_lp_event.xSubtype = 4; ev->event.hp_lp_event.xCorrelationToken = mine.ptr_as_u64; ev->event.hp_lp_event.x.xSubtypeData = subtype_data('M', 'F', 'M', 'A'); ev->event.data.alloc.target_lp = targetLp; 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)(userToken, rc);}EXPORT_SYMBOL(mf_allocateLpEvents);/* * Global kernel interface to unseed and deallocate events already in * Hypervisor. */void mf_deallocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, unsigned count, MFCompleteHandler hdlr, void *userToken){ struct pending_event *ev = new_pending_event(); int rc; if (ev == NULL) rc = -ENOMEM; else { union safe_cast mine; mine.ptr = userToken; ev->event.hp_lp_event.xSubtype = 5; ev->event.hp_lp_event.xCorrelationToken = mine.ptr_as_u64; ev->event.hp_lp_event.x.xSubtypeData = subtype_data('M', 'F', 'M', 'D'); ev->event.data.alloc.target_lp = targetLp; 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)(userToken, rc);}EXPORT_SYMBOL(mf_deallocateLpEvents);/* * Global kernel interface to tell the VSP object in the primary * partition to power this partition off. */void mf_powerOff(void){ printk(KERN_INFO "mf.c: Down it goes...\n"); signal_ce_msg("\x00\x00\x00\x4D\x00\x00\x00\x00\x00\x00\x00\x00", 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("\x00\x00\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x00", NULL); for (;;);}/* * Display a single word SRC onto the VSP control panel. */void mf_displaySrc(u32 word){ u8 ce[12]; memcpy(ce, "\x00\x00\x00\x4A\x00\x00\x00\x01\x00\x00\x00\x00", 12); 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_displayProgress(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_clearSrc(void){ signal_ce_msg("\x00\x00\x00\x4B\x00\x00\x00\x00\x00\x00\x00\x00", 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, &hvHandler); /* virtual continue ack */ signal_ce_msg("\x00\x00\x00\x57\x00\x00\x00\x00\x00\x00\x00\x00", NULL); /* initialization complete */ printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities initialized\n");}void mf_setSide(char side){ u64 newSide; struct VspCmdData myVspCmd; memset(&myVspCmd, 0, sizeof(myVspCmd)); switch (side) { case 'A': newSide = 0; break; case 'B': newSide = 1; break; case 'C': newSide = 2; break; default: newSide = 3; break; } myVspCmd.sub_data.ipl_type = newSide; myVspCmd.cmd = 10; (void)signal_vsp_instruction(&myVspCmd);}char mf_getSide(void){ char returnValue = ' '; int rc = 0; struct VspCmdData myVspCmd; memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.cmd = 2; myVspCmd.sub_data.ipl_type = 0; mb(); rc = signal_vsp_instruction(&myVspCmd); if (rc != 0) return returnValue; if (myVspCmd.result_code == 0) { switch (myVspCmd.sub_data.ipl_type) { case 0: returnValue = 'A'; break; case 1: returnValue = 'B'; break; case 2: returnValue = 'C'; break; default: returnValue = 'D'; break; } } return returnValue;}void mf_getSrcHistory(char *buffer, int size){#if 0 struct IplTypeReturnStuff returnStuff; struct pending_event *ev = new_pending_event(); int rc = 0; char *pages[4]; pages[0] = kmalloc(4096, GFP_ATOMIC); pages[1] = kmalloc(4096, GFP_ATOMIC); pages[2] = kmalloc(4096, GFP_ATOMIC); pages[3] = kmalloc(4096, GFP_ATOMIC); if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL) || (pages[2] == NULL) || (pages[3] == NULL)) return -ENOMEM; returnStuff.xType = 0; returnStuff.xRc = 0; returnStuff.xDone = 0; ev->event.hp_lp_event.xSubtype = 6; ev->event.hp_lp_event.x.xSubtypeData = subtype_data('M', 'F', 'V', 'I'); ev->event.data.vsp_cmd.xEvent = &returnStuff; ev->event.data.vsp_cmd.cmd = 4; ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex(); ev->event.data.vsp_cmd.result_code = 0xFF; ev->event.data.vsp_cmd.reserved = 0; ev->event.data.vsp_cmd.sub_data.page[0] = ISERIES_HV_ADDR(pages[0]); ev->event.data.vsp_cmd.sub_data.page[1] = ISERIES_HV_ADDR(pages[1]); ev->event.data.vsp_cmd.sub_data.page[2] = ISERIES_HV_ADDR(pages[2]); ev->event.data.vsp_cmd.sub_data.page[3] = ISERIES_HV_ADDR(pages[3]); mb(); if (signal_event(ev) != 0) return; while (returnStuff.xDone != 1) udelay(10); if (returnStuff.xRc == 0) memcpy(buffer, pages[0], size); kfree(pages[0]); kfree(pages[1]); kfree(pages[2]); kfree(pages[3]);#endif}void mf_setCmdLine(const char *cmdline, int size, u64 side){ struct VspCmdData myVspCmd; dma_addr_t dma_addr = 0; char *page = dma_alloc_coherent(iSeries_vio_dev, size, &dma_addr, GFP_ATOMIC); if (page == NULL) { printk(KERN_ERR "mf.c: couldn't allocate memory to set command line\n"); return; } copy_from_user(page, cmdline, size); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.cmd = 31; myVspCmd.sub_data.kern.token = dma_addr; myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; myVspCmd.sub_data.kern.side = side; myVspCmd.sub_data.kern.length = size; mb(); (void)signal_vsp_instruction(&myVspCmd); dma_free_coherent(iSeries_vio_dev, size, page, dma_addr);}int mf_getCmdLine(char *cmdline, int *size, u64 side){ struct VspCmdData myVspCmd; int rc; int len = *size; dma_addr_t dma_addr; dma_addr = dma_map_single(iSeries_vio_dev, cmdline, len, DMA_FROM_DEVICE); memset(cmdline, 0, len); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.cmd = 33; myVspCmd.sub_data.kern.token = dma_addr; myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; myVspCmd.sub_data.kern.side = side; myVspCmd.sub_data.kern.length = len; mb(); rc = signal_vsp_instruction(&myVspCmd); if (rc == 0) { if (myVspCmd.result_code == 0) len = myVspCmd.sub_data.length_out;#if 0 else memcpy(cmdline, "Bad cmdline", 11);#endif } dma_unmap_single(iSeries_vio_dev, dma_addr, *size, DMA_FROM_DEVICE); return len;}int mf_setVmlinuxChunk(const char *buffer, int size, int offset, u64 side){ struct VspCmdData myVspCmd; int rc; dma_addr_t dma_addr = 0; char *page = dma_alloc_coherent(iSeries_vio_dev, size, &dma_addr, GFP_ATOMIC); if (page == NULL) { printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); return -ENOMEM; } copy_from_user(page, buffer, size); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.cmd = 30; myVspCmd.sub_data.kern.token = dma_addr; myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; myVspCmd.sub_data.kern.side = side; myVspCmd.sub_data.kern.offset = offset; myVspCmd.sub_data.kern.length = size; mb(); rc = signal_vsp_instruction(&myVspCmd); if (rc == 0) { if (myVspCmd.result_code == 0) rc = 0; else rc = -ENOMEM; } dma_free_coherent(iSeries_vio_dev, size, page, dma_addr); return rc;}int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side){ struct VspCmdData myVspCmd; int rc; int len = *size; dma_addr_t dma_addr; dma_addr = dma_map_single(iSeries_vio_dev, buffer, len, DMA_FROM_DEVICE); memset(buffer, 0, len); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.cmd = 32; myVspCmd.sub_data.kern.token = dma_addr; myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; myVspCmd.sub_data.kern.side = side; myVspCmd.sub_data.kern.offset = offset; myVspCmd.sub_data.kern.length = len; mb(); rc = signal_vsp_instruction(&myVspCmd); if (rc == 0) { if (myVspCmd.result_code == 0) *size = myVspCmd.sub_data.length_out; else rc = -ENOMEM; } dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE); return rc;}int mf_setRtcTime(unsigned long time){ struct rtc_time tm; to_tm(time, &tm); return mf_setRtc(&tm);}struct RtcTimeData { struct completion com; struct CeMsgData xCeMsg; int xRc;};void getRtcTimeComplete(void * token, struct CeMsgData *ceMsg){ struct RtcTimeData *rtc = (struct RtcTimeData *)token; memcpy(&(rtc->xCeMsg), ceMsg, sizeof(rtc->xCeMsg)); rtc->xRc = 0; complete(&rtc->com);}static unsigned long lastsec = 1;int mf_getRtcTime(unsigned long *time){ u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart)); u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1); int year = 1970; int year1 = (dataWord1 >> 24) & 0x000000FF; int year2 = (dataWord1 >> 16) & 0x000000FF; int sec = (dataWord1 >> 8) & 0x000000FF; int min = dataWord1 & 0x000000FF; int hour = (dataWord2 >> 24) & 0x000000FF; int day = (dataWord2 >> 8) & 0x000000FF; int mon = dataWord2 & 0x000000FF; BCD_TO_BIN(sec); BCD_TO_BIN(min); BCD_TO_BIN(hour); BCD_TO_BIN(day); BCD_TO_BIN(mon); BCD_TO_BIN(year1); BCD_TO_BIN(year2); year = year1 * 100 + year2; *time = mktime(year, mon, day, hour, min, sec); *time += (jiffies / HZ); /* * Now THIS is a nasty hack! * It ensures that the first two calls to mf_getRtcTime get different * answers. That way the loop in init_time (time.c) will not think * the clock is stuck. */ if (lastsec) { *time -= lastsec; --lastsec; } return 0;}int mf_getRtc(struct rtc_time *tm){ struct CeMsgCompleteData ceComplete; struct RtcTimeData rtcData; int rc; memset(&ceComplete, 0, sizeof(ceComplete)); memset(&rtcData, 0, sizeof(rtcData)); init_completion(&rtcData.com); ceComplete.handler = &getRtcTimeComplete; ceComplete.token = (void *)&rtcData; rc = signal_ce_msg("\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00", &ceComplete); if (rc == 0) { wait_for_completion(&rtcData.com); if (rtcData.xRc == 0) { if ((rtcData.xCeMsg.ce_msg[2] == 0xa9) || (rtcData.xCeMsg.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_setRtc(tm); } { u32 dataWord1 = *((u32 *)(rtcData.xCeMsg.ce_msg+4)); u32 dataWord2 = *((u32 *)(rtcData.xCeMsg.ce_msg+8)); u8 year = (dataWord1 >> 16) & 0x000000FF; u8 sec = (dataWord1 >> 8) & 0x000000FF; u8 min = dataWord1 & 0x000000FF; u8 hour = (dataWord2 >> 24) & 0x000000FF; u8 day = (dataWord2 >> 8) & 0x000000FF; u8 mon = dataWord2 & 0x000000FF; 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; } } else { rc = rtcData.xRc; tm->tm_sec = 0; tm->tm_min = 0; tm->tm_hour = 0; tm->tm_mday = 15; tm->tm_mon = 5; tm->tm_year = 52; } tm->tm_wday = 0; tm->tm_yday = 0; tm->tm_isdst = 0; } return rc;}int mf_setRtc(struct rtc_time * tm){ char ceTime[12] = "\x00\x00\x00\x41\x00\x00\x00\x00\x00\x00\x00\x00"; 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); ceTime[4] = y1; ceTime[5] = y2; ceTime[6] = sec; ceTime[7] = min; ceTime[8] = hour; ceTime[10] = day; ceTime[11] = mon; return signal_ce_msg(ceTime, NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -