4 Driver for the AMD Device Exclusion Vector (DEV)
10 #include <minix/config.h>
11 #include <minix/type.h>
18 #include <sys/vm_i386.h>
19 #include <minix/com.h>
20 #include <minix/const.h>
21 #include <minix/ipc.h>
22 #include <minix/syslib.h>
23 #include <minix/sysutil.h>
24 #include <minix/endpoint.h>
27 /* Offsets from capability pointer */
28 #define DEV_OP 4 /* Selects control/status register to access */
29 #define DEV_OP_FUNC_SHIFT 8 /* Function part in OP reg. */
30 #define DEV_DATA 8 /* Read/write to access reg. selected */
33 #define DEVF_BASE_LO 0
34 #define DEVF_BASE_HI 1
37 #define DEVF_CAP_MAPS_MASK 0x00ff0000
38 #define DEVF_CAP_MAPS_SHIFT 16
39 #define DEVF_CAP_DOMS_MASK 0x0000ff00
40 #define DEVF_CAP_DOMS_SHIFT 8
41 #define DEVF_CAP_REV_MASK 0x000000ff
42 #define DEVF_CAP_REV_SHIFT 0
44 #define DEVF_ERR_STATUS 5
45 #define DEVF_ERR_ADDR_LO 6
46 #define DEVF_ERR_ADDR_HI 7
48 static int dev_devind
;
49 static u8_t dev_capptr
;
52 static int find_dev(int *devindp
, u8_t
*capaddrp
);
53 static u32_t
read_reg(int function
, int index
);
54 static void write_reg(int function
, int index
, u32_t value
);
55 static void init_domain(int index
);
56 static void init_map(int index
);
57 static int do_add_phys(message
*m
);
58 static int do_del_phys(message
*m
);
59 static int do_add4pci(message
*m
);
60 static void add_range(u32_t busaddr
, u32_t size
);
61 static void del_range(u32_t busaddr
, u32_t size
);
62 static void do_pm_notify(message
*m
);
63 static void report_exceptions(void);
65 /* SEF functions and variables. */
66 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
67 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
74 /* SEF local startup. */
81 r
= sef_receive(ANY
, &m
);
83 panic(__FILE__
, "sef_receive failed", r
);
84 if (is_notify(m
.m_type
)) {
85 if (_ENDPOINT_P(m
.m_source
) == PM_PROC_NR
) {
90 else if (m
.m_type
== IOMMU_MAP
) {
96 printf("amddev: got message from %d\n", m
.m_source
);
100 /*===========================================================================*
101 * sef_local_startup *
102 *===========================================================================*/
103 PRIVATE
void sef_local_startup()
105 /* Register init callbacks. */
106 sef_setcb_init_fresh(sef_cb_init_fresh
);
107 sef_setcb_init_lu(sef_cb_init_fresh
);
108 sef_setcb_init_restart(sef_cb_init_fresh
);
110 /* Register live update callbacks. */
111 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready
);
112 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard
);
114 /* Let SEF perform startup. */
118 /*===========================================================================*
119 * sef_cb_init_fresh *
120 *===========================================================================*/
121 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*info
)
123 /* Initialize the amddev driver. */
124 int r
, n_maps
, n_domains
, revision
;
128 printf("amddev: starting\n");
130 r
= find_dev(&dev_devind
, &dev_capptr
);
133 flags
= pci_attr_r16(dev_devind
, dev_capptr
+CAP_SD_INFO
);
134 printf("amddev`init: flags = 0x%x\n", flags
);
136 bits
= read_reg(DEVF_CAP
, 0);
137 n_maps
= ((bits
& DEVF_CAP_MAPS_MASK
) >> DEVF_CAP_MAPS_SHIFT
);
138 n_domains
= ((bits
& DEVF_CAP_DOMS_MASK
) >> DEVF_CAP_DOMS_SHIFT
);
139 revision
= ((bits
& DEVF_CAP_REV_MASK
) >> DEVF_CAP_REV_SHIFT
);
140 printf("amddev`init: DEVF_CAP = 0x%x (%d maps, %d domains, rev 0x%x)\n",
141 bits
, n_maps
, n_domains
, revision
);
143 printf("status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
144 read_reg(DEVF_ERR_STATUS
, 0),
145 read_reg(DEVF_ERR_ADDR_LO
, 0),
146 read_reg(DEVF_ERR_ADDR_HI
, 0));
154 write_reg(DEVF_CR
, 0, 0x10 | 0x8 | 0x4 | 1);
156 printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR
, 0));
161 /* Returns 0 if no device found, or 1 if a device is found. */
162 static int find_dev(devindp
, capaddrp
)
166 int r
, devind
, first
;
167 u8_t capptr
, type
, next
, subtype
;
168 u16_t vid
, did
, status
;
178 r
= pci_first_dev(&devind
, &vid
, &did
);
181 printf("amddev`find_dev: no first dev\n");
187 r
= pci_next_dev(&devind
, &vid
, &did
);
190 printf("amddev`find_dev: no next dev\n");
195 printf("amddev`find_dev: got devind %d, vid 0x%x, did 0x%x\n",
198 /* Check capabilities bit in the device status register */
199 status
= pci_attr_r16(devind
, PCI_SR
);
200 if (!(status
& PSR_CAPPTR
))
203 capptr
= (pci_attr_r8(devind
, PCI_CAPPTR
) & PCI_CP_MASK
);
206 type
= pci_attr_r8(devind
, capptr
+CAP_TYPE
);
207 next
= (pci_attr_r8(devind
, capptr
+CAP_NEXT
) &
209 if (type
== CAP_T_SECURE_DEV
)
212 "amddev`find_dev: found secure device\n");
213 subtype
= (pci_attr_r8(devind
, capptr
+
214 CAP_SD_INFO
) & CAP_SD_SUBTYPE_MASK
);
215 if (subtype
== CAP_T_SD_DEV
)
217 printf("amddev`find_dev: AMD DEV\n");
230 static u32_t
read_reg(int function
, int index
)
232 pci_attr_w32(dev_devind
, dev_capptr
+ DEV_OP
, ((function
<<
233 DEV_OP_FUNC_SHIFT
) | index
));
234 return pci_attr_r32(dev_devind
, dev_capptr
+ DEV_DATA
);
237 static void write_reg(int function
, int index
, u32_t value
)
239 pci_attr_w32(dev_devind
, dev_capptr
+ DEV_OP
, ((function
<<
240 DEV_OP_FUNC_SHIFT
) | index
));
241 pci_attr_w32(dev_devind
, dev_capptr
+ DEV_DATA
, value
);
244 static void init_domain(int index
)
246 size_t size
, memsize
;
250 table
= alloc_contig(size
, AC_ALIGN4K
, &busaddr
);
252 panic("AMDDEV","malloc failed", NO_NUM
);
255 memset(table
, 0, size
);
256 memsize
= 0x37000 / 8;
257 printf("memsize = 0x%x / 8\n", memsize
*8);
258 memset(table
, 0xff, memsize
);
262 memset(table
, 0xff, size
);
263 memset(table
, 0x00, size
);
266 printf("init_domain: busaddr = %p\n", busaddr
);
268 write_reg(DEVF_BASE_HI
, index
, 0);
269 write_reg(DEVF_BASE_LO
, index
, busaddr
| 3);
271 printf("after write: DEVF_BASE_LO: 0x%x\n",
272 read_reg(DEVF_BASE_LO
, index
));
275 static void init_map(int index
)
277 u32_t v
, dom
, busno
, unit0
, unit1
;
283 v
= (dom
<< 26) | (dom
<< 20) | (busno
<< 12) |
284 (0 << 11) | (unit1
<< 6) |
285 (0 << 5) | (unit0
<< 0);
286 write_reg(DEVF_MAP
, index
, v
);
288 printf("after write: DEVF_MAP: 0x%x\n", read_reg(DEVF_MAP
, index
));
292 static int do_add(message
*m
)
305 printf("amddev`do_add: got request for 0x%x@0x%x from %d\n",
309 if (start
% I386_PAGE_SIZE
)
311 printf("amddev`do_add: bad start 0x%x from proc %d\n",
315 if (size
% I386_PAGE_SIZE
)
317 printf("amddev`do_add: bad size 0x%x from proc %d\n",
321 r
= sys_umap(proc
, VM_D
, (vir_bytes
)start
, size
, &busaddr
);
324 printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n",
328 add_range(busaddr
, size
);
333 static int do_add_phys(message
*m
)
343 printf("amddev`do_add_phys: got request for 0x%x@0x%x\n",
347 if (start
% I386_PAGE_SIZE
)
349 printf("amddev`do_add_phys: bad start 0x%x\n", start
);
352 if (size
% I386_PAGE_SIZE
)
354 printf("amddev`do_add_phys: bad size 0x%x\n", size
);
357 add_range(start
, size
);
359 write_reg(DEVF_CR
, 0, 0x10);
360 for (i
= 0; i
<1000000; i
++)
362 if (read_reg(DEVF_CR
, 0) & 0x10)
369 static int do_del_phys(message
*m
)
378 printf("amddev`do_del_phys: got request for 0x%x@0x%x\n",
382 if (start
% I386_PAGE_SIZE
)
384 printf("amddev`do_del_phys: bad start 0x%x\n", start
);
387 if (size
% I386_PAGE_SIZE
)
389 printf("amddev`do_del_phys: bad size 0x%x\n", size
);
392 del_range(start
, size
);
394 write_reg(DEVF_CR
, 0, 0x10);
399 static int do_add4pci(message
*m
)
401 int r
, pci_bus
, pci_dev
, pci_func
;
415 "amddev`do_add4pci: got request for 0x%x@0x%x from %d for pci dev %u.%u.%u\n",
416 size
, start
, proc
, pci_bus
, pci_dev
, pci_func
);
418 if (start
% I386_PAGE_SIZE
)
420 printf("amddev`do_add4pci: bad start 0x%x from proc %d\n",
424 if (size
% I386_PAGE_SIZE
)
426 printf("amddev`do_add4pci: bad size 0x%x from proc %d\n",
431 printf("amddev`do_add4pci: should check with PCI\n");
433 r
= sys_umap(proc
, VM_D
, (vir_bytes
)start
, size
, &busaddr
);
437 "amddev`do_add4pci: umap failed for 0x%x@0x%x, proc %d: %d\n",
438 size
, start
, proc
, r
);
442 r
= adddma(proc
, start
, size
);
447 "amddev`do_add4pci: adddma failed for 0x%x@0x%x, proc %d: %d\n",
448 size
, start
, proc
, r
);
452 add_range(busaddr
, size
);
458 static void add_range(u32_t busaddr
, u32_t size
)
463 printf("add_range: mapping 0x%x@0x%x\n", size
, busaddr
);
466 for (o
= 0; o
<size
; o
+= I386_PAGE_SIZE
)
468 bit
= (busaddr
+o
)/I386_PAGE_SIZE
;
469 table
[bit
/8] &= ~(1 << (bit
% 8));
473 static void del_range(u32_t busaddr
, u32_t size
)
478 printf("del_range: mapping 0x%x@0x%x\n", size
, busaddr
);
481 for (o
= 0; o
<size
; o
+= I386_PAGE_SIZE
)
483 bit
= (busaddr
+o
)/I386_PAGE_SIZE
;
484 table
[bit
/8] |= (1 << (bit
% 8));
488 static void do_pm_notify(message
*m
)
492 phys_bytes base
, size
;
494 if (m
->m_source
!= PM_PROC_NR
)
496 printf("amddev`do_pm_notify: notify not from PM (from %d)\n",
503 r
= getdma(&proc_e
, &base
, &size
);
506 if (errno
!= -EAGAIN
)
509 "amddev`do_pm_notify: getdma failed: %d\n",
516 "amddev`do_pm_notify: deleting 0x%x@0x%x for proc %d\n",
518 del_range(base
, size
);
519 r
= deldma(proc_e
, base
, size
);
522 printf("amddev`do_pm_notify: deldma failed: %d\n",
529 static void report_exceptions(void)
533 status
= read_reg(DEVF_ERR_STATUS
, 0);
534 if (!(status
& 0x80000000))
536 printf("amddev: status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
537 status
, read_reg(DEVF_ERR_ADDR_LO
, 0),
538 read_reg(DEVF_ERR_ADDR_HI
, 0));
539 write_reg(DEVF_ERR_STATUS
, 0, 0);