Added copy_phys_to_phys
[people/xl0/gpxe.git] / src / arch / i386 / include / virtaddr.h
1 #ifndef VIRTADDR_H
2 #define VIRTADDR_H
3
4 /* Segment selectors as used in our protected-mode GDTs.
5  *
6  * Don't change these unless you really know what you're doing.
7  */
8 #define PHYSICAL_CS 0x08
9 #define PHYSICAL_DS 0x10
10 #define VIRTUAL_CS 0x18
11 #define VIRTUAL_DS 0x20
12 #define LONG_CS 0x28
13 #define LONG_DS 0x30
14
15 #ifndef ASSEMBLY
16
17 #include "stdint.h"
18 #include "string.h"
19
20 #ifndef KEEP_IT_REAL
21
22 /*
23  * Without -DKEEP_IT_REAL, we are in 32-bit protected mode with a
24  * fixed link address but an unknown physical start address.  Our GDT
25  * sets up code and data segments with an offset of virt_offset, so
26  * that link-time addresses can still work.
27  *
28  */
29
30 /* C-callable function prototypes */
31
32 extern void relocate_to ( uint32_t new_phys_addr );
33
34 /* Variables in virtaddr.S */
35 extern unsigned long virt_offset;
36
37 /*
38  * Convert between virtual and physical addresses
39  *
40  */
41 static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
42         return ( ( unsigned long ) virt_addr ) + virt_offset;
43 }
44
45 static inline void * phys_to_virt ( unsigned long phys_addr ) {
46         return ( void * ) ( phys_addr - virt_offset );
47 }
48
49 static inline void copy_to_phys ( physaddr_t dest, void *src, size_t len ) {
50         memcpy ( phys_to_virt ( dest ), src, len );
51 }
52
53 static inline void copy_from_phys ( void *dest, physaddr_t src, size_t len ) {
54         memcpy ( dest, phys_to_virt ( src ), len );
55 }
56
57 static inline void copy_phys_to_phys ( physaddr_t dest, physaddr_t src,
58                                        size_t len ) {
59         memcpy ( phys_to_virt ( dest ), phys_to_virt ( src ), len );
60 }
61
62 #else /* KEEP_IT_REAL */
63
64 /*
65  * With -DKEEP_IT_REAL, we are in 16-bit real mode with fixed link
66  * addresses and a segmented memory model.  We have separate code and
67  * data segments.
68  *
69  * Because we may be called in 16-bit protected mode (damn PXE spec),
70  * we cannot simply assume that physical = segment * 16 + offset.
71  * Instead, we have to look up the physical start address of the
72  * segment in the !PXE structure.  We have to assume that
73  * virt_to_phys() is called only on pointers within the data segment,
74  * because nothing passes segment information to us.
75  *
76  * We don't implement phys_to_virt at all, because there will be many
77  * addresses that simply cannot be reached via a virtual address when
78  * the virtual address space is limited to 64kB!
79  */
80
81 static inline unsigned long virt_to_phys ( volatile const void *virt_addr ) {
82         /* Cheat: just for now, do the segment*16+offset calculation */
83         uint16_t ds;
84
85         __asm__ ( "movw %%ds, %%ax" : "=a" ( ds ) : );
86         return ( 16 * ds + ( ( unsigned long ) virt_addr ) );
87 }
88
89 /* Define it as a deprecated function so that we get compile-time
90  * warnings, rather than just the link-time errors.
91  */
92 extern void * phys_to_virt ( unsigned long phys_addr )
93      __attribute__ ((deprecated));
94
95 #endif /* KEEP_IT_REAL */
96
97 #endif /* ASSEMBLY */
98
99 #endif /* VIRTADDR_H */