📄 mf.c
字号:
unsigned size, unsigned count, MFCompleteHandler hdlr, void * userToken ){ struct StackElement * newElement = newStackElement(); int rc = 0; if ( newElement == NULL ) rc = -ENOMEM; else { union SafeCast mine; mine.ptr = userToken; newElement->event.xHvLpEvent.xSubtype = 4; newElement->event.xHvLpEvent.xCorrelationToken = mine.ptrAsU64; newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('M'<<8)+('A'<<0); newElement->event.xUnion.xAllocData.xTargetLp = targetLp; newElement->event.xUnion.xAllocData.xType = type; newElement->event.xUnion.xAllocData.xSize = size; newElement->event.xUnion.xAllocData.xCount = count; newElement->hdlr = hdlr; rc = signalEvent(newElement); } if ( (rc != 0) && (hdlr != NULL) ) (*hdlr)( userToken, rc );}/* * 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 StackElement * newElement = newStackElement(); int rc = 0; if ( newElement == NULL ) rc = -ENOMEM; else { union SafeCast mine; mine.ptr = userToken; newElement->event.xHvLpEvent.xSubtype = 5; newElement->event.xHvLpEvent.xCorrelationToken = mine.ptrAsU64; newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('M'<<8)+('D'<<0); newElement->event.xUnion.xAllocData.xTargetLp = targetLp; newElement->event.xUnion.xAllocData.xType = type; newElement->event.xUnion.xAllocData.xCount = count; newElement->hdlr = hdlr; rc = signalEvent(newElement); } if ( (rc != 0) && (hdlr != NULL) ) (*hdlr)( userToken, rc );}/* * 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" ); signalCEMsg( "\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" ); signalCEMsg( "\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; signalCEMsg( 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\x00" "PROGxxxx" " ", 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]; dmaAndSignalCEMsg( 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 ){ signalCEMsg( "\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( &spinlock ); for ( i = 0; i < sizeof(prealloc)/sizeof(*prealloc); ++i ) free( &prealloc[i] ); HvLpEvent_registerHandler( HvLpEvent_Type_MachineFac, &hvHandler ); /* virtual continue ack */ signalCEMsg( "\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" ); iSeries_proc_callback(&mf_proc_init);}void mf_setSide(char side){ int rc = 0; u64 newSide = 0; struct VspCmdData myVspCmd; memset(&myVspCmd, 0, sizeof(myVspCmd)); if (side == 'A') newSide = 0; else if (side == 'B') newSide = 1; else if (side == 'C') newSide = 2; else newSide = 3; myVspCmd.xSubData.xFunction02SelectIplTypeIn.xIplType = newSide; myVspCmd.xCmd = 10; rc = signalVspInstruction(&myVspCmd);}char mf_getSide(void){ char returnValue = ' '; int rc = 0; struct VspCmdData myVspCmd; memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.xCmd = 2; myVspCmd.xSubData.xFunction02SelectIplTypeIn.xIplType = 0; mb(); rc = signalVspInstruction(&myVspCmd); if (rc != 0) { return returnValue; } else { if (myVspCmd.xRc == 0) { if (myVspCmd.xSubData.xGetIplTypeOut.xIplType == 0) returnValue = 'A'; else if (myVspCmd.xSubData.xGetIplTypeOut.xIplType == 1) returnValue = 'B'; else if (myVspCmd.xSubData.xGetIplTypeOut.xIplType == 2) returnValue = 'C'; else returnValue = 'D'; } } return returnValue;}void mf_getSrcHistory(char *buffer, int size){ /* struct IplTypeReturnStuff returnStuff; struct StackElement * newElement = newStackElement(); 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 (( newElement == NULL ) || (pages[0] == NULL) || (pages[1] == NULL) || (pages[2] == NULL) || (pages[3] == NULL)) rc = -ENOMEM; else { returnStuff.xType = 0; returnStuff.xRc = 0; returnStuff.xDone = 0; newElement->event.xHvLpEvent.xSubtype = 6; newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('V'<<8)+('I'<<0); newElement->event.xUnion.xVspCmd.xEvent = &returnStuff; newElement->event.xUnion.xVspCmd.xCmd = 4; newElement->event.xUnion.xVspCmd.xLpIndex = HvLpConfig_getLpIndex(); newElement->event.xUnion.xVspCmd.xRc = 0xFF; newElement->event.xUnion.xVspCmd.xReserved1 = 0; newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[0] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[0])); newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[1] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[1])); newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[2] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[2])); newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[3] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[3])); mb(); rc = signalEvent(newElement); } if (rc != 0) { return; } else { 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]);*/}void mf_setCmdLine(const char *cmdline, int size, u64 side){ struct VspCmdData myVspCmd; int rc = 0; dma_addr_t dma_addr = 0; char *page = pci_alloc_consistent(iSeries_vio_dev, size, &dma_addr); 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.xCmd = 31; myVspCmd.xSubData.xSetKernelCmdLineIn.xToken = dma_addr; myVspCmd.xSubData.xSetKernelCmdLineIn.xAddressType = HvLpDma_AddressType_TceIndex; myVspCmd.xSubData.xSetKernelCmdLineIn.xSide = side; myVspCmd.xSubData.xSetKernelCmdLineIn.xTransferLength = size; mb(); rc = signalVspInstruction(&myVspCmd); pci_free_consistent(iSeries_vio_dev, size, page, dma_addr);}int mf_getCmdLine(char *cmdline, int *size, u64 side){ struct VspCmdData myVspCmd; int rc = 0; int len = *size; dma_addr_t dma_addr = pci_map_single(iSeries_vio_dev, cmdline, *size, PCI_DMA_FROMDEVICE); memset(cmdline, 0, *size); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.xCmd = 33; myVspCmd.xSubData.xGetKernelCmdLineIn.xToken = dma_addr; myVspCmd.xSubData.xGetKernelCmdLineIn.xAddressType = HvLpDma_AddressType_TceIndex; myVspCmd.xSubData.xGetKernelCmdLineIn.xSide = side; myVspCmd.xSubData.xGetKernelCmdLineIn.xTransferLength = *size; mb(); rc = signalVspInstruction(&myVspCmd); if ( ! rc ) { if (myVspCmd.xRc == 0) { len = myVspCmd.xSubData.xGetKernelCmdLineOut.xTransferLength; } /* else { memcpy(cmdline, "Bad cmdline", 11); } */ } pci_unmap_single(iSeries_vio_dev, dma_addr, *size, PCI_DMA_FROMDEVICE); return len;}int mf_setVmlinuxChunk(const char *buffer, int size, int offset, u64 side){ struct VspCmdData myVspCmd; int rc = 0; dma_addr_t dma_addr = 0; char *page = pci_alloc_consistent(iSeries_vio_dev, size, &dma_addr); 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.xCmd = 30; myVspCmd.xSubData.xGetKernelImageIn.xToken = dma_addr; myVspCmd.xSubData.xGetKernelImageIn.xAddressType = HvLpDma_AddressType_TceIndex; myVspCmd.xSubData.xGetKernelImageIn.xSide = side; myVspCmd.xSubData.xGetKernelImageIn.xOffset = offset; myVspCmd.xSubData.xGetKernelImageIn.xTransferLength = size; mb(); rc = signalVspInstruction(&myVspCmd); if (rc == 0) { if (myVspCmd.xRc == 0) { rc = 0; } else { rc = -ENOMEM; } } pci_free_consistent(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 = 0; int len = *size; dma_addr_t dma_addr = pci_map_single(iSeries_vio_dev, buffer, *size, PCI_DMA_FROMDEVICE); memset(buffer, 0, len); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.xCmd = 32; myVspCmd.xSubData.xGetKernelImageIn.xToken = dma_addr; myVspCmd.xSubData.xGetKernelImageIn.xAddressType = HvLpDma_AddressType_TceIndex; myVspCmd.xSubData.xGetKernelImageIn.xSide = side; myVspCmd.xSubData.xGetKernelImageIn.xOffset = offset; myVspCmd.xSubData.xGetKernelImageIn.xTransferLength = len; mb(); rc = signalVspInstruction(&myVspCmd); if (rc == 0) { if (myVspCmd.xRc == 0) { *size = myVspCmd.xSubData.xGetKernelImageOut.xTransferLength; } else { rc = -ENOMEM; } } pci_unmap_single(iSeries_vio_dev, dma_addr, len, PCI_DMA_FROMDEVICE); return rc;}int mf_setRtcTime(unsigned long time){ struct rtc_time tm; to_tm(time, &tm); return mf_setRtc( &tm );}struct RtcTimeData{ struct semaphore *xSemaphore; 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; up(rtc->xSemaphore);}static unsigned long lastsec = 1;int mf_getRtcTime(unsigned long *time){/* unsigned long usec, tsec; */ 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 = 0; DECLARE_MUTEX_LOCKED(Semaphore); memset(&ceComplete, 0, sizeof(ceComplete)); memset(&rtcData, 0, sizeof(rtcData)); rtcData.xSemaphore = &Semaphore; ceComplete.xHdlr = &getRtcTimeComplete; ceComplete.xToken = (void *)&rtcData; rc = signalCEMsg( "\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00", &ceComplete ); if ( rc == 0 ) { down(&Semaphore); if ( rtcData.xRc == 0) { if ( ( rtcData.xCeMsg.xCEMsg[2] == 0xa9 ) || ( rtcData.xCeMsg.xCEMsg[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.xCEMsg+4)); u32 dataWord2 = *((u32 *)(rtcData.xCeMsg.xCEMsg+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"; int rc = 0; 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; rc = signalCEMsg( ceTime, NULL ); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -