了解MmMapIoSpace以及MmUnmapIoSpace函数的实现原理以及实现方法
Code
1 源码路径
2 H:\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\CEDDK\DDK_MAP
3 目的,了解MmMapIoSpace以及MmUnmapIoSpace函数的实现原理以及实现方法
4 分析之前,要看看一个很关键的东西——PHYSICAL_ADDRESS,这个参数很重要,是地址的组织形式。
5 // in ceddk.h
6 typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
7 // in winnt.h
8 typedef struct _LARGE_INTEGER {
9 #else // MIDL_PASS
10 typedef union _LARGE_INTEGER {
11 struct {
12 DWORD LowPart;
13 LONG HighPart;
14 };
15 struct {
16 DWORD LowPart;
17 LONG HighPart;
18 } u;
19 #endif //MIDL_PASS
20 LONGLONG QuadPart;
21 } LARGE_INTEGER;
22 在MSDN中有这样的解释:
23 LARGE_INTEGER Union
24
25 The LARGE_INTEGER structure is used to represent a 64-bit signed integer value.
26
27 Note Your C compiler may support 64-bit integers natively. For example, Microsoft Visual C++ supports the __int64 sized integer type. For
28
29 more information, see the documentation included with your C compiler.
30
31 Members
32 LowPart
33 Low-order 32 bits.
34
35 HighPart
36 High-order 32 bits.
37
38 u
39 LowPart
40 Low-order 32 bits.
41
42 HighPart
43 High-order 32 bits.
44
45 QuadPart
46 Signed 64-bit integer.
47
48 Remarks
49 The LARGE_INTEGER structure is actually a union. If your compiler has built-in support for 64-bit integers, use the QuadPart member to store
50
51 the 64-bit integer. Otherwise, use the LowPart and HighPart members to store the 64-bit integer.
52
53
54 OK,现在就来看看MmMapIoSpace吧。
55 首先看它的一个成功使用例子:
56
57 void CDlgDemoDlg::OnButton1()
58 {
59 // TODO: Add your control notification handler code here
60 //unsigned char *gpio_base;
61 unsigned int *gpio_base;
62 OutputDebugString(L"TestDrv - LedDrive1\n");
63 //PUCHAR ioPortBase;
64 PHYSICAL_ADDRESS PortAddress = {0x56000060, 0}; // LowPart=0x56000060;HighPart=0;
65 gpio_base =(unsigned int *)MmMapIoSpace( PortAddress, 0x04,FALSE ); // 获得内存,4字节大小。
66 *gpio_base = 0x0585ff87; // 直接访问硬件
67 MmUnmapIoSpace(gpio_base,0x04);//释放内存
68 }
69 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gooogleman/archive/2009/05/16/4189536.aspx
70
71 再看MmMapIoSpace实现过程H:\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\CEDDK\DDK_MAP
72
73 /*++
74 Routine Description:
75 map the given physical address range to nonpaged system space
76
77 Arguments:
78 PhysicalAddress - starting physical address of the I/O range to be mapped
79 NumberOfBytes - number of bytes to be mapped
80 CacheEnable - TRUE if the physical address range can be mapped as cached
81 memory
82
83 Return Value:
84 base virtual address that maps the base physical address for the range, or
85 NULL if space for mapping the range is insufficient
86 --*/
87 PVOID
88 MmMapIoSpace (
89 IN PHYSICAL_ADDRESS PhysicalAddress,
90 IN ULONG NumberOfBytes,
91 IN BOOLEAN CacheEnable
92 )
93 {
94 PVOID pVirtualAddress;
95 ULONGLONG SourcePhys;
96 ULONG SourceSize;
97 BOOL bSuccess;
98
99 //
100 // Page align source and adjust size to compensate
101 //
102
103 SourcePhys = PhysicalAddress.QuadPart & ~(PAGE_SIZE - 1);// for page align
104 SourceSize = NumberOfBytes + (PhysicalAddress.LowPart & (PAGE_SIZE - 1));
105
106 if (SourceSize < NumberOfBytes) { // Prevent Integer overflow.
107 SetLastError(ERROR_INVALID_PARAMETER);
108 return NULL;
109 }
110
111
112 pVirtualAddress = VirtualAlloc(0, SourceSize, MEM_RESERVE, PAGE_NOACCESS);
113
114 if (pVirtualAddress != NULL)
115 {
116 bSuccess = VirtualCopy(
117 pVirtualAddress, (PVOID)(SourcePhys >> 8), SourceSize,
118 PAGE_PHYSICAL | PAGE_READWRITE | (CacheEnable ? 0 : PAGE_NOCACHE));
119
120 if (bSuccess)
121 {
122 (ULONG)pVirtualAddress += PhysicalAddress.LowPart & (PAGE_SIZE - 1);//保证虚拟地址是页对齐
123 }
124 else
125 {
126 VirtualFree(pVirtualAddress, 0, MEM_RELEASE);//释放内存。
127 pVirtualAddress = NULL;
128 }
129 }
130
131 return pVirtualAddress;//返回虚拟内存地址。
132 }
133
134 =================================================================================
135 从这个看来MmMapIoSpace也是使用了驱动中常用的VirtualAlloc、VirtualCopy、VirtualFree来实现的,只不过是加入了页对齐,使用起来较安全。
136 再看看MmUnmapIoSpace
137
138 /*++
139 Routine Description:
140 unmap a specified range of physical addresses previously mapped by
141 MmMapIoSpace
142
143 Arguments:
144 BaseAddress - pointer to the base virtual address to which the physical
145 pages were mapped
146 NumberOfBytes - number of bytes that were mapped
147
148 Return Value:
149 None
150 --*/
151 VOID
152 MmUnmapIoSpace (
153 IN PVOID BaseAddress,
154 IN ULONG NumberOfBytes
155 )
156 {
157 VirtualFree((PVOID)((ULONG)BaseAddress & ~(ULONG)(PAGE_SIZE - 1)), 0, MEM_RELEASE);
158 }
159 //嘿嘿,还是使用驱动的常用方法VirtualFree来释放虚拟内存,只是安全系数高一些。
160 类似参考文章:http://hi.chinaunix.net/?uid-21747227-action-viewspace-itemid-39331
161
1 源码路径
2 H:\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\CEDDK\DDK_MAP
3 目的,了解MmMapIoSpace以及MmUnmapIoSpace函数的实现原理以及实现方法
4 分析之前,要看看一个很关键的东西——PHYSICAL_ADDRESS,这个参数很重要,是地址的组织形式。
5 // in ceddk.h
6 typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
7 // in winnt.h
8 typedef struct _LARGE_INTEGER {
9 #else // MIDL_PASS
10 typedef union _LARGE_INTEGER {
11 struct {
12 DWORD LowPart;
13 LONG HighPart;
14 };
15 struct {
16 DWORD LowPart;
17 LONG HighPart;
18 } u;
19 #endif //MIDL_PASS
20 LONGLONG QuadPart;
21 } LARGE_INTEGER;
22 在MSDN中有这样的解释:
23 LARGE_INTEGER Union
24
25 The LARGE_INTEGER structure is used to represent a 64-bit signed integer value.
26
27 Note Your C compiler may support 64-bit integers natively. For example, Microsoft Visual C++ supports the __int64 sized integer type. For
28
29 more information, see the documentation included with your C compiler.
30
31 Members
32 LowPart
33 Low-order 32 bits.
34
35 HighPart
36 High-order 32 bits.
37
38 u
39 LowPart
40 Low-order 32 bits.
41
42 HighPart
43 High-order 32 bits.
44
45 QuadPart
46 Signed 64-bit integer.
47
48 Remarks
49 The LARGE_INTEGER structure is actually a union. If your compiler has built-in support for 64-bit integers, use the QuadPart member to store
50
51 the 64-bit integer. Otherwise, use the LowPart and HighPart members to store the 64-bit integer.
52
53
54 OK,现在就来看看MmMapIoSpace吧。
55 首先看它的一个成功使用例子:
56
57 void CDlgDemoDlg::OnButton1()
58 {
59 // TODO: Add your control notification handler code here
60 //unsigned char *gpio_base;
61 unsigned int *gpio_base;
62 OutputDebugString(L"TestDrv - LedDrive1\n");
63 //PUCHAR ioPortBase;
64 PHYSICAL_ADDRESS PortAddress = {0x56000060, 0}; // LowPart=0x56000060;HighPart=0;
65 gpio_base =(unsigned int *)MmMapIoSpace( PortAddress, 0x04,FALSE ); // 获得内存,4字节大小。
66 *gpio_base = 0x0585ff87; // 直接访问硬件
67 MmUnmapIoSpace(gpio_base,0x04);//释放内存
68 }
69 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gooogleman/archive/2009/05/16/4189536.aspx
70
71 再看MmMapIoSpace实现过程H:\WINCE600\PUBLIC\COMMON\OAK\DRIVERS\CEDDK\DDK_MAP
72
73 /*++
74 Routine Description:
75 map the given physical address range to nonpaged system space
76
77 Arguments:
78 PhysicalAddress - starting physical address of the I/O range to be mapped
79 NumberOfBytes - number of bytes to be mapped
80 CacheEnable - TRUE if the physical address range can be mapped as cached
81 memory
82
83 Return Value:
84 base virtual address that maps the base physical address for the range, or
85 NULL if space for mapping the range is insufficient
86 --*/
87 PVOID
88 MmMapIoSpace (
89 IN PHYSICAL_ADDRESS PhysicalAddress,
90 IN ULONG NumberOfBytes,
91 IN BOOLEAN CacheEnable
92 )
93 {
94 PVOID pVirtualAddress;
95 ULONGLONG SourcePhys;
96 ULONG SourceSize;
97 BOOL bSuccess;
98
99 //
100 // Page align source and adjust size to compensate
101 //
102
103 SourcePhys = PhysicalAddress.QuadPart & ~(PAGE_SIZE - 1);// for page align
104 SourceSize = NumberOfBytes + (PhysicalAddress.LowPart & (PAGE_SIZE - 1));
105
106 if (SourceSize < NumberOfBytes) { // Prevent Integer overflow.
107 SetLastError(ERROR_INVALID_PARAMETER);
108 return NULL;
109 }
110
111
112 pVirtualAddress = VirtualAlloc(0, SourceSize, MEM_RESERVE, PAGE_NOACCESS);
113
114 if (pVirtualAddress != NULL)
115 {
116 bSuccess = VirtualCopy(
117 pVirtualAddress, (PVOID)(SourcePhys >> 8), SourceSize,
118 PAGE_PHYSICAL | PAGE_READWRITE | (CacheEnable ? 0 : PAGE_NOCACHE));
119
120 if (bSuccess)
121 {
122 (ULONG)pVirtualAddress += PhysicalAddress.LowPart & (PAGE_SIZE - 1);//保证虚拟地址是页对齐
123 }
124 else
125 {
126 VirtualFree(pVirtualAddress, 0, MEM_RELEASE);//释放内存。
127 pVirtualAddress = NULL;
128 }
129 }
130
131 return pVirtualAddress;//返回虚拟内存地址。
132 }
133
134 =================================================================================
135 从这个看来MmMapIoSpace也是使用了驱动中常用的VirtualAlloc、VirtualCopy、VirtualFree来实现的,只不过是加入了页对齐,使用起来较安全。
136 再看看MmUnmapIoSpace
137
138 /*++
139 Routine Description:
140 unmap a specified range of physical addresses previously mapped by
141 MmMapIoSpace
142
143 Arguments:
144 BaseAddress - pointer to the base virtual address to which the physical
145 pages were mapped
146 NumberOfBytes - number of bytes that were mapped
147
148 Return Value:
149 None
150 --*/
151 VOID
152 MmUnmapIoSpace (
153 IN PVOID BaseAddress,
154 IN ULONG NumberOfBytes
155 )
156 {
157 VirtualFree((PVOID)((ULONG)BaseAddress & ~(ULONG)(PAGE_SIZE - 1)), 0, MEM_RELEASE);
158 }
159 //嘿嘿,还是使用驱动的常用方法VirtualFree来释放虚拟内存,只是安全系数高一些。
160 类似参考文章:http://hi.chinaunix.net/?uid-21747227-action-viewspace-itemid-39331
161
注意事项:
一、如果文章标题标有【原创】字眼的,gooogleman有原创著作权,请转载的时候不要删除文章的任何部分,并且商业网站转载必须经过gooogleman同意。
二、文章标题标有【转载】也请转载的时候标明原创作者的名字和原文地址,尊重原创作者。
三、本博客为gooogleman的官方博客,并且会和gooogleman官方网站http://www.gooogleman.com/以及gooogleman CSDN 博客同步更新。
四、本博客原创文章所有权属于gooogleman嵌入式开发板联盟。
五、gooogleman嵌入式开发板联盟盟主旗舰店为http://gooogleman.taobao.com/ 旺旺ID 为:gooogleman2009 目前发现网上有类似的ID,请各位网友不要认错, gooogleman和gooogleman2009 是唯一的!