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