1/* 2 * Copyright (c) 2006 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 * 22 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23 * contributors may be used to endorse or promote products derived from this 24 * software without specific prior written permission. 25 */ 26 27/* 28 * Cimarron hardware access macros. 29 */ 30 31#ifndef _cim_defs_h 32#define _cim_defs_h 33 34/*-----------------------------------------*/ 35/* MEMORY ACCESS MACROS */ 36/*-----------------------------------------*/ 37 38#ifndef CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS 39 40#define READ_GP32(offset) \ 41 (*(volatile unsigned long *)(cim_gp_ptr + (offset))) 42 43#define READ_REG32(offset) \ 44 (*(volatile unsigned long *)(cim_vg_ptr + (offset))) 45 46#define READ_FB32(offset) \ 47 (*(volatile unsigned long *)(cim_fb_ptr + (offset))) 48 49#define WRITE_GP32(offset, value) \ 50 (*(volatile unsigned long *)(cim_gp_ptr + (offset))) = (value) 51 52#define WRITE_REG32(offset, value) \ 53 (*(volatile unsigned long *)(cim_vg_ptr + (offset))) = (value) 54 55#define WRITE_COMMAND32(offset, value) \ 56 (*(unsigned long *)(cim_cmd_ptr + (offset))) = (value) 57 58#define WRITE_COMMAND8(offset, value) \ 59 (*(unsigned char *)(cim_cmd_ptr + (offset))) = (value) 60 61#define WRITE_FB32(offset, value) \ 62 (*(unsigned long *)(cim_fb_ptr + (offset))) = (value) 63 64#define READ_VID32(offset) \ 65 (*(volatile unsigned long *)(cim_vid_ptr + (offset))) 66 67#define WRITE_VID32(offset, value) \ 68 (*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value) 69 70#define READ_VIP32(offset) \ 71 (*(volatile unsigned long *)(cim_vip_ptr + (offset))) 72 73#define WRITE_VIP32(offset, value) \ 74 (*(volatile unsigned long *)(cim_vip_ptr + (offset))) = (value) 75 76#define READ_VOP32(offset) \ 77 (*(volatile unsigned long *)(cim_vid_ptr + (offset))) 78 79#define WRITE_VOP32(offset, value) \ 80 (*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value) 81 82#endif 83 84/*-----------------------------------------*/ 85/* GP POLLING MACROS */ 86/*-----------------------------------------*/ 87 88#define GP3_WAIT_WRAP(variable) \ 89 while(((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) || \ 90 (variable <= (gp3_cmd_top + GP3_BLT_COMMAND_SIZE + GP3_BLT_COMMAND_SIZE + 96))) 91 92#define GP3_WAIT_PRIMITIVE(variable) \ 93 while (((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) && \ 94 (variable <= (gp3_cmd_next + 96))) 95 96#define GP3_WAIT_BUSY \ 97 while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_BUSY) 98 99#define GP3_WAIT_PENDING \ 100 while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_PENDING) 101 102/*-----------------------------------------------------------------*/ 103/* MSR MACROS */ 104/* These macros facilitate interaction with the model specific */ 105/* registers in GeodeLX. There are two included methods, direct */ 106/* access using the rdmsr and wrmsr opcodes and an indirect method */ 107/* using VSAII. */ 108/*-----------------------------------------------------------------*/ 109 110#ifdef CIMARRON_INCLUDE_MSR_MACROS 111 112#if CIMARRON_MSR_DIRECT_ASM 113 114/*----------------------------------------------------------------- 115 * MSR_READ 116 * Read the contents of a 64 bit MSR into a data structure 117 *-----------------------------------------------------------------*/ 118 119#define MSR_READ(msr_reg, device_add, data64_ptr) \ 120{ \ 121 unsigned long msr_add = (unsigned long)(msr_reg) | \ 122 (unsigned long)(device_add); \ 123 unsigned long data_high, data_low; \ 124 _asm { mov ecx, msr_add } \ 125 _asm { rdmsr } \ 126 _asm { mov data_high, edx } \ 127 _asm { mov data_low, eax } \ 128 \ 129 ((Q_WORD *)(data64_ptr))->high = data_high; \ 130 ((Q_WORD *)(data64_ptr))->low = data_low; \ 131} 132 133/*----------------------------------------------------------------- 134 * MSR_WRITE 135 * Write the contents of a 64 bit data structure to a MSR. 136 *-----------------------------------------------------------------*/ 137 138#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ 139{ \ 140 unsigned long msr_add = (unsigned long)(msr_reg) | \ 141 (unsigned long)(device_add); \ 142 unsigned long data_high, data_low; \ 143 \ 144 data_high = ((Q_WORD *)(data64_ptr))->high; \ 145 data_low = ((Q_WORD *)(data64_ptr))->low; \ 146 \ 147 _asm { mov ecx, msr_add } \ 148 _asm { mov edx, data_high } \ 149 _asm { mov eax, data_low } \ 150 _asm { wrmsr } \ 151} 152 153#elif CIMARRON_MSR_VSA_IO 154 155/*----------------------------------------------------------------- 156 * MSR_READ 157 * Read the contents of a 64 bit MSR into a data structure 158 *-----------------------------------------------------------------*/ 159 160#define MSR_READ(msr_reg, device_add, data64_ptr) \ 161{ \ 162 unsigned long msr_add = (unsigned long)(msr_reg) | \ 163 (unsigned long)(device_add); \ 164 unsigned long data_high, data_low; \ 165 \ 166 _asm { mov dx, 0x0AC1C } \ 167 _asm { mov eax, 0x0FC530007 } \ 168 _asm { out dx, eax } \ 169 \ 170 _asm { add dl, 2 } \ 171 _asm { mov ecx, msr_add } \ 172 _asm { in ax, dx } \ 173 _asm { mov data_high, edx } \ 174 _asm { mov data_low, eax } \ 175 \ 176 ((Q_WORD *)(data64_ptr))->high = data_high; \ 177 ((Q_WORD *)(data64_ptr))->low = data_low; \ 178} 179 180/*----------------------------------------------------------------- 181 * MSR_WRITE 182 * Write the contents of a 64 bit data structure to a MSR. 183 *-----------------------------------------------------------------*/ 184 185#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ 186{ \ 187 unsigned long msr_add = (unsigned long)(msr_reg) | \ 188 (unsigned long)(device_add); \ 189 unsigned long data_high, data_low; \ 190 \ 191 data_high = ((Q_WORD *)(data64_ptr))->high; \ 192 data_low = ((Q_WORD *)(data64_ptr))->low; \ 193 \ 194 _asm { mov dx, 0x0AC1C } \ 195 _asm { mov eax, 0x0FC530007 } \ 196 _asm { out dx, eax } \ 197 \ 198 _asm { add dl, 2 } \ 199 _asm { mov ecx, msr_add } \ 200 _asm { mov ebx, data_high } \ 201 _asm { mov eax, data_low } \ 202 \ 203 _asm { mov esi, 0 } \ 204 _asm { mov edi, 0 } \ 205 _asm { out dx, ax } \ 206} 207 208#elif CIMARRON_MSR_ABSTRACTED_ASM 209 210/*----------------------------------------------------------------- 211 * MSR_READ 212 * Read the contents of a 64 bit MSR into a data structure 213 *-----------------------------------------------------------------*/ 214 215#define MSR_READ(msr,adr,val) \ 216 __asm__ __volatile__( \ 217 " mov $0x0AC1C, %%edx\n" \ 218 " mov $0xFC530007, %%eax\n" \ 219 " out %%eax,%%dx\n" \ 220 " add $2,%%dl\n" \ 221 " in %%dx, %%ax" \ 222 : "=a" ((val)->low), "=d" ((val)->high) \ 223 : "c" (msr | adr)) 224 225/*----------------------------------------------------------------- 226 * MSR_WRITE 227 * Write the contents of a 64 bit data structure to a MSR. 228 *-----------------------------------------------------------------*/ 229 230#define MSR_WRITE(msr,adr,val) \ 231 { int d0, d1, d2, d3; \ 232 __asm__ __volatile__( \ 233 " push %%ebx\n" \ 234 " mov $0x0AC1C, %%edx\n" \ 235 " mov $0xFC530007, %%eax\n" \ 236 " out %%eax,%%dx\n" \ 237 " add $2,%%dl\n" \ 238 " mov %4, %3\n" \ 239 " mov 0(%5), %%ebx\n" \ 240 " mov 4(%5), %0\n" \ 241 " xor %2, %2\n" \ 242 " xor %1, %1\n" \ 243 " out %%ax, %%dx\n" \ 244 " pop %%ebx\n" \ 245 : "=a" (d0), "=&D" (d1), "=&S" (d2), "=c" (d3) \ 246 : "1" (msr | adr), "2" (val)); \ 247 } 248 249#elif CIMARRON_MSR_KERNEL_ROUTINE 250 251#include "asm/msr.h" 252 253/*----------------------------------------------------------------- 254 * MSR_READ 255 * Read the contents of a 64 bit MSR into a data structure 256 *-----------------------------------------------------------------*/ 257 258#define MSR_READ(msr_reg, device_add, data64_ptr) \ 259{ \ 260 unsigned long addr, val1, val2; \ 261 \ 262 addr = device_add | msr_reg; \ 263 rdmsr (addr, val1, val2); \ 264 \ 265 ((Q_WORD *)(data64_ptr))->high = val2; \ 266 ((Q_WORD *)(data64_ptr))->low = val1; \ 267} 268 269/*----------------------------------------------------------------- 270 * MSR_WRITE 271 * Read the contents of a 64 bit data structure to a MSR. 272 *-----------------------------------------------------------------*/ 273 274#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ 275{ \ 276 unsigned long addr, val1, val2; \ 277 \ 278 val2 = ((Q_WORD *)(data64_ptr))->high; \ 279 val1 = ((Q_WORD *)(data64_ptr))->low; \ 280 \ 281 addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg; \ 282 wrmsr(addr, val1, val2); \ 283} 284 285#elif CIMARRON_MSR_HOOKS 286 287#define MSR_READ(msr_reg, device_add, data64_ptr) \ 288{ \ 289 unsigned long addr, val1, val2; \ 290 \ 291 addr = device_add | msr_reg; \ 292 if (cim_rdmsr) { \ 293 cim_rdmsr (addr, &val1, &val2); \ 294 \ 295 ((Q_WORD *)(data64_ptr))->high = val2; \ 296 ((Q_WORD *)(data64_ptr))->low = val1; \ 297 } \ 298} 299 300#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ 301{ \ 302 unsigned long addr, val1, val2; \ 303 \ 304 val2 = ((Q_WORD *)(data64_ptr))->high; \ 305 val1 = ((Q_WORD *)(data64_ptr))->low; \ 306 \ 307 addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg; \ 308 if (cim_wrmsr) \ 309 cim_wrmsr(addr, val1, val2); \ 310} 311#endif 312 313#endif /* #ifdef CIMARRON_INCLUDE_MSR_MACROS */ 314 315/*-----------------------------------------------------------------*/ 316/* STRING MACROS */ 317/* These macros are included to facilitate the optimization of */ 318/* routines that write or copy large amounts of data. Two versions */ 319/* of these macros are included. One is intended for operating */ 320/* systems that allow the use of inline assembly, while the other */ 321/* is a pure C implementation for stricter operating systems. */ 322/*-----------------------------------------------------------------*/ 323 324#ifdef CIMARRON_INCLUDE_STRING_MACROS 325 326#if CIMARRON_OPTIMIZE_ASSEMBLY 327 328/*----------------------------------------------------------------- 329 * WRITE_COMMAND_STRING32 330 * Write a series of DWORDs to the current command buffer offset 331 *-----------------------------------------------------------------*/ 332 333#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ 334{ \ 335 _asm { cld } \ 336 _asm { mov edi, cim_cmd_ptr } \ 337 _asm { add edi, offset } \ 338 _asm { mov esi, dataptr } \ 339 _asm { add esi, dataoffset } \ 340 _asm { mov ecx, dword_count } \ 341 _asm { rep movsd } \ 342} 343 344/*----------------------------------------------------------------- 345 * WRITE_FB_STRING32 346 * Write a series of DWORDS to video memory. 347 *-----------------------------------------------------------------*/ 348 349#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ 350{ \ 351 unsigned long temp = (unsigned long)(dataptr); \ 352 _asm { cld } \ 353 _asm { mov edi, cim_fb_ptr } \ 354 _asm { add edi, offset } \ 355 _asm { mov esi, temp } \ 356 _asm { mov ecx, dword_count } \ 357 _asm { rep movsd } \ 358} 359 360/*----------------------------------------------------------------- 361 * WRITE_FB_CONSTANT 362 * Write a constant DWORD to multiple video memory addresses 363 *-----------------------------------------------------------------*/ 364 365#define WRITE_FB_CONSTANT(offset, value, dword_count) \ 366{ \ 367 unsigned long outptr = (unsigned long)cim_fb_ptr + offset; \ 368 unsigned long dwords = dword_count; \ 369 _asm { cld } \ 370 _asm { mov edi, outptr } \ 371 _asm { mov eax, value } \ 372 _asm { mov ecx, dwords } \ 373 _asm { rep stosd } \ 374} 375 376/*----------------------------------------------------------------- 377 * WRITE_HOST_SOURCE_STRING32 378 * Write a series of DWORDs to the GP host source register 379 *-----------------------------------------------------------------*/ 380 381#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ 382{ \ 383 _asm { cld } \ 384 _asm { mov edi, cim_gp_ptr } \ 385 _asm { add edi, GP3_HST_SRC_RANGE } \ 386 _asm { mov esi, dataptr } \ 387 _asm { add esi, dataoffset } \ 388 _asm { mov ecx, dword_count } \ 389 _asm { rep movsd } \ 390} 391 392#elif CIMARRON_OPTIMIZE_FORLOOP 393 394/*----------------------------------------------------------------- 395 * WRITE_COMMAND_STRING32 396 * Write a series of DWORDs to the current command buffer offset 397 *-----------------------------------------------------------------*/ 398 399#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ 400{ \ 401 unsigned long i; \ 402 unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ 403 unsigned long byte_off = 0; \ 404 for (i = 0; i < dword_count; i++, byte_off += 4) \ 405 WRITE_COMMAND32 ((offset) + byte_off, \ 406 *((unsigned long *)(tempdata + byte_off))); \ 407} 408 409/*----------------------------------------------------------------- 410 * WRITE_FB_STRING32 411 * Write a series of DWORDS to video memory. 412 *-----------------------------------------------------------------*/ 413 414#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ 415{ \ 416 unsigned long i; \ 417 unsigned long tempdata = (unsigned long)dataptr; \ 418 unsigned long byte_off = 0; \ 419 for (i = 0; i < dword_count; i++, byte_off += 4) \ 420 WRITE_FB32 ((offset) + byte_off, \ 421 *((unsigned long *)(tempdata + byte_off))); \ 422} 423 424/*----------------------------------------------------------------- 425 * WRITE_FB_CONSTANT 426 * Write a constant DWORD to multiple video memory addresses 427 *-----------------------------------------------------------------*/ 428 429#define WRITE_FB_CONSTANT(offset, value, dword_count) \ 430{ \ 431 unsigned long i; \ 432 unsigned long tempoffset = offset; \ 433 for (i = 0; i < dword_count; i++, tempoffset += 4) \ 434 WRITE_FB32 (tempoffset, value); \ 435} 436 437/*----------------------------------------------------------------- 438 * WRITE_HOST_SOURCE_STRING32 439 * Write a series of DWORDs to the GP host source register 440 *-----------------------------------------------------------------*/ 441 442#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ 443{ \ 444 unsigned long i; \ 445 unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ 446 unsigned long byte_off = 0; \ 447 for (i = 0; i < dword_count; i++, byte_off += 4) \ 448 WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, \ 449 *((unsigned long *)(tempdata + byte_off))); \ 450} 451 452#elif CIMARRON_OPTIMIZE_ABSTRACTED_ASM 453 454#define move_dw(d,s,n) \ 455 __asm__ __volatile__( \ 456 " rep\n" \ 457 " movsl\n" \ 458 : "=&c" (d0), "=&S" (d1), "=&D" (d2) \ 459 : "0" (n), "1" ((const char *)s), "2" ((char *)d) \ 460 : "memory") 461 462/*----------------------------------------------------------------- 463 * WRITE_COMMAND_STRING32 464 * Write a series of DWORDs to the current command buffer offset 465 *-----------------------------------------------------------------*/ 466 467#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ 468{ \ 469 int d0, d1, d2; \ 470 move_dw (cim_cmd_ptr+ ((unsigned long)(offset)), \ 471 ((unsigned long)(dataptr)+(dataoffset)), \ 472 dword_count); \ 473} 474 475/*----------------------------------------------------------------- 476 * WRITE_FB_STRING32 477 * Write a series of DWORDS to video memory. 478 *-----------------------------------------------------------------*/ 479 480#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ 481{ \ 482 unsigned long i; \ 483 unsigned long tempdata = (unsigned long)dataptr; \ 484 unsigned long byte_off = 0; \ 485 for (i = 0; i < dword_count; i++, byte_off += 4) \ 486 WRITE_FB32 ((offset) + byte_off, \ 487 *((unsigned long *)(tempdata + byte_off))); \ 488} 489 490/*----------------------------------------------------------------- 491 * WRITE_FB_CONSTANT 492 * Write a constant DWORD to multiple video memory addresses 493 *-----------------------------------------------------------------*/ 494 495#define WRITE_FB_CONSTANT(offset, value, dword_count) \ 496{ \ 497 unsigned long i; \ 498 unsigned long tempoffset = offset; \ 499 for (i = 0; i < dword_count; i++, tempoffset += 4) \ 500 WRITE_FB32 (tempoffset, value); \ 501} 502 503/*----------------------------------------------------------------- 504 * WRITE_HOST_SOURCE_STRING32 505 * Write a series of DWORDs to the GP host source register 506 *-----------------------------------------------------------------*/ 507 508#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ 509{ \ 510 unsigned long i; \ 511 unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ 512 unsigned long byte_off = 0; \ 513 for (i = 0; i < dword_count; i++, byte_off += 4) \ 514 WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, \ 515 *((unsigned long *)(tempdata + byte_off))); \ 516} 517 518#endif 519 520#endif /* #ifdef CIMARRON_INCLUDE_STRING_MACROS */ 521 522/*----------------------------------------------------------------- 523 * WRITE_COMMAND_STRING8 524 * Write a series of bytes to the current command buffer offset 525 *-----------------------------------------------------------------*/ 526 527#define WRITE_COMMAND_STRING8(offset, dataptr, dataoffset, byte_count) \ 528{ \ 529 unsigned long i; \ 530 unsigned long array = (unsigned long)dataptr + (dataoffset); \ 531 for (i = 0; i < byte_count; i++) \ 532 WRITE_COMMAND8 ((offset) + i, *((unsigned char *)(array + i))); \ 533} 534 535/*----------------------------------------------------------------- 536 * WRITE_HOST_SOURCE_STRING8 537 * Write a series of bytes to the host source register 538 *-----------------------------------------------------------------*/ 539 540#define WRITE_HOST_SOURCE_STRING8(dataptr, dataoffset, byte_count) \ 541{ \ 542 unsigned long temp1 = (unsigned long)dataptr + (dataoffset); \ 543 unsigned long temp2 = 0; \ 544 unsigned long shift = 0; \ 545 unsigned long counter; \ 546 if (byte_count) \ 547 { \ 548 for (counter = 0; counter < byte_count; counter++) \ 549 { \ 550 temp2 |= ((unsigned long)(*((unsigned char *) \ 551 (temp1 + counter)))) << shift; \ 552 shift += 8; \ 553 } \ 554 WRITE_GP32 (GP3_HST_SRC, temp2); \ 555 } \ 556} 557 558/*-----------------------------------------*/ 559/* CUSTOM STRING MACROS */ 560/*-----------------------------------------*/ 561 562#ifndef CIMARRON_EXCLUDE_CUSTOM_MACROS 563 564#define WRITE_CUSTOM_COMMAND_STRING32 WRITE_COMMAND_STRING32 565#define WRITE_CUSTOM_COMMAND_STRING8 WRITE_COMMAND_STRING8 566 567#endif 568 569/*-----------------------------------------*/ 570/* IO ACCESS MACROS */ 571/*-----------------------------------------*/ 572 573#ifdef CIMARRON_INCLUDE_IO_MACROS 574 575#if CIMARRON_IO_DIRECT_ACCESS 576 577/*------------------------------------------- 578 * OUTD 579 * Writes one DWORD to a single I/O address. 580 *-------------------------------------------*/ 581 582#define OUTD(port, data) cim_outd(port, data) 583void 584cim_outd(unsigned short port, unsigned long data) 585{ 586 _asm { 587pushf mov eax, data mov dx, port out dx, eax popf}} 588/*------------------------------------------- 589 * IND 590 * Reads one DWORD from a single I/O address. 591 *-------------------------------------------*/ 592#define IND(port) cim_ind(port) 593unsigned long 594cim_ind(unsigned short port) 595{ 596 unsigned long data; 597 598 _asm { 599 pushf mov dx, port in eax, dx mov data, eax popf} return data; 600} 601 602/*------------------------------------------- 603 * OUTW 604 * Writes one WORD to a single I/O address. 605 *-------------------------------------------*/ 606 607#define OUTW(port, data) cim_outw(port, data) 608void 609cim_outw(unsigned short port, unsigned short data) 610{ 611 _asm { 612pushf mov ax, data mov dx, port out dx, ax popf}} 613/*------------------------------------------- 614 * INW 615 * Reads one WORD from a single I/O address. 616 *-------------------------------------------*/ 617#define INW(port) cim_inw(port) 618unsigned short 619cim_inw(unsigned short port) 620{ 621 unsigned short data; 622 623 _asm { 624 pushf mov dx, port in ax, dx mov data, ax popf} return data; 625} 626 627/*------------------------------------------- 628 * OUTB 629 * Writes one BYTE to a single I/O address. 630 *-------------------------------------------*/ 631 632#define OUTB(port, data) cim_outb(port, data) 633void 634cim_outb(unsigned short port, unsigned char data) 635{ 636 _asm { 637pushf mov al, data mov dx, port out dx, al popf}} 638/*------------------------------------------- 639 * INB 640 * Reads one BYTE from a single I/O address. 641 *-------------------------------------------*/ 642#define INB(port) cim_inb(port) 643unsigned char 644cim_inb(unsigned short port) 645{ 646 unsigned char data; 647 648 _asm { 649 pushf mov dx, port in al, dx mov data, al popf} return data; 650} 651 652#elif CIMARRON_IO_ABSTRACTED_ASM 653 654/*------------------------------------------- 655 * OUTD 656 * Writes one DWORD to a single I/O address. 657 *-------------------------------------------*/ 658 659#define OUTD(port, data) cim_outd(port, data) 660void cim_outd(unsigned short port, unsigned long data); 661void 662cim_outd(unsigned short port, unsigned long data) 663{ 664 __asm__ __volatile__("outl %0,%w1"::"a"(data), "Nd"(port)); 665} 666 667/*------------------------------------------- 668 * IND 669 * Reads one DWORD from a single I/O address. 670 *-------------------------------------------*/ 671 672#define IND(port) cim_ind(port) 673unsigned long cim_ind(unsigned short port); 674unsigned long 675cim_ind(unsigned short port) 676{ 677 unsigned long value; 678 __asm__ __volatile__("inl %w1,%0":"=a"(value):"Nd"(port)); 679 680 return value; 681} 682 683/*------------------------------------------- 684 * OUTW 685 * Writes one WORD to a single I/O address. 686 *-------------------------------------------*/ 687 688#define OUTW(port, data) cim_outw(port, data) 689void cim_outw(unsigned short port, unsigned short data); 690void 691cim_outw(unsigned short port, unsigned short data) 692{ 693 __asm__ volatile ("out %0,%1"::"a" (data), "d"(port)); 694} 695 696/*------------------------------------------- 697 * INW 698 * Reads one WORD from a single I/O address. 699 *-------------------------------------------*/ 700 701#define INW(port) cim_inw(port) 702unsigned short cim_inw(unsigned short port); 703unsigned short 704cim_inw(unsigned short port) 705{ 706 unsigned short value; 707 __asm__ volatile ("in %1,%0":"=a" (value):"d"(port)); 708 709 return value; 710} 711 712/*------------------------------------------- 713 * INB 714 * Reads one BYTE from a single I/O address. 715 *-------------------------------------------*/ 716 717#define INB(port) cim_inb(port) 718unsigned char cim_inb(unsigned short port); 719unsigned char 720cim_inb(unsigned short port) 721{ 722 unsigned char value; 723 __asm__ volatile ("inb %1,%0":"=a" (value):"d"(port)); 724 725 return value; 726} 727 728/*------------------------------------------- 729 * OUTB 730 * Writes one BYTE to a single I/O address. 731 *-------------------------------------------*/ 732 733#define OUTB(port) cim_outb(port) 734void cim_outb(unsigned short port, unsigned char data); 735void 736cim_outb(unsigned short port, unsigned char data) 737{ 738 __asm__ volatile ("outb %0,%1"::"a" (data), "d"(port)); 739} 740 741#endif 742 743#endif /* CIMARRON_INCLUDE_IO_MACROS */ 744 745extern void (*cim_rdmsr) (unsigned long, unsigned long *, unsigned long *); 746extern void (*cim_wrmsr) (unsigned long, unsigned long, unsigned long); 747 748#endif 749