📄 ixlinuxinit.c
字号:
/* * @par * IXP400 SW Release version 2.1 * * -- Copyright Notice -- * * @par * Copyright (c) 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * @par * -- End of Copyright Notice --*//* Non-Linux related headers */#include <IxFeatureCtrl.h>#include <IxNpeMh.h>/* Linux initialization */#ifdef __linux#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <asm/uaccess.h>/****************************************************** * Include File Operations functions and declarations * * if Microcode is to be read in from a file * ******************************************************/#ifdef IX_NPEDL_READ_MICROCODE_FROM_FILE/* #defines, variables and forward declarations for file operations */#define DEV_IXNPE_MAJOR_NUMBER 241typedef struct { UINT32* data; UINT32 size; struct IxNpeMicrocodeSegment* next;} IxNpeMicrocodeSegment;UINT32* ixNpeMicrocode_binaryArray;PRIVATE IxNpeMicrocodeSegment* ixNpeDlSegmentedListHead = NULL;PRIVATE IxNpeMicrocodeSegment* ixNpeDlSegmentedListTail = NULL;PRIVATE UINT32 ixNpeDlMicrocodePageOrder, ixNpeDlTotalBytesReadIn = 0;int ixNpe_dev_open (struct inode *inode, struct file *file);int ixNpe_dev_release (struct inode *inode, struct file *file);ssize_t ixNpe_dev_write (struct file *file, const char *buf, size_t byteCount, loff_t *offset);struct file_operations ixNpe_dev_fops = { owner: THIS_MODULE, open: ixNpe_dev_open, release: ixNpe_dev_release, write: ixNpe_dev_write};#endif /* IX_NPEDL_READ_MICROCODE_FROM_FILE *//* Module parameters */static int livelock_dispatcher = 0;/* default: don't use livelock dispatcher*/MODULE_PARM(livelock_dispatcher, "i");MODULE_PARM_DESC(livelock_dispatcher, "If non-zero, use the livelock prevention qmgr dispatcher");/* Init and cleanup functions for module */static int __init ixp400_sw_init_module(void){ /* Add initialization code here */#ifdef DEBUG printk("\n\n"__FUNCTION__": addr=%p\n\n", ixp400_sw_init_module);#endif /* * If livelock prevention dispatcher is requested - enable in FeatureCtrl */ if (livelock_dispatcher != 0) { ixFeatureCtrlSwConfigurationWrite (IX_FEATURECTRL_ORIGB0_DISPATCHER, IX_FEATURE_CTRL_SWCONFIG_DISABLED); }#ifdef IX_NPEDL_READ_MICROCODE_FROM_FILE /* Register driver for /dev/ixNpe */ if (register_chrdev(DEV_IXNPE_MAJOR_NUMBER, "ixNpe", &ixNpe_dev_fops)) printk (KERN_ERR "Failed to register driver for /dev/ixNpe\n");#endif /* IX_NPEDL_READ_MICROCODE_FROM_FILE */ printk(KERN_DEBUG "ixp400: Module init.\n"); return 0;}static void __exit ixp400_sw_cleanup_module(void){ /* Add cleanup code here */ ixNpeMhUnload();#ifdef IX_NPEDL_READ_MICROCODE_FROM_FILE /* Free memory Microcode images are in and unregister driver for ixNpe */ free_pages((UINT32)ixNpeMicrocode_binaryArray, ixNpeDlMicrocodePageOrder); if (unregister_chrdev(DEV_IXNPE_MAJOR_NUMBER, "ixNpe")) { printk (KERN_ERR "Failed to unregister driver for /dev/ixNpe\n"); }#endif /* IX_NPEDL_READ_MICROCODE_FROM_FILE */ printk(KERN_DEBUG "ixp400: Module uninit.\n");}module_init(ixp400_sw_init_module);module_exit(ixp400_sw_cleanup_module);/****************************************** * Include File Operations functions if * * Microcode is to be read in from a file * ******************************************/#ifdef IX_NPEDL_READ_MICROCODE_FROM_FILE/* File Operations support for /dev/ixNpe */int ixNpe_dev_open (struct inode *inode, struct file *file){ /* Test to see if we've read in Microcode already */ if (ixNpeMicrocode_binaryArray != NULL) { printk (KERN_ERR "ixp400.o: Microcode is already in memory.\n"); return -EEXIST; } MOD_INC_USE_COUNT; /* Increment use count to prevent premature rmmod-ing */ ixNpeDlSegmentedListHead = NULL; /* Reset linked list which keeps track of Microcode fragments */ ixNpeDlSegmentedListTail = NULL; ixNpeDlTotalBytesReadIn = 0; return 0;}int ixNpe_dev_release (struct inode *inode, struct file *file){ IxNpeMicrocodeSegment* temp = NULL; UINT32* currentPosition = NULL; UINT32 pagesNeeded, x; /* If we got data, allocate pages and copy piecemeal * * data into permanent memory as single block */ if (ixNpeDlTotalBytesReadIn > 0) { /* Calculate how many pages needed */ pagesNeeded = ixNpeDlTotalBytesReadIn/PAGE_SIZE; if (ixNpeDlTotalBytesReadIn%PAGE_SIZE) { pagesNeeded++; /* Allow for lack of floating point division */ } /* Shift right to find what order is needed for __get_free_pages */ for (x = pagesNeeded; x > 0; x >>= 1) { ixNpeDlMicrocodePageOrder++; } /* __get_free_pages returns a pointer cast as an unsigned long */ ixNpeMicrocode_binaryArray = (UINT32 *)(__get_free_pages(GFP_KERNEL, ixNpeDlMicrocodePageOrder)); if (ixNpeMicrocode_binaryArray == NULL) { printk (KERN_ERR "ixp400.o: Error, couldn't get enough memory to store Microcode in (need %d pages).\n", pagesNeeded); } else { /* Copy each segment of data into a single image */ temp = ixNpeDlSegmentedListHead; currentPosition = ixNpeMicrocode_binaryArray; while (temp != NULL) { memcpy(currentPosition, temp->data, temp->size); /* increment pointers */ currentPosition = (UINT32 *)((UINT32)currentPosition + temp->size); temp = (IxNpeMicrocodeSegment *) temp->next; /* cast is for fussy compiler */ } } } /* Free the temporary list memory and decrement use count */ while (ixNpeDlSegmentedListHead->next != NULL) { /* Move the head pointer down the list and free old element */ temp = ixNpeDlSegmentedListHead; ixNpeDlSegmentedListHead = (IxNpeMicrocodeSegment *) ixNpeDlSegmentedListHead->next; kfree (temp->data); kfree (temp); } MOD_DEC_USE_COUNT; return 0;}ssize_t ixNpe_dev_write (struct file *file, const char *buf, size_t byteCount, loff_t *offset){ /* Malloc memory to hold this segment of the Microcode */ UINT32* currentData = kmalloc (byteCount, GFP_KERNEL); IxNpeMicrocodeSegment* currentSegment = kmalloc (sizeof(IxNpeMicrocodeSegment), GFP_KERNEL); /* Copy data from user space */ if (copy_from_user(currentData, buf, byteCount)) { /* Copy Failed: Free memory just kmalloced */ kfree (currentData); kfree (currentSegment); /* Reset total byte count to prevent page allocation in ixNpe_dev_release() */ ixNpeDlTotalBytesReadIn = 0; return -EFAULT; } /* Copy was successful so update struct */ currentSegment->data = currentData; currentSegment->size = byteCount; currentSegment->next = NULL; ixNpeDlTotalBytesReadIn += byteCount; /* Add to linked list of microcode segments */ if (ixNpeDlSegmentedListHead == NULL) { ixNpeDlSegmentedListHead = currentSegment; ixNpeDlSegmentedListTail = currentSegment; } else { ixNpeDlSegmentedListTail->next = (struct IxNpeMicrocodeSegment *)currentSegment; /* cast is for fussy compiler */ ixNpeDlSegmentedListTail = currentSegment; } /* Return the number of bytes we wrote */ return byteCount;}#endif /* IX_NPEDL_READ_MICROCODE_FROM_FILE */#else#error Non-Linux compilation#endif /* #ifdef __linux */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -