汇编程序编写的读取spd信息的代码:
1 ;----------------------------------------------------------- 2 ;功能: 通过SMbus 读取内存的SPD 信息 3 ;时间: 2015/09 4 ;环境: DOS + MASM5 5 ;说明: 代码中涉及的smbus规范是基于Intel平台 6 ;--------------------------------------------------------- 7 ;功能: 显示ascii 表示的字符 8 echoch macro ascii 9 mov ah,2 10 mov dl,ascii 11 int 21h 12 endm 13 ;--------------------------------------------------------- 14 .386P 15 ;-------------------- data segment --------------------------------- 16 dseg segment use16 17 busnum dw 0000h ;总线号0 - 00FFh 18 devnum dw 001fh ;设备号0 - 001Fh 19 funnum dw 0007h ;功能号0 - 0007h 20 regnum dw 00ffh ;寄存器0 - 00FFh 21 ; 22 sm_base dw 0000h ;存放smbus 基地址 23 sm_devnum dw 0000h ;a0/a2/a4/a6 24 sm_regnum dw 0000h ; 25 ; 26 bufferlen = 128 27 buffer db bufferlen dup(0) ;存放spd 128-byte的信息 28 buffer1 db 'smbus base address :' 29 buffer2 db 'device index :' 30 dseg ends 31 ;-------------------- data segment end ---------------------------------- 32 ;-------------------- code segment --------------------------------- 33 cseg segment use16 34 assume cs:cseg, ds:dseg 35 start: 36 mov ax,dseg 37 mov ds,ax 38 ;----------------------扫描PCI --------------------- 39 mov busnum,0000h 40 mov devnum,0000h 41 mov funnum,0000h 42 mov regnum,0000h 43 nextreg: 44 call pci_read ;读取pci 配置空间的前4 个字节 45 cmp ax,0ffffh ;判断设备是否存在 46 jz nextfun ;不存在,跳到下一个fun 47 ; 48 add regnum,08h ;读class code 49 call pci_read 50 and eax,0ffffff00h 51 cmp eax,0c050000h ;根据class code 判断SMbus Controller( 0c0500 ) 52 jz find ;是SMbus Controller 53 nextfun: 54 mov regnum,0000h 55 inc funnum 56 cmp funnum,0007h 57 ja nextdev ;funnum 大于 7,跳到下一个dev 58 jmp nextreg 59 nextdev: 60 mov regnum,0000h 61 mov funnum,0000h 62 inc devnum 63 cmp devnum,001fh 64 ja nextbus ;devnum 大于 1fh,跳到下一个bus 65 jmp nextreg 66 nextbus: 67 mov regnum,0000h 68 mov funnum,0000h 69 mov devnum,0000h 70 inc busnum 71 cmp busnum,0005h 72 ja notfind ;busnum 大于5,没找到SMbus Controller --结束 73 jmp nextreg 74 75 ;--------------------找到SMbus Controller------------------- 76 find: 77 sub regnum,08h 78 add regnum,20h ;SMbus 的基地址在pci 配置空间中的偏移地址 79 call pci_read ;读取SMbus 的基地址 80 and ax,0fffeh ;1111_1111_1111_1110,最后一位1 :表示端口方式 81 mov sm_base,ax ;把基地址保存到sm_base 82 ; 83 ;-----------------------打印smbus 的基地址------------ 84 mov dx,offset buffer1 85 mov cx,20 86 mov ah,40h 87 int 21h 88 ; 89 mov ax,sm_base 90 shr ax,8 91 push ax 92 shr al,4 93 call toascii 94 echoch al 95 pop ax 96 call toascii 97 echoch al 98 ; 99 mov ax,sm_base 100 push ax 101 shr al,4 102 call toascii 103 echoch al 104 pop ax 105 call toascii 106 echoch al 107 echoch 0dh ;换行 108 echoch 0ah 109 ;--------------------读smbus 设备的SPD ---------------- 110 mov sm_devnum,00a0h ;设备a0 111 ; 112 nextd: 113 mov sm_regnum,0000h 114 mov dx,offset buffer2 115 mov cx,14 116 mov ah,40h 117 int 21h 118 ; 119 mov ax,sm_devnum 120 push ax 121 shr al,4 122 call toascii 123 echoch al 124 pop ax 125 call toascii 126 echoch al 127 echoch ' ' 128 ; 129 call sm_read ;读128-byte 的spd,存入buffer , 并显示buffer 130 echoch 0dh ;换行 131 echoch 0ah 132 add sm_devnum,2 ;设备号a0/a2/a4/a6 133 cmp sm_devnum,0a8h 134 jl nextd ;小于,循环 135 ;---------------------------------------- 136 ;--------------结束,返回DOS ------------- 137 notfind: 138 mov ah,4ch 139 int 21h 140 ;--------------------------------------------- 141 ;------------------子程序---------------- 142 ;---------------------------------------- 143 ;功能: 通过smbus IO registers 读取spd 信息,并存入buffer 144 ;入口: 145 ; 146 sm_read proc 147 push dx 148 push ax 149 ; 150 mov ax,dseg ;设置目的地址(buffer 的地址) 151 mov es,ax ;段地址为数据段地址 152 mov di,offset buffer ;偏移地址为缓冲区的偏移地址 153 nextch: 154 ;----------smbus 访问规范-------- 155 call iodelay 156 mov dx,sm_base ;SMbus 的基地址 157 add dx,00h ;status register 158 mov al,0feh ; 159 out dx,al 160 call iodelay ;延时 161 ; 162 mov dx,sm_base 163 add dx,04h ;slave address register 164 mov ax,sm_devnum ;从设备地址:a0/a2/a4/a6 , 165 or al,01h ;末位:1 - 表示读 166 out dx,al 167 call iodelay 168 ; 169 mov dx,sm_base 170 add dx,03h ;command register 171 mov ax,sm_regnum ;寄存器索引 172 out dx,al 173 call iodelay 174 inc sm_regnum 175 ; 176 mov dx,sm_base 177 add dx,02h ;control register 178 mov al,48h ;设置读写模式:字节(48h)、字(4ch)、块(54h) 179 out dx,al 180 call iodelay 181 call iodelay 182 ; 183 mov dx,sm_base 184 add dx,00h 185 in al,dx 186 cmp al,04h ;判断读结果 187 jz enderr ;读出错,设备不存在,返回 188 ; 189 mov dx,sm_base 190 add dx,05h ;data0 register 191 in al,dx ;回读数据 192 mov es:[di],al ;数据保存到buffer 中 193 inc di 194 cmp sm_regnum,7fh 195 ja endsm ;128-byte 读完 196 jmp nextch 197 endsm: ;读完结束,打印buffer 后,结束 198 call print_buffer 199 pop ax 200 pop dx 201 ret 202 enderr: ;读出错结束,直接退出 203 pop ax 204 pop dx 205 ret 206 sm_read endp 207 ;-------------------------------------------------- 208 ;功能:延时,等待外设把数据准备好 209 ; 210 iodelay proc 211 push cx 212 mov cx,0ffffh 213 delay: 214 loop delay 215 mov cx,0ffffh 216 delay1: 217 loop delay1 218 pop cx 219 ret 220 iodelay endp 221 ;--------------------------------------------- 222 ;功能: 根据eax中的地址读取pci的配置空间,并存入eax 223 ;入口: busnum、devnum、funnum、regnum 224 ;出口: eax 225 ; 226 pci_read proc 227 ;protect register 228 push ebx 229 push dx 230 ;clear 231 xor eax,eax 232 xor ebx,ebx 233 ;enable 234 add eax,1h 235 shl eax,31 236 ;bus number 237 mov ebx,ds:[00] 238 and ebx,0ffh 239 shl ebx,16 240 add eax,ebx 241 ;device number 242 xor ebx,ebx 243 mov ebx,ds:[02] 244 and ebx,0ffh 245 shl ebx,11 246 add eax,ebx 247 ;function number 248 xor ebx,ebx 249 mov ebx,ds:[04] 250 and ebx,0ffh 251 shl ebx,8 252 add eax,ebx 253 ;register 254 xor ebx,ebx 255 mov ebx,ds:[06] 256 and ebx,0ffh 257 add eax,ebx 258 ;read IO 259 mov dx,0cf8h 260 out dx,eax 261 mov dx,0cfch 262 in eax,dx 263 ;resume register 264 pop dx 265 pop ebx 266 ret 267 pci_read endp 268 ;---------------------------------------------- 269 ;功能:打印buffer的内容(以ascii 形式) 270 ; 271 print_buffer proc 272 push ax 273 push ds 274 push si 275 push cx 276 push bp 277 ; 278 mov ax,dseg ;设置源地址(buffer 的地址) 279 mov ds,ax 280 mov si,offset buffer 281 mov cx,bufferlen 282 cld 283 nextline3: 284 dec cx 285 echoch 0dh 286 echoch 0ah 287 mov bp,16 288 nextch3: 289 lodsb ;加载一个字节到al 290 ; 291 push ax 292 shr al,4 293 call toascii 294 echoch al 295 pop ax 296 call toascii 297 echoch al 298 echoch ' ' 299 ; 300 dec bp 301 jz nextline3 302 loop nextch3 303 ; 304 pop bp ;出栈顺序与入栈顺序相反 305 pop cx 306 pop si 307 pop ds 308 pop ax 309 ret 310 print_buffer endp 311 ;---------------------------------------- 312 ;功能:把al 的低4位转成ascii码,并存入al 313 ;入口: al 314 ;出口: al 315 toascii proc 316 and al,0fh ;高四位清零 317 add al,90h ;1001_xxxx 318 daa 319 adc al,40h 320 daa 321 ret 322 toascii endp 323 ;------------------------------------------- 324 cseg ends 325 ;------------- code segment end -------------------------- 326 end start