This source file includes following definitions.
- apm_check
- apm_disconnect
- apm_connect
- apmprobe
- apmfixmem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 #include <sys/param.h>
54 #include "libsa.h"
55 #include <stand/boot/bootarg.h>
56
57 #include <uvm/uvm_extern.h>
58
59 #include <dev/isa/isareg.h>
60
61 #include <machine/apmvar.h>
62 #include <machine/biosvar.h>
63
64 #define vm_page_size 4096
65
66 #include "debug.h"
67
68 extern int debug;
69
70 static __inline u_int
71 apm_check(void)
72 {
73 register u_int detail;
74 register u_int8_t f;
75
76 __asm __volatile(DOINT(0x15) "\n\t"
77 "setc %b1\n\t"
78 "movzwl %%ax, %0\n\t"
79 "shll $16, %%ecx\n\t"
80 "orl %%ecx, %0"
81 : "=a" (detail), "=b" (f)
82 : "0" (APM_INSTCHECK), "1" (APM_DEV_APM_BIOS)
83 : "%ecx", "cc");
84
85 if (f || BIOS_regs.biosr_bx != 0x504d ) {
86 #ifdef DEBUG
87 if (debug)
88 printf("apm_check: %x, %x, %x\n",
89 f, BIOS_regs.biosr_bx, detail);
90 #endif
91 return 0;
92 } else
93 return detail;
94 }
95
96 static __inline int
97 apm_disconnect(void)
98 {
99 register u_int16_t rv;
100
101 __asm __volatile(DOINT(0x15) "\n\t"
102 "setc %b0"
103 : "=a" (rv)
104 : "0" (APM_DISCONNECT), "b" (APM_DEV_APM_BIOS)
105 : "%ecx", "%edx", "cc");
106
107 return ((rv & 0xff)? rv >> 8 : 0);
108 }
109
110 static __inline int
111 apm_connect(bios_apminfo_t *ai)
112 {
113 register u_int16_t f;
114
115 __asm __volatile (DOINT(0x15) "\n\t"
116 "setc %b1\n\t"
117 "movb %%ah, %h1\n\t"
118 "movzwl %%ax, %%eax\n\tshll $4, %0\n\t"
119 "movzwl %%cx, %%ecx\n\tshll $4, %2\n\t"
120 "movzwl %%dx, %%edx\n\tshll $4, %3\n\t"
121 : "=a" (ai->apm_code32_base),
122 "=b" (f),
123 "=c" (ai->apm_code16_base),
124 "=d" (ai->apm_data_base)
125 : "0" (APM_PROT32_CONNECT), "1" (APM_DEV_APM_BIOS)
126 : "cc");
127
128 if (f & 0xff)
129 return (f >> 8);
130
131 ai->apm_entry = BIOS_regs.biosr_bx;
132 #if 0
133 ai->apm_code_len = BIOS_regs.biosr_si & 0xffff;
134 ai->apm_code16_len = BIOS_regs.biosr_si & 0xffff;
135 ai->apm_data_len = BIOS_regs.biosr_di & 0xffff;
136 #else
137 ai->apm_code_len = 0xffff - (ai->apm_code32_base & 0xffff);
138 ai->apm_code16_len = 0xffff - (ai->apm_code16_base & 0xffff);
139 ai->apm_data_len = 0xffff - (ai->apm_data_base & 0xffff);
140 #endif
141 if (ai->apm_data_base < BOOTARG_OFF)
142 ai->apm_data_len = NBPG - (ai->apm_data_base & PGOFSET) - 1;
143
144 #ifdef DEBUG
145 if (debug)
146 printf("cs=%x:%x/%x:%x, ds=%x:%x\n",
147 ai->apm_code32_base, ai->apm_code_len,
148 ai->apm_code16_base, ai->apm_code16_len,
149 ai->apm_data_base, ai->apm_data_len);
150 #endif
151
152 __asm __volatile (DOINT(0x15) "\n\t"
153 "setc %b1\n\t"
154 "movb %%ah, %h1"
155 : "=b" (f)
156 : "a" (APM_DRIVER_VERSION),
157 "0" (APM_DEV_APM_BIOS),
158 "c" (APM_VERSION)
159 : "cc");
160
161 return 0;
162 }
163
164 static bios_apminfo_t ai;
165
166 void
167 apmprobe(void)
168 {
169 if ((ai.apm_detail = apm_check())) {
170
171 apm_disconnect();
172
173 if (apm_connect(&ai) != 0) {
174 printf("\napm: connect error\n");
175 return;
176 }
177 #ifdef DEBUG
178 if (debug)
179 printf("apm[%x cs=%x[%x]/%x[%x] ds=%x[%x] @ %x]",
180 ai.apm_detail,
181 ai.apm_code32_base, ai.apm_code_len,
182 ai.apm_code16_base, ai.apm_code16_len,
183 ai.apm_data_base, ai.apm_data_len,
184 ai.apm_entry);
185 else
186 printf(" apm");
187 #else
188 printf(" apm");
189 #endif
190 addbootarg(BOOTARG_APMINFO, sizeof(ai), &ai);
191 }
192 }
193
194 void
195 apmfixmem(void)
196 {
197 #ifdef DEBUG
198 printf("apmremove (%d)", ai.apm_detail);
199 #endif
200 if (ai.apm_detail)
201 mem_delete(trunc_page(ai.apm_data_base),
202 round_page(ai.apm_data_base + ai.apm_data_len));
203 }