2
* Copyright (c) 2006 Advanced Micro Devices, Inc.
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:
11
* The above copyright notice and this permission notice shall be included in
12
* all copies or substantial portions of the Software.
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.
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.
28
* Cimarron hardware access macros.
34
/*-----------------------------------------*/
35
/* MEMORY ACCESS MACROS */
36
/*-----------------------------------------*/
38
#ifndef CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS
40
#define READ_GP32(offset) \
41
(*(volatile unsigned long *)(cim_gp_ptr + (offset)))
43
#define READ_REG32(offset) \
44
(*(volatile unsigned long *)(cim_vg_ptr + (offset)))
46
#define READ_FB32(offset) \
47
(*(volatile unsigned long *)(cim_fb_ptr + (offset)))
49
#define WRITE_GP32(offset, value) \
50
(*(volatile unsigned long *)(cim_gp_ptr + (offset))) = (value)
52
#define WRITE_REG32(offset, value) \
53
(*(volatile unsigned long *)(cim_vg_ptr + (offset))) = (value)
55
#define WRITE_COMMAND32(offset, value) \
56
(*(unsigned long *)(cim_cmd_ptr + (offset))) = (value)
58
#define WRITE_COMMAND8(offset, value) \
59
(*(unsigned char *)(cim_cmd_ptr + (offset))) = (value)
61
#define WRITE_FB32(offset, value) \
62
(*(unsigned long *)(cim_fb_ptr + (offset))) = (value)
64
#define READ_VID32(offset) \
65
(*(volatile unsigned long *)(cim_vid_ptr + (offset)))
67
#define WRITE_VID32(offset, value) \
68
(*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value)
70
#define READ_VIP32(offset) \
71
(*(volatile unsigned long *)(cim_vip_ptr + (offset)))
73
#define WRITE_VIP32(offset, value) \
74
(*(volatile unsigned long *)(cim_vip_ptr + (offset))) = (value)
76
#define READ_VOP32(offset) \
77
(*(volatile unsigned long *)(cim_vid_ptr + (offset)))
79
#define WRITE_VOP32(offset, value) \
80
(*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value)
84
/*-----------------------------------------*/
85
/* GP POLLING MACROS */
86
/*-----------------------------------------*/
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)))
92
#define GP3_WAIT_PRIMITIVE(variable) \
93
while (((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) && \
94
(variable <= (gp3_cmd_next + 96)))
96
#define GP3_WAIT_BUSY \
97
while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_BUSY)
99
#define GP3_WAIT_PENDING \
100
while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_PENDING)
102
/*-----------------------------------------------------------------*/
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 */
108
/*-----------------------------------------------------------------*/
110
#ifdef CIMARRON_INCLUDE_MSR_MACROS
112
#if CIMARRON_MSR_DIRECT_ASM
114
/*-----------------------------------------------------------------
116
* Read the contents of a 64 bit MSR into a data structure
117
*-----------------------------------------------------------------*/
119
#define MSR_READ(msr_reg, device_add, data64_ptr) \
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 } \
126
_asm { mov data_high, edx } \
127
_asm { mov data_low, eax } \
129
((Q_WORD *)(data64_ptr))->high = data_high; \
130
((Q_WORD *)(data64_ptr))->low = data_low; \
133
/*-----------------------------------------------------------------
135
* Write the contents of a 64 bit data structure to a MSR.
136
*-----------------------------------------------------------------*/
138
#define MSR_WRITE(msr_reg, device_add, data64_ptr) \
140
unsigned long msr_add = (unsigned long)(msr_reg) | \
141
(unsigned long)(device_add); \
142
unsigned long data_high, data_low; \
144
data_high = ((Q_WORD *)(data64_ptr))->high; \
145
data_low = ((Q_WORD *)(data64_ptr))->low; \
147
_asm { mov ecx, msr_add } \
148
_asm { mov edx, data_high } \
149
_asm { mov eax, data_low } \
153
#elif CIMARRON_MSR_VSA_IO
155
/*-----------------------------------------------------------------
157
* Read the contents of a 64 bit MSR into a data structure
158
*-----------------------------------------------------------------*/
160
#define MSR_READ(msr_reg, device_add, data64_ptr) \
162
unsigned long msr_add = (unsigned long)(msr_reg) | \
163
(unsigned long)(device_add); \
164
unsigned long data_high, data_low; \
166
_asm { mov dx, 0x0AC1C } \
167
_asm { mov eax, 0x0FC530007 } \
168
_asm { out dx, eax } \
171
_asm { mov ecx, msr_add } \
173
_asm { mov data_high, edx } \
174
_asm { mov data_low, eax } \
176
((Q_WORD *)(data64_ptr))->high = data_high; \
177
((Q_WORD *)(data64_ptr))->low = data_low; \
180
/*-----------------------------------------------------------------
182
* Write the contents of a 64 bit data structure to a MSR.
183
*-----------------------------------------------------------------*/
185
#define MSR_WRITE(msr_reg, device_add, data64_ptr) \
187
unsigned long msr_add = (unsigned long)(msr_reg) | \
188
(unsigned long)(device_add); \
189
unsigned long data_high, data_low; \
191
data_high = ((Q_WORD *)(data64_ptr))->high; \
192
data_low = ((Q_WORD *)(data64_ptr))->low; \
194
_asm { mov dx, 0x0AC1C } \
195
_asm { mov eax, 0x0FC530007 } \
196
_asm { out dx, eax } \
199
_asm { mov ecx, msr_add } \
200
_asm { mov ebx, data_high } \
201
_asm { mov eax, data_low } \
203
_asm { mov esi, 0 } \
204
_asm { mov edi, 0 } \
205
_asm { out dx, ax } \
208
#elif CIMARRON_MSR_ABSTRACTED_ASM
210
/*-----------------------------------------------------------------
212
* Read the contents of a 64 bit MSR into a data structure
213
*-----------------------------------------------------------------*/
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" \
222
: "=a" ((val)->low), "=d" ((val)->high) \
225
/*-----------------------------------------------------------------
227
* Write the contents of a 64 bit data structure to a MSR.
228
*-----------------------------------------------------------------*/
230
#define MSR_WRITE(msr,adr,val) \
231
{ int d0, d1, d2, d3; \
232
__asm__ __volatile__( \
234
" mov $0x0AC1C, %%edx\n" \
235
" mov $0xFC530007, %%eax\n" \
236
" out %%eax,%%dx\n" \
239
" mov 0(%5), %%ebx\n" \
243
" out %%ax, %%dx\n" \
245
: "=a" (d0), "=&D" (d1), "=&S" (d2), "=c" (d3) \
246
: "1" (msr | adr), "2" (val)); \
249
#elif CIMARRON_MSR_KERNEL_ROUTINE
253
/*-----------------------------------------------------------------
255
* Read the contents of a 64 bit MSR into a data structure
256
*-----------------------------------------------------------------*/
258
#define MSR_READ(msr_reg, device_add, data64_ptr) \
260
unsigned long addr, val1, val2; \
262
addr = device_add | msr_reg; \
263
rdmsr (addr, val1, val2); \
265
((Q_WORD *)(data64_ptr))->high = val2; \
266
((Q_WORD *)(data64_ptr))->low = val1; \
269
/*-----------------------------------------------------------------
271
* Read the contents of a 64 bit data structure to a MSR.
272
*-----------------------------------------------------------------*/
274
#define MSR_WRITE(msr_reg, device_add, data64_ptr) \
276
unsigned long addr, val1, val2; \
278
val2 = ((Q_WORD *)(data64_ptr))->high; \
279
val1 = ((Q_WORD *)(data64_ptr))->low; \
281
addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg; \
282
wrmsr(addr, val1, val2); \
285
#elif CIMARRON_MSR_HOOKS
287
#define MSR_READ(msr_reg, device_add, data64_ptr) \
289
unsigned long addr, val1, val2; \
291
addr = device_add | msr_reg; \
293
cim_rdmsr (addr, &val1, &val2); \
295
((Q_WORD *)(data64_ptr))->high = val2; \
296
((Q_WORD *)(data64_ptr))->low = val1; \
300
#define MSR_WRITE(msr_reg, device_add, data64_ptr) \
302
unsigned long addr, val1, val2; \
304
val2 = ((Q_WORD *)(data64_ptr))->high; \
305
val1 = ((Q_WORD *)(data64_ptr))->low; \
307
addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg; \
309
cim_wrmsr(addr, val1, val2); \
313
#endif /* #ifdef CIMARRON_INCLUDE_MSR_MACROS */
315
/*-----------------------------------------------------------------*/
317
/* These macros are included to facilitate the optimization of */
318
/* routines that write or copy large amounts of data. Two vesions */
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
/*-----------------------------------------------------------------*/
324
#ifdef CIMARRON_INCLUDE_STRING_MACROS
326
#if CIMARRON_OPTIMIZE_ASSEMBLY
328
/*-----------------------------------------------------------------
329
* WRITE_COMMAND_STRING32
330
* Write a series of DWORDs to the current command buffer offset
331
*-----------------------------------------------------------------*/
333
#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \
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 } \
344
/*-----------------------------------------------------------------
346
* Write a series of DWORDS to video memory.
347
*-----------------------------------------------------------------*/
349
#define WRITE_FB_STRING32(offset, dataptr, dword_count) \
351
unsigned long temp = (unsigned long)(dataptr); \
353
_asm { mov edi, cim_fb_ptr } \
354
_asm { add edi, offset } \
355
_asm { mov esi, temp } \
356
_asm { mov ecx, dword_count } \
360
/*-----------------------------------------------------------------
362
* Write a constant DWORD to multiple video memory addresses
363
*-----------------------------------------------------------------*/
365
#define WRITE_FB_CONSTANT(offset, value, dword_count) \
367
unsigned long outptr = (unsigned long)cim_fb_ptr + offset; \
368
unsigned long dwords = dword_count; \
370
_asm { mov edi, outptr } \
371
_asm { mov eax, value } \
372
_asm { mov ecx, dwords } \
376
/*-----------------------------------------------------------------
377
* WRITE_HOST_SOURCE_STRING32
378
* Write a series of DWORDs to the GP host source register
379
*-----------------------------------------------------------------*/
381
#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \
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 } \
392
#elif CIMARRON_OPTIMIZE_FORLOOP
394
/*-----------------------------------------------------------------
395
* WRITE_COMMAND_STRING32
396
* Write a series of DWORDs to the current command buffer offset
397
*-----------------------------------------------------------------*/
399
#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \
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))); \
409
/*-----------------------------------------------------------------
411
* Write a series of DWORDS to video memory.
412
*-----------------------------------------------------------------*/
414
#define WRITE_FB_STRING32(offset, dataptr, dword_count) \
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))); \
424
/*-----------------------------------------------------------------
426
* Write a constant DWORD to multiple video memory addresses
427
*-----------------------------------------------------------------*/
429
#define WRITE_FB_CONSTANT(offset, value, dword_count) \
432
unsigned long tempoffset = offset; \
433
for (i = 0; i < dword_count; i++, tempoffset += 4) \
434
WRITE_FB32 (tempoffset, value); \
437
/*-----------------------------------------------------------------
438
* WRITE_HOST_SOURCE_STRING32
439
* Write a series of DWORDs to the GP host source register
440
*-----------------------------------------------------------------*/
442
#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \
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))); \
452
#elif CIMARRON_OPTIMIZE_ABSTRACTED_ASM
454
#define move_dw(d,s,n) \
455
__asm__ __volatile__( \
458
: "=&c" (d0), "=&S" (d1), "=&D" (d2) \
459
: "0" (n), "1" ((const char *)s), "2" ((char *)d) \
462
/*-----------------------------------------------------------------
463
* WRITE_COMMAND_STRING32
464
* Write a series of DWORDs to the current command buffer offset
465
*-----------------------------------------------------------------*/
467
#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \
470
move_dw (cim_cmd_ptr+ ((unsigned long)(offset)), \
471
((unsigned long)(dataptr)+(dataoffset)), \
475
/*-----------------------------------------------------------------
477
* Write a series of DWORDS to video memory.
478
*-----------------------------------------------------------------*/
480
#define WRITE_FB_STRING32(offset, dataptr, dword_count) \
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))); \
490
/*-----------------------------------------------------------------
492
* Write a constant DWORD to multiple video memory addresses
493
*-----------------------------------------------------------------*/
495
#define WRITE_FB_CONSTANT(offset, value, dword_count) \
498
unsigned long tempoffset = offset; \
499
for (i = 0; i < dword_count; i++, tempoffset += 4) \
500
WRITE_FB32 (tempoffset, value); \
503
/*-----------------------------------------------------------------
504
* WRITE_HOST_SOURCE_STRING32
505
* Write a series of DWORDs to the GP host source register
506
*-----------------------------------------------------------------*/
508
#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \
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))); \
520
#endif /* #ifdef CIMARRON_INCLUDE_STRING_MACROS */
522
/*-----------------------------------------------------------------
523
* WRITE_COMMAND_STRING8
524
* Write a series of bytes to the current command buffer offset
525
*-----------------------------------------------------------------*/
527
#define WRITE_COMMAND_STRING8(offset, dataptr, dataoffset, byte_count) \
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))); \
535
/*-----------------------------------------------------------------
536
* WRITE_HOST_SOURCE_STRING8
537
* Write a series of bytes to the host source register
538
*-----------------------------------------------------------------*/
540
#define WRITE_HOST_SOURCE_STRING8(dataptr, dataoffset, byte_count) \
542
unsigned long temp1 = (unsigned long)dataptr + (dataoffset); \
543
unsigned long temp2 = 0; \
544
unsigned long shift = 0; \
545
unsigned long counter; \
548
for (counter = 0; counter < byte_count; counter++) \
550
temp2 |= ((unsigned long)(*((unsigned char *) \
551
(temp1 + counter)))) << shift; \
554
WRITE_GP32 (GP3_HST_SRC, temp2); \
558
/*-----------------------------------------*/
559
/* CUSTOM STRING MACROS */
560
/*-----------------------------------------*/
562
#ifndef CIMARRON_EXCLUDE_CUSTOM_MACROS
564
#define WRITE_CUSTOM_COMMAND_STRING32 WRITE_COMMAND_STRING32
565
#define WRITE_CUSTOM_COMMAND_STRING8 WRITE_COMMAND_STRING8
569
/*-----------------------------------------*/
570
/* IO ACCESS MACROS */
571
/*-----------------------------------------*/
573
#ifdef CIMARRON_INCLUDE_IO_MACROS
575
#if CIMARRON_IO_DIRECT_ACCESS
577
/*-------------------------------------------
579
* Writes one DWORD to a single I/O address.
580
*-------------------------------------------*/
582
#define OUTD(port, data) cim_outd(port, data)
584
cim_outd(unsigned short port, unsigned long data)
587
pushf mov eax, data mov dx, port out dx, eax popf}}
588
/*-------------------------------------------
590
* Reads one DWORD from a single I/O address.
591
*-------------------------------------------*/
592
#define IND(port) cim_ind(port)
594
cim_ind(unsigned short port)
599
pushf mov dx, port in eax, dx mov data, eax popf} return data;
602
/*-------------------------------------------
604
* Writes one WORD to a single I/O address.
605
*-------------------------------------------*/
607
#define OUTW(port, data) cim_outw(port, data)
609
cim_outw(unsigned short port, unsigned short data)
612
pushf mov ax, data mov dx, port out dx, ax popf}}
613
/*-------------------------------------------
615
* Reads one WORD from a single I/O address.
616
*-------------------------------------------*/
617
#define INW(port) cim_inw(port)
619
cim_inw(unsigned short port)
624
pushf mov dx, port in ax, dx mov data, ax popf} return data;
627
/*-------------------------------------------
629
* Writes one BYTE to a single I/O address.
630
*-------------------------------------------*/
632
#define OUTB(port, data) cim_outb(port, data)
634
cim_outb(unsigned short port, unsigned char data)
637
pushf mov al, data mov dx, port out dx, al popf}}
638
/*-------------------------------------------
640
* Reads one BYTE from a single I/O address.
641
*-------------------------------------------*/
642
#define INB(port) cim_inb(port)
644
cim_inb(unsigned short port)
649
pushf mov dx, port in al, dx mov data, al popf} return data;
652
#elif CIMARRON_IO_ABSTRACTED_ASM
654
/*-------------------------------------------
656
* Writes one DWORD to a single I/O address.
657
*-------------------------------------------*/
659
#define OUTD(port, data) cim_outd(port, data)
660
void cim_outd(unsigned short port, unsigned long data);
662
cim_outd(unsigned short port, unsigned long data)
664
__asm__ __volatile__("outl %0,%w1"::"a"(data), "Nd"(port));
667
/*-------------------------------------------
669
* Reads one DWORD from a single I/O address.
670
*-------------------------------------------*/
672
#define IND(port) cim_ind(port)
673
unsigned long cim_ind(unsigned short port);
675
cim_ind(unsigned short port)
678
__asm__ __volatile__("inl %w1,%0":"=a"(value):"Nd"(port));
683
/*-------------------------------------------
685
* Writes one WORD to a single I/O address.
686
*-------------------------------------------*/
688
#define OUTW(port, data) cim_outw(port, data)
689
void cim_outw(unsigned short port, unsigned short data);
691
cim_outw(unsigned short port, unsigned short data)
693
__asm__ volatile ("out %0,%1"::"a" (data), "d"(port));
696
/*-------------------------------------------
698
* Reads one WORD from a single I/O address.
699
*-------------------------------------------*/
701
#define INW(port) cim_inw(port)
702
unsigned short cim_inw(unsigned short port);
704
cim_inw(unsigned short port)
706
unsigned short value;
707
__asm__ volatile ("in %1,%0":"=a" (value):"d"(port));
712
/*-------------------------------------------
714
* Reads one BYTE from a single I/O address.
715
*-------------------------------------------*/
717
#define INB(port) cim_inb(port)
718
unsigned char cim_inb(unsigned short port);
720
cim_inb(unsigned short port)
723
__asm__ volatile ("inb %1,%0":"=a" (value):"d"(port));
728
/*-------------------------------------------
730
* Writes one BYTE to a single I/O address.
731
*-------------------------------------------*/
733
#define OUTB(port) cim_outb(port)
734
void cim_outb(unsigned short port, unsigned char data);
736
cim_outb(unsigned short port, unsigned char data)
738
__asm__ volatile ("outb %0,%1"::"a" (data), "d"(port));
743
#endif /* CIMARRON_INCLUDE_IO_MACROS */
745
extern void (*cim_rdmsr) (unsigned long, unsigned long *, unsigned long *);
746
extern void (*cim_wrmsr) (unsigned long, unsigned long, unsigned long);