1 /*
2 * Copyright (c) 2009, Intel Corporation.
3 * All Rights Reserved.
4 */
5
6 /*
7 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
8 * Use is subject to license terms.
9 */
10 /*
11 * Portions Philip Brown phil@bolthole.com Dec 2001
12 */
13
14
15 /*
16 * agpgart driver
17 *
18 * This driver is primary targeted at providing memory support for INTEL
19 * AGP device, INTEL memory less video card, and AMD64 cpu GART devices.
20 * So there are four main architectures, ARC_IGD810, ARC_IGD830, ARC_INTELAGP,
21 * ARC_AMD64AGP to agpgart driver. However, the memory
22 * interfaces are the same for these architectures. The difference is how to
23 * manage the hardware GART table for them.
24 *
25 * For large memory allocation, this driver use direct mapping to userland
26 * application interface to save kernel virtual memory .
27 */
28
29 #include <sys/types.h>
30 #include <sys/pci.h>
31 #include <sys/systm.h>
32 #include <sys/conf.h>
33 #include <sys/file.h>
34 #include <sys/kstat.h>
35 #include <sys/stat.h>
36 #include <sys/modctl.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/sunldi.h>
40 #include <sys/policy.h>
41 #include <sys/ddidevmap.h>
42 #include <vm/seg_dev.h>
43 #include <sys/pmem.h>
44 #include <sys/agpgart.h>
45 #include <sys/agp/agpdefs.h>
46 #include <sys/agp/agpgart_impl.h>
47 #include <sys/agp/agpamd64gart_io.h>
48 #include <sys/agp/agpmaster_io.h>
49 #include <sys/agp/agptarget_io.h>
50
51 /* Dynamic debug support */
52 int agp_debug_var = 0;
53 #define AGPDB_PRINT1(fmt) if (agp_debug_var == 1) cmn_err fmt
54 #define AGPDB_PRINT2(fmt) if (agp_debug_var >= 1) cmn_err fmt
55
56 /* Driver global softstate handle */
57 static void *agpgart_glob_soft_handle;
58
59 #define MAX_INSTNUM 16
60
61 #define AGP_DEV2INST(devt) (getminor((devt)) >> 4)
62 #define AGP_INST2MINOR(instance) ((instance) << 4)
63 #define IS_INTEL_830(type) ((type) == ARC_IGD830)
64 #define IS_TRUE_AGP(type) (((type) == ARC_INTELAGP) || \
65 ((type) == ARC_AMD64AGP))
66
67 #define AGP_HASH_NODE 1024
68
69 static void
list_head_init(struct list_head * head)70 list_head_init(struct list_head *head) {
71 struct list_head *entry, *tmp;
72 /* HASH for accelerate */
73 entry = kmem_zalloc(AGP_HASH_NODE *
74 sizeof (struct list_head), KM_SLEEP);
75 head->next = entry;
76 for (int i = 0; i < AGP_HASH_NODE; i++) {
77 tmp = &entry[i];
78 tmp->next = tmp;
79 tmp->prev = tmp;
80 tmp->gttseg = NULL;
81 }
82 }
83
84 static void
list_head_add_new(struct list_head * head,igd_gtt_seg_t * gttseg)85 list_head_add_new(struct list_head *head,
86 igd_gtt_seg_t *gttseg)
87 {
88 struct list_head *entry, *tmp;
89 int key;
90 entry = kmem_zalloc(sizeof (*entry), KM_SLEEP);
91 key = gttseg->igs_pgstart % AGP_HASH_NODE;
92 tmp = &head->next[key];
93 tmp->next->prev = entry;
94 entry->next = tmp->next;
95 entry->prev = tmp;
96 tmp->next = entry;
97 entry->gttseg = gttseg;
98 }
99
100 static void
list_head_del(struct list_head * entry)101 list_head_del(struct list_head *entry) {
102 (entry)->next->prev = (entry)->prev; \
103 (entry)->prev->next = (entry)->next; \
104 (entry)->gttseg = NULL; \
105 }
106
107 #define list_head_for_each_safe(entry, temp, head) \
108 for (int key = 0; key < AGP_HASH_NODE; key++) \
109 for (entry = (&(head)->next[key])->next, temp = (entry)->next; \
110 entry != &(head)->next[key]; \
111 entry = temp, temp = temp->next)
112
113
114 #define agpinfo_default_to_32(v, v32) \
115 { \
116 (v32).agpi32_version = (v).agpi_version; \
117 (v32).agpi32_devid = (v).agpi_devid; \
118 (v32).agpi32_mode = (v).agpi_mode; \
119 (v32).agpi32_aperbase = (uint32_t)(v).agpi_aperbase; \
120 (v32).agpi32_apersize = (uint32_t)(v).agpi_apersize; \
121 (v32).agpi32_pgtotal = (v).agpi_pgtotal; \
122 (v32).agpi32_pgsystem = (v).agpi_pgsystem; \
123 (v32).agpi32_pgused = (v).agpi_pgused; \
124 }
125
126 static ddi_dma_attr_t agpgart_dma_attr = {
127 DMA_ATTR_V0,
128 0U, /* dma_attr_addr_lo */
129 0xffffffffU, /* dma_attr_addr_hi */
130 0xffffffffU, /* dma_attr_count_max */
131 (uint64_t)AGP_PAGE_SIZE, /* dma_attr_align */
132 1, /* dma_attr_burstsizes */
133 1, /* dma_attr_minxfer */
134 0xffffffffU, /* dma_attr_maxxfer */
135 0xffffffffU, /* dma_attr_seg */
136 1, /* dma_attr_sgllen, variable */
137 4, /* dma_attr_granular */
138 0 /* dma_attr_flags */
139 };
140
141 /*
142 * AMD64 supports gart table above 4G. See alloc_gart_table.
143 */
144 static ddi_dma_attr_t garttable_dma_attr = {
145 DMA_ATTR_V0,
146 0U, /* dma_attr_addr_lo */
147 0xffffffffU, /* dma_attr_addr_hi */
148 0xffffffffU, /* dma_attr_count_max */
149 (uint64_t)AGP_PAGE_SIZE, /* dma_attr_align */
150 1, /* dma_attr_burstsizes */
151 1, /* dma_attr_minxfer */
152 0xffffffffU, /* dma_attr_maxxfer */
153 0xffffffffU, /* dma_attr_seg */
154 1, /* dma_attr_sgllen, variable */
155 4, /* dma_attr_granular */
156 0 /* dma_attr_flags */
157 };
158
159 /*
160 * AGPGART table need a physical contiguous memory. To assure that
161 * each access to gart table is strongly ordered and uncachable,
162 * we use DDI_STRICTORDER_ACC.
163 */
164 static ddi_device_acc_attr_t gart_dev_acc_attr = {
165 DDI_DEVICE_ATTR_V0,
166 DDI_NEVERSWAP_ACC,
167 DDI_STRICTORDER_ACC /* must be DDI_STRICTORDER_ACC */
168 };
169
170 /*
171 * AGP memory is usually used as texture memory or for a framebuffer, so we
172 * can set the memory attribute to write combining. Video drivers will
173 * determine the frame buffer attributes, for example the memory is write
174 * combinging or non-cachable. However, the interface between Xorg and agpgart
175 * driver to support attribute selcetion doesn't exist yet. So we set agp memory
176 * to non-cachable by default now. This attribute might be overridden
177 * by MTTR in X86.
178 */
179 static ddi_device_acc_attr_t mem_dev_acc_attr = {
180 DDI_DEVICE_ATTR_V0,
181 DDI_NEVERSWAP_ACC,
182 DDI_STRICTORDER_ACC /* Can be DDI_MERGING_OK_ACC */
183 };
184
185 static keytable_ent_t *
186 agp_find_bound_keyent(agpgart_softstate_t *softstate, uint32_t pg_offset);
187 static void
188 amd64_gart_unregister(amd64_garts_dev_t *cpu_garts);
189
190
191 static void
agp_devmap_unmap(devmap_cookie_t handle,void * devprivate,offset_t off,size_t len,devmap_cookie_t new_handle1,void ** new_devprivate1,devmap_cookie_t new_handle2,void ** new_devprivate2)192 agp_devmap_unmap(devmap_cookie_t handle, void *devprivate,
193 offset_t off, size_t len, devmap_cookie_t new_handle1,
194 void **new_devprivate1, devmap_cookie_t new_handle2,
195 void **new_devprivate2)
196 {
197
198 struct keytable_ent *mementry;
199 agpgart_softstate_t *softstate;
200 agpgart_ctx_t *ctxp, *newctxp1, *newctxp2;
201
202 ASSERT(AGP_ALIGNED(len) && AGP_ALIGNED(off));
203 ASSERT(devprivate);
204 ASSERT(handle);
205
206 ctxp = (agpgart_ctx_t *)devprivate;
207 softstate = ctxp->actx_sc;
208 ASSERT(softstate);
209
210 if (new_handle1 != NULL) {
211 newctxp1 = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
212 newctxp1->actx_sc = softstate;
213 newctxp1->actx_off = ctxp->actx_off;
214 *new_devprivate1 = newctxp1;
215 }
216
217 if (new_handle2 != NULL) {
218 newctxp2 = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
219 newctxp2->actx_sc = softstate;
220 newctxp2->actx_off = off + len;
221 *new_devprivate2 = newctxp2;
222 }
223
224 mutex_enter(&softstate->asoft_instmutex);
225 if ((new_handle1 == NULL) && (new_handle2 == NULL)) {
226 mementry =
227 agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(off));
228 ASSERT(mementry);
229 mementry->kte_refcnt--;
230 } else if ((new_handle1 != NULL) && (new_handle2 != NULL)) {
231 mementry =
232 agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(off));
233 ASSERT(mementry);
234 mementry->kte_refcnt++;
235 }
236 ASSERT(mementry->kte_refcnt >= 0);
237 mutex_exit(&softstate->asoft_instmutex);
238 kmem_free(ctxp, sizeof (struct agpgart_ctx));
239 }
240
241 /*ARGSUSED*/
242 static int
agp_devmap_map(devmap_cookie_t handle,dev_t dev,uint_t flags,offset_t offset,size_t len,void ** new_devprivate)243 agp_devmap_map(devmap_cookie_t handle, dev_t dev,
244 uint_t flags, offset_t offset, size_t len, void **new_devprivate)
245 {
246 agpgart_softstate_t *softstate;
247 int instance;
248 struct keytable_ent *mementry;
249 agpgart_ctx_t *newctxp;
250
251 ASSERT(handle);
252 instance = AGP_DEV2INST(dev);
253 softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
254 if (softstate == NULL) {
255 AGPDB_PRINT2((CE_WARN, "agp_devmap_map: get soft state err"));
256 return (ENXIO);
257 }
258
259 ASSERT(softstate);
260 ASSERT(mutex_owned(&softstate->asoft_instmutex));
261 ASSERT(len);
262 ASSERT(AGP_ALIGNED(offset) && AGP_ALIGNED(len));
263
264 mementry =
265 agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(offset));
266 ASSERT(mementry);
267 mementry->kte_refcnt++;
268 ASSERT(mementry->kte_refcnt >= 0);
269 newctxp = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
270 newctxp->actx_off = offset;
271 newctxp->actx_sc = softstate;
272 *new_devprivate = newctxp;
273
274 return (0);
275 }
276
277 /*ARGSUSED*/
agp_devmap_dup(devmap_cookie_t handle,void * devprivate,devmap_cookie_t new_handle,void ** new_devprivate)278 static int agp_devmap_dup(devmap_cookie_t handle, void *devprivate,
279 devmap_cookie_t new_handle, void **new_devprivate)
280 {
281 struct keytable_ent *mementry;
282 agpgart_ctx_t *newctxp, *ctxp;
283 agpgart_softstate_t *softstate;
284
285 ASSERT(devprivate);
286 ASSERT(handle && new_handle);
287
288 ctxp = (agpgart_ctx_t *)devprivate;
289 ASSERT(AGP_ALIGNED(ctxp->actx_off));
290
291 newctxp = kmem_zalloc(sizeof (agpgart_ctx_t), KM_SLEEP);
292 newctxp->actx_off = ctxp->actx_off;
293 newctxp->actx_sc = ctxp->actx_sc;
294 softstate = (agpgart_softstate_t *)newctxp->actx_sc;
295
296 mutex_enter(&softstate->asoft_instmutex);
297 mementry = agp_find_bound_keyent(softstate,
298 AGP_BYTES2PAGES(newctxp->actx_off));
299 mementry->kte_refcnt++;
300 ASSERT(mementry->kte_refcnt >= 0);
301 mutex_exit(&softstate->asoft_instmutex);
302 *new_devprivate = newctxp;
303
304 return (0);
305 }
306
307 struct devmap_callback_ctl agp_devmap_cb = {
308 DEVMAP_OPS_REV, /* rev */
309 agp_devmap_map, /* map */
310 NULL, /* access */
311 agp_devmap_dup, /* dup */
312 agp_devmap_unmap, /* unmap */
313 };
314
315 /*
316 * agp_master_regis_byname()
317 *
318 * Description:
319 * Open the AGP master device node by device path name and
320 * register the device handle for later operations.
321 * We check all possible driver instance from 0
322 * to MAX_INSTNUM because the master device could be
323 * at any instance number. Only one AGP master is supported.
324 *
325 * Arguments:
326 * master_hdlp AGP master device LDI handle pointer
327 * agpgart_l AGPGART driver LDI identifier
328 *
329 * Returns:
330 * -1 failed
331 * 0 success
332 */
333 static int
agp_master_regis_byname(ldi_handle_t * master_hdlp,ldi_ident_t agpgart_li)334 agp_master_regis_byname(ldi_handle_t *master_hdlp, ldi_ident_t agpgart_li)
335 {
336 int i;
337 char buf[MAXPATHLEN];
338
339 ASSERT(master_hdlp);
340 ASSERT(agpgart_li);
341
342 /*
343 * Search all possible instance numbers for the agp master device.
344 * Only one master device is supported now, so the search ends
345 * when one master device is found.
346 */
347 for (i = 0; i < MAX_INSTNUM; i++) {
348 (void) snprintf(buf, MAXPATHLEN, "%s%d", AGPMASTER_DEVLINK, i);
349 if ((ldi_open_by_name(buf, 0, kcred,
350 master_hdlp, agpgart_li)))
351 continue;
352 AGPDB_PRINT1((CE_NOTE,
353 "master device found: instance number=%d", i));
354 break;
355
356 }
357
358 /* AGP master device not found */
359 if (i == MAX_INSTNUM)
360 return (-1);
361
362 return (0);
363 }
364
365 /*
366 * agp_target_regis_byname()
367 *
368 * Description:
369 * This function opens agp bridge device node by
370 * device path name and registers the device handle
371 * for later operations.
372 * We check driver instance from 0 to MAX_INSTNUM
373 * because the master device could be at any instance
374 * number. Only one agp target is supported.
375 *
376 *
377 * Arguments:
378 * target_hdlp AGP target device LDI handle pointer
379 * agpgart_l AGPGART driver LDI identifier
380 *
381 * Returns:
382 * -1 failed
383 * 0 success
384 */
385 static int
agp_target_regis_byname(ldi_handle_t * target_hdlp,ldi_ident_t agpgart_li)386 agp_target_regis_byname(ldi_handle_t *target_hdlp, ldi_ident_t agpgart_li)
387 {
388 int i;
389 char buf[MAXPATHLEN];
390
391 ASSERT(target_hdlp);
392 ASSERT(agpgart_li);
393
394 for (i = 0; i < MAX_INSTNUM; i++) {
395 (void) snprintf(buf, MAXPATHLEN, "%s%d", AGPTARGET_DEVLINK, i);
396 if ((ldi_open_by_name(buf, 0, kcred,
397 target_hdlp, agpgart_li)))
398 continue;
399
400 AGPDB_PRINT1((CE_NOTE,
401 "bridge device found: instance number=%d", i));
402 break;
403
404 }
405
406 /* AGP bridge device not found */
407 if (i == MAX_INSTNUM) {
408 AGPDB_PRINT2((CE_WARN, "bridge device not found"));
409 return (-1);
410 }
411
412 return (0);
413 }
414
415 /*
416 * amd64_gart_regis_byname()
417 *
418 * Description:
419 * Open all amd64 gart device nodes by deice path name and
420 * register the device handles for later operations. Each cpu
421 * has its own amd64 gart device.
422 *
423 * Arguments:
424 * cpu_garts cpu garts device list header
425 * agpgart_l AGPGART driver LDI identifier
426 *
427 * Returns:
428 * -1 failed
429 * 0 success
430 */
431 static int
amd64_gart_regis_byname(amd64_garts_dev_t * cpu_garts,ldi_ident_t agpgart_li)432 amd64_gart_regis_byname(amd64_garts_dev_t *cpu_garts, ldi_ident_t agpgart_li)
433 {
434 amd64_gart_dev_list_t *gart_list;
435 int i;
436 char buf[MAXPATHLEN];
437 ldi_handle_t gart_hdl;
438 int ret;
439
440 ASSERT(cpu_garts);
441 ASSERT(agpgart_li);
442
443 /*
444 * Search all possible instance numbers for the gart devices.
445 * There can be multiple on-cpu gart devices for Opteron server.
446 */
447 for (i = 0; i < MAX_INSTNUM; i++) {
448 (void) snprintf(buf, MAXPATHLEN, "%s%d", CPUGART_DEVLINK, i);
449 ret = ldi_open_by_name(buf, 0, kcred,
450 &gart_hdl, agpgart_li);
451
452 if (ret == ENODEV)
453 continue;
454 else if (ret != 0) { /* There was an error opening the device */
455 amd64_gart_unregister(cpu_garts);
456 return (ret);
457 }
458
459 AGPDB_PRINT1((CE_NOTE,
460 "amd64 gart device found: instance number=%d", i));
461
462 gart_list = (amd64_gart_dev_list_t *)
463 kmem_zalloc(sizeof (amd64_gart_dev_list_t), KM_SLEEP);
464
465 /* Add new item to the head of the gart device list */
466 gart_list->gart_devhdl = gart_hdl;
467 gart_list->next = cpu_garts->gart_dev_list_head;
468 cpu_garts->gart_dev_list_head = gart_list;
469 cpu_garts->gart_device_num++;
470 }
471
472 if (cpu_garts->gart_device_num == 0)
473 return (ENODEV);
474 return (0);
475 }
476
477 /*
478 * Unregister agp master device handle
479 */
480 static void
agp_master_unregister(ldi_handle_t * master_hdlp)481 agp_master_unregister(ldi_handle_t *master_hdlp)
482 {
483 ASSERT(master_hdlp);
484
485 if (master_hdlp) {
486 (void) ldi_close(*master_hdlp, 0, kcred);
487 *master_hdlp = NULL;
488 }
489 }
490
491 /*
492 * Unregister agp bridge device handle
493 */
494 static void
agp_target_unregister(ldi_handle_t * target_hdlp)495 agp_target_unregister(ldi_handle_t *target_hdlp)
496 {
497 if (target_hdlp) {
498 (void) ldi_close(*target_hdlp, 0, kcred);
499 *target_hdlp = NULL;
500 }
501 }
502
503 /*
504 * Unregister all amd64 gart device handles
505 */
506 static void
amd64_gart_unregister(amd64_garts_dev_t * cpu_garts)507 amd64_gart_unregister(amd64_garts_dev_t *cpu_garts)
508 {
509 amd64_gart_dev_list_t *gart_list;
510 amd64_gart_dev_list_t *next;
511
512 ASSERT(cpu_garts);
513
514 for (gart_list = cpu_garts->gart_dev_list_head;
515 gart_list; gart_list = next) {
516
517 ASSERT(gart_list->gart_devhdl);
518 (void) ldi_close(gart_list->gart_devhdl, 0, kcred);
519 next = gart_list->next;
520 /* Free allocated memory */
521 kmem_free(gart_list, sizeof (amd64_gart_dev_list_t));
522 }
523 cpu_garts->gart_dev_list_head = NULL;
524 cpu_garts->gart_device_num = 0;
525 }
526
527 /*
528 * lyr_detect_master_type()
529 *
530 * Description:
531 * This function gets agp master type by querying agp master device.
532 *
533 * Arguments:
534 * master_hdlp agp master device ldi handle pointer
535 *
536 * Returns:
537 * -1 unsupported device
538 * DEVICE_IS_I810 i810 series
539 * DEVICE_IS_I810 i830 series
540 * DEVICE_IS_AGP true agp master
541 */
542 static int
lyr_detect_master_type(ldi_handle_t * master_hdlp)543 lyr_detect_master_type(ldi_handle_t *master_hdlp)
544 {
545 int vtype;
546 int err;
547
548 ASSERT(master_hdlp);
549
550 /* ldi_ioctl(agpmaster) */
551 err = ldi_ioctl(*master_hdlp, DEVICE_DETECT,
552 (intptr_t)&vtype, FKIOCTL, kcred, 0);
553 if (err) /* Unsupported graphics device */
554 return (-1);
555 return (vtype);
556 }
557
558 /*
559 * devtect_target_type()
560 *
561 * Description:
562 * This function gets the host bridge chipset type by querying the agp
563 * target device.
564 *
565 * Arguments:
566 * target_hdlp agp target device LDI handle pointer
567 *
568 * Returns:
569 * CHIP_IS_INTEL Intel agp chipsets
570 * CHIP_IS_AMD AMD agp chipset
571 * -1 unsupported chipset
572 */
573 static int
lyr_detect_target_type(ldi_handle_t * target_hdlp)574 lyr_detect_target_type(ldi_handle_t *target_hdlp)
575 {
576 int btype;
577 int err;
578
579 ASSERT(target_hdlp);
580
581 err = ldi_ioctl(*target_hdlp, CHIP_DETECT, (intptr_t)&btype,
582 FKIOCTL, kcred, 0);
583 if (err) /* Unsupported bridge device */
584 return (-1);
585 return (btype);
586 }
587
588 /*
589 * lyr_init()
590 *
591 * Description:
592 * This function detects the graphics system architecture and
593 * registers all relative device handles in a global structure
594 * "agp_regdev". Then it stores the system arc type in driver
595 * soft state.
596 *
597 * Arguments:
598 * agp_regdev AGP devices registration struct pointer
599 * agpgart_l AGPGART driver LDI identifier
600 *
601 * Returns:
602 * 0 System arc supported and agp devices registration successed.
603 * -1 System arc not supported or device registration failed.
604 */
605 int
lyr_init(agp_registered_dev_t * agp_regdev,ldi_ident_t agpgart_li)606 lyr_init(agp_registered_dev_t *agp_regdev, ldi_ident_t agpgart_li)
607 {
608 ldi_handle_t *master_hdlp;
609 ldi_handle_t *target_hdlp;
610 amd64_garts_dev_t *garts_dev;
611 int card_type, chip_type;
612 int ret;
613
614 ASSERT(agp_regdev);
615
616 bzero(agp_regdev, sizeof (agp_registered_dev_t));
617 agp_regdev->agprd_arctype = ARC_UNKNOWN;
618 /*
619 * Register agp devices, assuming all instances attached, and
620 * detect which agp architucture this server belongs to. This
621 * must be done before the agpgart driver starts to use layered
622 * driver interfaces.
623 */
624 master_hdlp = &agp_regdev->agprd_masterhdl;
625 target_hdlp = &agp_regdev->agprd_targethdl;
626 garts_dev = &agp_regdev->agprd_cpugarts;
627
628 /* Check whether the system is amd64 arc */
629 if ((ret = amd64_gart_regis_byname(garts_dev, agpgart_li)) == ENODEV) {
630 /* No amd64 gart devices */
631 AGPDB_PRINT1((CE_NOTE,
632 "lyr_init: this is not an amd64 system"));
633 if (agp_master_regis_byname(master_hdlp, agpgart_li)) {
634 AGPDB_PRINT2((CE_WARN,
635 "lyr_init: register master device unsuccessful"));
636 goto err1;
637 }
638 if (agp_target_regis_byname(target_hdlp, agpgart_li)) {
639 AGPDB_PRINT2((CE_WARN,
640 "lyr_init: register target device unsuccessful"));
641 goto err2;
642 }
643 card_type = lyr_detect_master_type(master_hdlp);
644 /*
645 * Detect system arc by master device. If it is a intel
646 * integrated device, finish the detection successfully.
647 */
648 switch (card_type) {
649 case DEVICE_IS_I810: /* I810 likewise graphics */
650 AGPDB_PRINT1((CE_NOTE,
651 "lyr_init: the system is Intel 810 arch"));
652 agp_regdev->agprd_arctype = ARC_IGD810;
653 return (0);
654 case DEVICE_IS_I830: /* I830 likewise graphics */
655 AGPDB_PRINT1((CE_NOTE,
656 "lyr_init: the system is Intel 830 arch"));
657 agp_regdev->agprd_arctype = ARC_IGD830;
658 return (0);
659 case DEVICE_IS_AGP: /* AGP graphics */
660 break;
661 default: /* Non IGD/AGP graphics */
662 AGPDB_PRINT2((CE_WARN,
663 "lyr_init: non-supported master device"));
664 goto err3;
665 }
666
667 chip_type = lyr_detect_target_type(target_hdlp);
668
669 /* Continue to detect AGP arc by target device */
670 switch (chip_type) {
671 case CHIP_IS_INTEL: /* Intel chipset */
672 AGPDB_PRINT1((CE_NOTE,
673 "lyr_init: Intel AGP arch detected"));
674 agp_regdev->agprd_arctype = ARC_INTELAGP;
675 return (0);
676 case CHIP_IS_AMD: /* AMD chipset */
677 AGPDB_PRINT2((CE_WARN,
678 "lyr_init: no cpu gart, but have AMD64 chipsets"));
679 goto err3;
680 default: /* Non supported chipset */
681 AGPDB_PRINT2((CE_WARN,
682 "lyr_init: detection can not continue"));
683 goto err3;
684 }
685
686 }
687
688 if (ret)
689 return (-1); /* Errors in open amd64 cpu gart devices */
690
691 /*
692 * AMD64 cpu gart device exsits, continue detection
693 */
694 if (agp_master_regis_byname(master_hdlp, agpgart_li)) {
695 AGPDB_PRINT1((CE_NOTE, "lyr_init: no AGP master in amd64"));
696 goto err1;
697 }
698
699 if (agp_target_regis_byname(target_hdlp, agpgart_li)) {
700 AGPDB_PRINT1((CE_NOTE,
701 "lyr_init: no AGP bridge"));
702 goto err2;
703 }
704
705 AGPDB_PRINT1((CE_NOTE,
706 "lyr_init: the system is AMD64 AGP architecture"));
707
708 agp_regdev->agprd_arctype = ARC_AMD64AGP;
709
710 return (0); /* Finished successfully */
711
712 err3:
713 agp_target_unregister(&agp_regdev->agprd_targethdl);
714 err2:
715 agp_master_unregister(&agp_regdev->agprd_masterhdl);
716 err1:
717 /* AMD64 CPU gart registered ? */
718 if (ret == 0) {
719 amd64_gart_unregister(garts_dev);
720 }
721 agp_regdev->agprd_arctype = ARC_UNKNOWN;
722 return (-1);
723 }
724
725 void
lyr_end(agp_registered_dev_t * agp_regdev)726 lyr_end(agp_registered_dev_t *agp_regdev)
727 {
728 ASSERT(agp_regdev);
729
730 switch (agp_regdev->agprd_arctype) {
731 case ARC_IGD810:
732 case ARC_IGD830:
733 case ARC_INTELAGP:
734 agp_master_unregister(&agp_regdev->agprd_masterhdl);
735 agp_target_unregister(&agp_regdev->agprd_targethdl);
736
737 return;
738 case ARC_AMD64AGP:
739 agp_master_unregister(&agp_regdev->agprd_masterhdl);
740 agp_target_unregister(&agp_regdev->agprd_targethdl);
741 amd64_gart_unregister(&agp_regdev->agprd_cpugarts);
742
743 return;
744 default:
745 ASSERT(0);
746 return;
747 }
748 }
749
750 int
lyr_get_info(agp_kern_info_t * info,agp_registered_dev_t * agp_regdev)751 lyr_get_info(agp_kern_info_t *info, agp_registered_dev_t *agp_regdev)
752 {
753 ldi_handle_t hdl;
754 igd_info_t value1;
755 i_agp_info_t value2;
756 size_t prealloc_size;
757 int err;
758
759 ASSERT(info);
760 ASSERT(agp_regdev);
761
762 switch (agp_regdev->agprd_arctype) {
763 case ARC_IGD810:
764 hdl = agp_regdev->agprd_masterhdl;
765 err = ldi_ioctl(hdl, I8XX_GET_INFO, (intptr_t)&value1,
766 FKIOCTL, kcred, 0);
767 if (err)
768 return (-1);
769 info->agpki_mdevid = value1.igd_devid;
770 info->agpki_aperbase = value1.igd_aperbase;
771 info->agpki_apersize = (uint32_t)value1.igd_apersize;
772
773 hdl = agp_regdev->agprd_targethdl;
774 err = ldi_ioctl(hdl, I8XX_GET_PREALLOC_SIZE,
775 (intptr_t)&prealloc_size, FKIOCTL, kcred, 0);
776 if (err)
777 return (-1);
778 info->agpki_presize = prealloc_size;
779
780 break;
781
782 case ARC_IGD830:
783 hdl = agp_regdev->agprd_masterhdl;
784 err = ldi_ioctl(hdl, I8XX_GET_INFO, (intptr_t)&value1,
785 FKIOCTL, kcred, 0);
786 if (err)
787 return (-1);
788 info->agpki_mdevid = value1.igd_devid;
789 info->agpki_aperbase = value1.igd_aperbase;
790 info->agpki_apersize = (uint32_t)value1.igd_apersize;
791
792 hdl = agp_regdev->agprd_targethdl;
793 err = ldi_ioctl(hdl, I8XX_GET_PREALLOC_SIZE,
794 (intptr_t)&prealloc_size, FKIOCTL, kcred, 0);
795 if (err)
796 return (-1);
797
798 /*
799 * Assume all units are kilobytes unless explicitly
800 * stated below:
801 * preallocated GTT memory = preallocated memory - GTT size
802 * - scratch page size
803 *
804 * scratch page size = 4
805 * GTT size (KB) = aperture size (MB)
806 * this algorithm came from Xorg source code
807 */
808 if (prealloc_size > (info->agpki_apersize + 4))
809 prealloc_size =
810 prealloc_size - info->agpki_apersize - 4;
811 else {
812 AGPDB_PRINT2((CE_WARN, "lyr_get_info: "
813 "pre-allocated memory too small, setting to zero"));
814 prealloc_size = 0;
815 }
816 info->agpki_presize = prealloc_size;
817 AGPDB_PRINT2((CE_NOTE,
818 "lyr_get_info: prealloc_size = %ldKB, apersize = %dMB",
819 prealloc_size, info->agpki_apersize));
820 break;
821 case ARC_INTELAGP:
822 case ARC_AMD64AGP:
823 /* AGP devices */
824 hdl = agp_regdev->agprd_masterhdl;
825 err = ldi_ioctl(hdl, AGP_MASTER_GETINFO,
826 (intptr_t)&value2, FKIOCTL, kcred, 0);
827 if (err)
828 return (-1);
829 info->agpki_mdevid = value2.iagp_devid;
830 info->agpki_mver = value2.iagp_ver;
831 info->agpki_mstatus = value2.iagp_mode;
832 hdl = agp_regdev->agprd_targethdl;
833 err = ldi_ioctl(hdl, AGP_TARGET_GETINFO,
834 (intptr_t)&value2, FKIOCTL, kcred, 0);
835 if (err)
836 return (-1);
837 info->agpki_tdevid = value2.iagp_devid;
838 info->agpki_tver = value2.iagp_ver;
839 info->agpki_tstatus = value2.iagp_mode;
840 info->agpki_aperbase = value2.iagp_aperbase;
841 info->agpki_apersize = (uint32_t)value2.iagp_apersize;
842 break;
843 default:
844 AGPDB_PRINT2((CE_WARN,
845 "lyr_get_info: function doesn't work for unknown arc"));
846 return (-1);
847 }
848 if ((info->agpki_apersize >= MAXAPERMEGAS) ||
849 (info->agpki_apersize == 0) ||
850 (info->agpki_aperbase == 0)) {
851 AGPDB_PRINT2((CE_WARN,
852 "lyr_get_info: aperture is not programmed correctly!"));
853 return (-1);
854 }
855
856 return (0);
857 }
858
859 /*
860 * lyr_i8xx_add_to_gtt()
861 *
862 * Description:
863 * This function sets up the integrated video device gtt table
864 * via an ioclt to the AGP master driver.
865 *
866 * Arguments:
867 * pg_offset The start entry to be setup
868 * keyent Keytable entity pointer
869 * agp_regdev AGP devices registration struct pointer
870 *
871 * Returns:
872 * 0 success
873 * -1 invalid operations
874 */
875 int
lyr_i8xx_add_to_gtt(uint32_t pg_offset,keytable_ent_t * keyent,agp_registered_dev_t * agp_regdev)876 lyr_i8xx_add_to_gtt(uint32_t pg_offset, keytable_ent_t *keyent,
877 agp_registered_dev_t *agp_regdev)
878 {
879 int err = 0;
880 int rval;
881 ldi_handle_t hdl;
882 igd_gtt_seg_t gttseg;
883 uint32_t *addrp, i;
884 uint32_t npages;
885
886 ASSERT(keyent);
887 ASSERT(agp_regdev);
888 gttseg.igs_pgstart = pg_offset;
889 npages = keyent->kte_pages;
890 gttseg.igs_npage = npages;
891 gttseg.igs_type = keyent->kte_type;
892 gttseg.igs_phyaddr = (uint32_t *)kmem_zalloc
893 (sizeof (uint32_t) * gttseg.igs_npage, KM_SLEEP);
894
895 addrp = gttseg.igs_phyaddr;
896 for (i = 0; i < npages; i++, addrp++) {
897 *addrp =
898 (uint32_t)((keyent->kte_pfnarray[i]) << GTT_PAGE_SHIFT);
899 }
900
901 hdl = agp_regdev->agprd_masterhdl;
902 if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)>tseg, FKIOCTL,
903 kcred, &rval)) {
904 AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: ldi_ioctl error"));
905 AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: pg_start=0x%x",
906 gttseg.igs_pgstart));
907 AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: pages=0x%x",
908 gttseg.igs_npage));
909 AGPDB_PRINT2((CE_WARN, "lyr_i8xx_add_to_gtt: type=0x%x",
910 gttseg.igs_type));
911 err = -1;
912 }
913 kmem_free(gttseg.igs_phyaddr, sizeof (uint32_t) * gttseg.igs_npage);
914 return (err);
915 }
916
917 /*
918 * lyr_i8xx_remove_from_gtt()
919 *
920 * Description:
921 * This function clears the integrated video device gtt table via
922 * an ioctl to the agp master device.
923 *
924 * Arguments:
925 * pg_offset The starting entry to be cleared
926 * npage The number of entries to be cleared
927 * agp_regdev AGP devices struct pointer
928 *
929 * Returns:
930 * 0 success
931 * -1 invalid operations
932 */
933 int
lyr_i8xx_remove_from_gtt(uint32_t pg_offset,uint32_t npage,agp_registered_dev_t * agp_regdev)934 lyr_i8xx_remove_from_gtt(uint32_t pg_offset, uint32_t npage,
935 agp_registered_dev_t *agp_regdev)
936 {
937 int rval;
938 ldi_handle_t hdl;
939 igd_gtt_seg_t gttseg;
940
941 gttseg.igs_pgstart = pg_offset;
942 gttseg.igs_npage = npage;
943
944 hdl = agp_regdev->agprd_masterhdl;
945 if (ldi_ioctl(hdl, I8XX_REM_GTT, (intptr_t)>tseg, FKIOCTL,
946 kcred, &rval))
947 return (-1);
948
949 return (0);
950 }
951
952 /*
953 * lyr_set_gart_addr()
954 *
955 * Description:
956 * This function puts the gart table physical address in the
957 * gart base register.
958 * Please refer to gart and gtt table base register format for
959 * gart base register format in agpdefs.h.
960 *
961 * Arguments:
962 * phy_base The base physical address of gart table
963 * agp_regdev AGP devices registration struct pointer
964 *
965 * Returns:
966 * 0 success
967 * -1 failed
968 *
969 */
970
971 int
lyr_set_gart_addr(uint64_t phy_base,agp_registered_dev_t * agp_regdev)972 lyr_set_gart_addr(uint64_t phy_base, agp_registered_dev_t *agp_regdev)
973 {
974 amd64_gart_dev_list_t *gart_list;
975 ldi_handle_t hdl;
976 int err = 0;
977
978 ASSERT(agp_regdev);
979 switch (agp_regdev->agprd_arctype) {
980 case ARC_IGD810:
981 {
982 uint32_t base;
983
984 ASSERT((phy_base & I810_POINTER_MASK) == 0);
985 base = (uint32_t)phy_base;
986
987 hdl = agp_regdev->agprd_masterhdl;
988 err = ldi_ioctl(hdl, I810_SET_GTT_BASE,
989 (intptr_t)&base, FKIOCTL, kcred, 0);
990 break;
991 }
992 case ARC_INTELAGP:
993 {
994 uint32_t addr;
995 addr = (uint32_t)phy_base;
996
997 ASSERT((phy_base & GTT_POINTER_MASK) == 0);
998 hdl = agp_regdev->agprd_targethdl;
999 err = ldi_ioctl(hdl, AGP_TARGET_SET_GATTADDR,
1000 (intptr_t)&addr, FKIOCTL, kcred, 0);
1001 break;
1002 }
1003 case ARC_AMD64AGP:
1004 {
1005 uint32_t addr;
1006
1007 ASSERT((phy_base & AMD64_POINTER_MASK) == 0);
1008 addr = (uint32_t)((phy_base >> AMD64_GARTBASE_SHIFT)
1009 & AMD64_GARTBASE_MASK);
1010
1011 for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
1012 gart_list;
1013 gart_list = gart_list->next) {
1014 hdl = gart_list->gart_devhdl;
1015 if (ldi_ioctl(hdl, AMD64_SET_GART_ADDR,
1016 (intptr_t)&addr, FKIOCTL, kcred, 0)) {
1017 err = -1;
1018 break;
1019 }
1020 }
1021 break;
1022 }
1023 default:
1024 err = -1;
1025 }
1026
1027 if (err)
1028 return (-1);
1029
1030 return (0);
1031 }
1032
1033 int
lyr_set_agp_cmd(uint32_t cmd,agp_registered_dev_t * agp_regdev)1034 lyr_set_agp_cmd(uint32_t cmd, agp_registered_dev_t *agp_regdev)
1035 {
1036 ldi_handle_t hdl;
1037 uint32_t command;
1038
1039 ASSERT(agp_regdev);
1040 command = cmd;
1041 hdl = agp_regdev->agprd_targethdl;
1042 if (ldi_ioctl(hdl, AGP_TARGET_SETCMD,
1043 (intptr_t)&command, FKIOCTL, kcred, 0))
1044 return (-1);
1045 hdl = agp_regdev->agprd_masterhdl;
1046 if (ldi_ioctl(hdl, AGP_MASTER_SETCMD,
1047 (intptr_t)&command, FKIOCTL, kcred, 0))
1048 return (-1);
1049
1050 return (0);
1051 }
1052
1053 int
lyr_config_devices(agp_registered_dev_t * agp_regdev)1054 lyr_config_devices(agp_registered_dev_t *agp_regdev)
1055 {
1056 amd64_gart_dev_list_t *gart_list;
1057 ldi_handle_t hdl;
1058 int rc = 0;
1059
1060 ASSERT(agp_regdev);
1061 switch (agp_regdev->agprd_arctype) {
1062 case ARC_IGD830:
1063 case ARC_IGD810:
1064 break;
1065 case ARC_INTELAGP:
1066 {
1067 hdl = agp_regdev->agprd_targethdl;
1068 rc = ldi_ioctl(hdl, AGP_TARGET_CONFIGURE,
1069 0, FKIOCTL, kcred, 0);
1070 break;
1071 }
1072 case ARC_AMD64AGP:
1073 {
1074 /*
1075 * BIOS always shadow registers such like Aperture Base
1076 * register, Aperture Size Register from the AGP bridge
1077 * to the AMD64 CPU host bridge. If future BIOSes are broken
1078 * in this regard, we may need to shadow these registers
1079 * in driver.
1080 */
1081
1082 for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
1083 gart_list;
1084 gart_list = gart_list->next) {
1085 hdl = gart_list->gart_devhdl;
1086 if (ldi_ioctl(hdl, AMD64_CONFIGURE,
1087 0, FKIOCTL, kcred, 0)) {
1088 rc = -1;
1089 break;
1090 }
1091 }
1092 break;
1093 }
1094 default:
1095 rc = -1;
1096 }
1097
1098 if (rc)
1099 return (-1);
1100
1101 return (0);
1102 }
1103
1104 int
lyr_unconfig_devices(agp_registered_dev_t * agp_regdev)1105 lyr_unconfig_devices(agp_registered_dev_t *agp_regdev)
1106 {
1107 amd64_gart_dev_list_t *gart_list;
1108 ldi_handle_t hdl;
1109 int rc = 0;
1110
1111 ASSERT(agp_regdev);
1112 switch (agp_regdev->agprd_arctype) {
1113 case ARC_IGD830:
1114 case ARC_IGD810:
1115 {
1116 hdl = agp_regdev->agprd_masterhdl;
1117 rc = ldi_ioctl(hdl, I8XX_UNCONFIG, 0, FKIOCTL, kcred, 0);
1118 break;
1119 }
1120 case ARC_INTELAGP:
1121 {
1122 hdl = agp_regdev->agprd_targethdl;
1123 rc = ldi_ioctl(hdl, AGP_TARGET_UNCONFIG,
1124 0, FKIOCTL, kcred, 0);
1125 break;
1126 }
1127 case ARC_AMD64AGP:
1128 {
1129 for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
1130 gart_list; gart_list = gart_list->next) {
1131 hdl = gart_list->gart_devhdl;
1132 if (ldi_ioctl(hdl, AMD64_UNCONFIG,
1133 0, FKIOCTL, kcred, 0)) {
1134 rc = -1;
1135 break;
1136 }
1137 }
1138 break;
1139 }
1140 default:
1141 rc = -1;
1142 }
1143
1144 if (rc)
1145 return (-1);
1146
1147 return (0);
1148 }
1149
1150 /*
1151 * lyr_flush_gart_cache()
1152 *
1153 * Description:
1154 * This function flushes the GART translation look-aside buffer. All
1155 * GART translation caches will be flushed after this operation.
1156 *
1157 * Arguments:
1158 * agp_regdev AGP devices struct pointer
1159 */
1160 void
lyr_flush_gart_cache(agp_registered_dev_t * agp_regdev)1161 lyr_flush_gart_cache(agp_registered_dev_t *agp_regdev)
1162 {
1163 amd64_gart_dev_list_t *gart_list;
1164 ldi_handle_t hdl;
1165
1166 ASSERT(agp_regdev);
1167 if (agp_regdev->agprd_arctype == ARC_AMD64AGP) {
1168 for (gart_list = agp_regdev->agprd_cpugarts.gart_dev_list_head;
1169 gart_list; gart_list = gart_list->next) {
1170 hdl = gart_list->gart_devhdl;
1171 (void) ldi_ioctl(hdl, AMD64_FLUSH_GTLB,
1172 0, FKIOCTL, kcred, 0);
1173 }
1174 } else if (agp_regdev->agprd_arctype == ARC_INTELAGP) {
1175 hdl = agp_regdev->agprd_targethdl;
1176 (void) ldi_ioctl(hdl, AGP_TARGET_FLUSH_GTLB, 0,
1177 FKIOCTL, kcred, 0);
1178 }
1179 }
1180
1181 /*
1182 * get_max_pages()
1183 *
1184 * Description:
1185 * This function compute the total pages allowed for agp aperture
1186 * based on the ammount of physical pages.
1187 * The algorithm is: compare the aperture size with 1/4 of total
1188 * physical pages, and use the smaller one to for the max available
1189 * pages. But the minimum video memory should be 192M.
1190 *
1191 * Arguments:
1192 * aper_size system agp aperture size (in MB)
1193 *
1194 * Returns:
1195 * The max possible number of agp memory pages available to users
1196 */
1197 static uint32_t
get_max_pages(uint32_t aper_size)1198 get_max_pages(uint32_t aper_size)
1199 {
1200 uint32_t i, j, size;
1201
1202 ASSERT(aper_size <= MAXAPERMEGAS);
1203
1204 i = AGP_MB2PAGES(aper_size);
1205 j = (physmem >> 2);
1206
1207 size = ((i < j) ? i : j);
1208
1209 if (size < AGP_MB2PAGES(MINAPERMEGAS))
1210 size = AGP_MB2PAGES(MINAPERMEGAS);
1211 return (size);
1212 }
1213
1214 /*
1215 * agp_fill_empty_keyent()
1216 *
1217 * Description:
1218 * This function finds a empty key table slot and
1219 * fills it with a new entity.
1220 *
1221 * Arguments:
1222 * softsate driver soft state pointer
1223 * entryp new entity data pointer
1224 *
1225 * Returns:
1226 * NULL no key table slot available
1227 * entryp the new entity slot pointer
1228 */
1229 static keytable_ent_t *
agp_fill_empty_keyent(agpgart_softstate_t * softstate,keytable_ent_t * entryp)1230 agp_fill_empty_keyent(agpgart_softstate_t *softstate, keytable_ent_t *entryp)
1231 {
1232 int key;
1233 keytable_ent_t *newentryp;
1234
1235 ASSERT(softstate);
1236 ASSERT(entryp);
1237 ASSERT(entryp->kte_memhdl);
1238 ASSERT(entryp->kte_pfnarray);
1239 ASSERT(mutex_owned(&softstate->asoft_instmutex));
1240
1241 for (key = 0; key < AGP_MAXKEYS; key++) {
1242 newentryp = &softstate->asoft_table[key];
1243 if (newentryp->kte_memhdl == NULL) {
1244 break;
1245 }
1246 }
1247
1248 if (key >= AGP_MAXKEYS) {
1249 AGPDB_PRINT2((CE_WARN,
1250 "agp_fill_empty_keyent: key table exhausted"));
1251 return (NULL);
1252 }
1253
1254 ASSERT(newentryp->kte_pfnarray == NULL);
1255 bcopy(entryp, newentryp, sizeof (keytable_ent_t));
1256 newentryp->kte_key = key;
1257
1258 return (newentryp);
1259 }
1260
1261 /*
1262 * agp_find_bound_keyent()
1263 *
1264 * Description:
1265 * This function finds the key table entity by agp aperture page offset.
1266 * Every keytable entity will have an agp aperture range after the binding
1267 * operation.
1268 *
1269 * Arguments:
1270 * softsate driver soft state pointer
1271 * pg_offset agp aperture page offset
1272 *
1273 * Returns:
1274 * NULL no such keytable entity
1275 * pointer key table entity pointer found
1276 */
1277 static keytable_ent_t *
agp_find_bound_keyent(agpgart_softstate_t * softstate,uint32_t pg_offset)1278 agp_find_bound_keyent(agpgart_softstate_t *softstate, uint32_t pg_offset)
1279 {
1280 int keycount;
1281 keytable_ent_t *entryp;
1282
1283 ASSERT(softstate);
1284 ASSERT(mutex_owned(&softstate->asoft_instmutex));
1285
1286 for (keycount = 0; keycount < AGP_MAXKEYS; keycount++) {
1287 entryp = &softstate->asoft_table[keycount];
1288 if (entryp->kte_bound == 0) {
1289 continue;
1290 }
1291
1292 if (pg_offset < entryp->kte_pgoff)
1293 continue;
1294 if (pg_offset >= (entryp->kte_pgoff + entryp->kte_pages))
1295 continue;
1296
1297 ASSERT(entryp->kte_memhdl);
1298 ASSERT(entryp->kte_pfnarray);
1299
1300 return (entryp);
1301 }
1302
1303 return (NULL);
1304 }
1305
1306 /*
1307 * agp_check_off()
1308 *
1309 * Description:
1310 * This function checks whether an AGP aperture range to be bound
1311 * overlaps with AGP offset already bound.
1312 *
1313 * Arguments:
1314 * entryp key table start entry pointer
1315 * pg_start AGP range start page offset
1316 * pg_num pages number to be bound
1317 *
1318 * Returns:
1319 * 0 Does not overlap
1320 * -1 Overlaps
1321 */
1322
1323 static int
agp_check_off(keytable_ent_t * entryp,uint32_t pg_start,uint32_t pg_num)1324 agp_check_off(keytable_ent_t *entryp, uint32_t pg_start, uint32_t pg_num)
1325 {
1326 int key;
1327 uint64_t pg_end;
1328 uint64_t kpg_end;
1329
1330 ASSERT(entryp);
1331
1332 pg_end = pg_start + pg_num;
1333 for (key = 0; key < AGP_MAXKEYS; key++) {
1334 if (!entryp[key].kte_bound)
1335 continue;
1336
1337 kpg_end = entryp[key].kte_pgoff + entryp[key].kte_pages;
1338 if (!((pg_end <= entryp[key].kte_pgoff) ||
1339 (pg_start >= kpg_end)))
1340 break;
1341 }
1342
1343 if (key == AGP_MAXKEYS)
1344 return (0);
1345 else
1346 return (-1);
1347 }
1348
1349 static int
is_controlling_proc(agpgart_softstate_t * st)1350 is_controlling_proc(agpgart_softstate_t *st)
1351 {
1352 ASSERT(st);
1353
1354 if (!st->asoft_acquired) {
1355 AGPDB_PRINT2((CE_WARN,
1356 "ioctl_agpgart_setup: gart not acquired"));
1357 return (-1);
1358 }
1359 if (st->asoft_curpid != ddi_get_pid()) {
1360 AGPDB_PRINT2((CE_WARN,
1361 "ioctl_agpgart_release: not controlling process"));
1362 return (-1);
1363 }
1364
1365 return (0);
1366 }
1367
release_control(agpgart_softstate_t * st)1368 static void release_control(agpgart_softstate_t *st)
1369 {
1370 st->asoft_curpid = 0;
1371 st->asoft_acquired = 0;
1372 }
1373
acquire_control(agpgart_softstate_t * st)1374 static void acquire_control(agpgart_softstate_t *st)
1375 {
1376 st->asoft_curpid = ddi_get_pid();
1377 st->asoft_acquired = 1;
1378 }
1379
1380 /*
1381 * agp_remove_from_gart()
1382 *
1383 * Description:
1384 * This function fills the gart table entries by a given page
1385 * frame number array and setup the agp aperture page to physical
1386 * memory page translation.
1387 * Arguments:
1388 * pg_offset Starting aperture page to be bound
1389 * entries the number of pages to be bound
1390 * acc_hdl GART table dma memory acc handle
1391 * tablep GART table kernel virtual address
1392 */
1393 static void
agp_remove_from_gart(uint32_t pg_offset,uint32_t entries,ddi_dma_handle_t dma_hdl,uint32_t * tablep)1394 agp_remove_from_gart(
1395 uint32_t pg_offset,
1396 uint32_t entries,
1397 ddi_dma_handle_t dma_hdl,
1398 uint32_t *tablep)
1399 {
1400 uint32_t items = 0;
1401 uint32_t *entryp;
1402
1403 entryp = tablep + pg_offset;
1404 while (items < entries) {
1405 *(entryp + items) = 0;
1406 items++;
1407 }
1408 (void) ddi_dma_sync(dma_hdl, pg_offset * sizeof (uint32_t),
1409 entries * sizeof (uint32_t), DDI_DMA_SYNC_FORDEV);
1410 }
1411
1412 /*
1413 * agp_unbind_key()
1414 *
1415 * Description:
1416 * This function unbinds AGP memory from the gart table. It will clear
1417 * all the gart entries related to this agp memory.
1418 *
1419 * Arguments:
1420 * softstate driver soft state pointer
1421 * entryp key table entity pointer
1422 *
1423 * Returns:
1424 * EINVAL invalid key table entity pointer
1425 * 0 success
1426 *
1427 */
1428 static int
agp_unbind_key(agpgart_softstate_t * softstate,keytable_ent_t * entryp)1429 agp_unbind_key(agpgart_softstate_t *softstate, keytable_ent_t *entryp)
1430 {
1431 int retval = 0;
1432
1433 ASSERT(entryp);
1434 ASSERT((entryp->kte_key >= 0) && (entryp->kte_key < AGP_MAXKEYS));
1435
1436 if (!entryp->kte_bound) {
1437 AGPDB_PRINT2((CE_WARN,
1438 "agp_unbind_key: key = 0x%x, not bound",
1439 entryp->kte_key));
1440 return (EINVAL);
1441 }
1442 if (entryp->kte_refcnt) {
1443 AGPDB_PRINT2((CE_WARN,
1444 "agp_unbind_key: memory is exported to users"));
1445 return (EINVAL);
1446 }
1447
1448 ASSERT((entryp->kte_pgoff + entryp->kte_pages) <=
1449 AGP_MB2PAGES(softstate->asoft_info.agpki_apersize));
1450 ASSERT((softstate->asoft_devreg.agprd_arctype != ARC_UNKNOWN));
1451
1452 switch (softstate->asoft_devreg.agprd_arctype) {
1453 case ARC_IGD810:
1454 case ARC_IGD830:
1455 retval = lyr_i8xx_remove_from_gtt(
1456 entryp->kte_pgoff, entryp->kte_pages,
1457 &softstate->asoft_devreg);
1458 if (retval) {
1459 AGPDB_PRINT2((CE_WARN,
1460 "agp_unbind_key: Key = 0x%x, clear table error",
1461 entryp->kte_key));
1462 return (EIO);
1463 }
1464 break;
1465 case ARC_INTELAGP:
1466 case ARC_AMD64AGP:
1467 agp_remove_from_gart(entryp->kte_pgoff,
1468 entryp->kte_pages,
1469 softstate->gart_dma_handle,
1470 (uint32_t *)softstate->gart_vbase);
1471 /* Flush GTLB table */
1472 lyr_flush_gart_cache(&softstate->asoft_devreg);
1473
1474 break;
1475 }
1476
1477 entryp->kte_bound = 0;
1478
1479 return (0);
1480 }
1481
1482 /*
1483 * agp_dealloc_kmem()
1484 *
1485 * Description:
1486 * This function deallocates dma memory resources for userland
1487 * applications.
1488 *
1489 * Arguments:
1490 * entryp keytable entity pointer
1491 */
1492 static void
agp_dealloc_kmem(keytable_ent_t * entryp)1493 agp_dealloc_kmem(keytable_ent_t *entryp)
1494 {
1495 kmem_free(entryp->kte_pfnarray, sizeof (pfn_t) * entryp->kte_pages);
1496 entryp->kte_pfnarray = NULL;
1497
1498 (void) ddi_dma_unbind_handle(KMEMP(entryp->kte_memhdl)->kmem_handle);
1499 KMEMP(entryp->kte_memhdl)->kmem_cookies_num = 0;
1500 ddi_dma_mem_free(&KMEMP(entryp->kte_memhdl)->kmem_acchdl);
1501 KMEMP(entryp->kte_memhdl)->kmem_acchdl = NULL;
1502 KMEMP(entryp->kte_memhdl)->kmem_reallen = 0;
1503 KMEMP(entryp->kte_memhdl)->kmem_kvaddr = NULL;
1504
1505 ddi_dma_free_handle(&(KMEMP(entryp->kte_memhdl)->kmem_handle));
1506 KMEMP(entryp->kte_memhdl)->kmem_handle = NULL;
1507
1508 kmem_free(entryp->kte_memhdl, sizeof (agp_kmem_handle_t));
1509 entryp->kte_memhdl = NULL;
1510 }
1511
1512 /*
1513 * agp_dealloc_mem()
1514 *
1515 * Description:
1516 * This function deallocates physical memory resources allocated for
1517 * userland applications.
1518 *
1519 * Arguments:
1520 * st driver soft state pointer
1521 * entryp key table entity pointer
1522 *
1523 * Returns:
1524 * -1 not a valid memory type or the memory is mapped by
1525 * user area applications
1526 * 0 success
1527 */
1528 static int
agp_dealloc_mem(agpgart_softstate_t * st,keytable_ent_t * entryp)1529 agp_dealloc_mem(agpgart_softstate_t *st, keytable_ent_t *entryp)
1530 {
1531
1532 ASSERT(entryp);
1533 ASSERT(st);
1534 ASSERT(entryp->kte_memhdl);
1535 ASSERT(mutex_owned(&st->asoft_instmutex));
1536
1537 /* auto unbind here */
1538 if (entryp->kte_bound && !entryp->kte_refcnt) {
1539 AGPDB_PRINT2((CE_WARN,
1540 "agp_dealloc_mem: key=0x%x, auto unbind",
1541 entryp->kte_key));
1542
1543 /*
1544 * agp_dealloc_mem may be called indirectly by agp_detach.
1545 * In the agp_detach function, agpgart_close is already
1546 * called which will free the gart table. agp_unbind_key
1547 * will panic if no valid gart table exists. So test if
1548 * gart table exsits here.
1549 */
1550 if (st->asoft_opened)
1551 (void) agp_unbind_key(st, entryp);
1552 }
1553 if (entryp->kte_refcnt) {
1554 AGPDB_PRINT2((CE_WARN,
1555 "agp_dealloc_mem: memory is exported to users"));
1556 return (-1);
1557 }
1558
1559 switch (entryp->kte_type) {
1560 case AGP_NORMAL:
1561 case AGP_PHYSICAL:
1562 agp_dealloc_kmem(entryp);
1563 break;
1564 default:
1565 return (-1);
1566 }
1567
1568 return (0);
1569 }
1570
1571 /*
1572 * agp_del_allkeys()
1573 *
1574 * Description:
1575 * This function calls agp_dealloc_mem to release all the agp memory
1576 * resource allocated.
1577 *
1578 * Arguments:
1579 * softsate driver soft state pointer
1580 * Returns:
1581 * -1 can not free all agp memory
1582 * 0 success
1583 *
1584 */
1585 static int
agp_del_allkeys(agpgart_softstate_t * softstate)1586 agp_del_allkeys(agpgart_softstate_t *softstate)
1587 {
1588 int key;
1589 int ret = 0;
1590
1591 ASSERT(softstate);
1592 for (key = 0; key < AGP_MAXKEYS; key++) {
1593 if (softstate->asoft_table[key].kte_memhdl != NULL) {
1594 /*
1595 * Check if we can free agp memory now.
1596 * If agp memory is exported to user
1597 * applications, agp_dealloc_mem will fail.
1598 */
1599 if (agp_dealloc_mem(softstate,
1600 &softstate->asoft_table[key]))
1601 ret = -1;
1602 }
1603 }
1604
1605 return (ret);
1606 }
1607
1608 /*
1609 * pfn2gartentry()
1610 *
1611 * Description:
1612 * This function converts a physical address to GART entry.
1613 * For AMD64, hardware only support addresses below 40bits,
1614 * about 1024G physical address, so the largest pfn
1615 * number is below 28 bits. Please refer to GART and GTT entry
1616 * format table in agpdefs.h for entry format. Intel IGD only
1617 * only supports GTT entry below 1G. Intel AGP only supports
1618 * GART entry below 4G.
1619 *
1620 * Arguments:
1621 * arc_type system agp arc type
1622 * pfn page frame number
1623 * itemv the entry item to be returned
1624 * Returns:
1625 * -1 not a invalid page frame
1626 * 0 conversion success
1627 */
1628 static int
pfn2gartentry(agp_arc_type_t arc_type,pfn_t pfn,uint32_t * itemv)1629 pfn2gartentry(agp_arc_type_t arc_type, pfn_t pfn, uint32_t *itemv)
1630 {
1631 uint64_t paddr;
1632
1633 paddr = (uint64_t)pfn << AGP_PAGE_SHIFT;
1634 AGPDB_PRINT1((CE_NOTE, "checking pfn number %lu for type %d",
1635 pfn, arc_type));
1636
1637 switch (arc_type) {
1638 case ARC_INTELAGP:
1639 {
1640 /* Only support 32-bit hardware address */
1641 if ((paddr & AGP_INTEL_POINTER_MASK) != 0) {
1642 AGPDB_PRINT2((CE_WARN,
1643 "INTEL AGP Hardware only support 32 bits"));
1644 return (-1);
1645 }
1646 *itemv = (pfn << AGP_PAGE_SHIFT) | AGP_ENTRY_VALID;
1647
1648 break;
1649 }
1650 case ARC_AMD64AGP:
1651 {
1652 uint32_t value1, value2;
1653 /* Physaddr should not exceed 40-bit */
1654 if ((paddr & AMD64_POINTER_MASK) != 0) {
1655 AGPDB_PRINT2((CE_WARN,
1656 "AMD64 GART hardware only supoort 40 bits"));
1657 return (-1);
1658 }
1659 value1 = (uint32_t)pfn >> 20;
1660 value1 <<= 4;
1661 value2 = (uint32_t)pfn << 12;
1662
1663 *itemv = value1 | value2 | AMD64_ENTRY_VALID;
1664 break;
1665 }
1666 case ARC_IGD810:
1667 if ((paddr & I810_POINTER_MASK) != 0) {
1668 AGPDB_PRINT2((CE_WARN,
1669 "Intel i810 only support 30 bits"));
1670 return (-1);
1671 }
1672 break;
1673
1674 case ARC_IGD830:
1675 if ((paddr & GTT_POINTER_MASK) != 0) {
1676 AGPDB_PRINT2((CE_WARN,
1677 "Intel IGD only support 32 bits"));
1678 return (-1);
1679 }
1680 break;
1681 default:
1682 AGPDB_PRINT2((CE_WARN,
1683 "pfn2gartentry: arc type = %d, not support", arc_type));
1684 return (-1);
1685 }
1686 return (0);
1687 }
1688
1689 /*
1690 * Check allocated physical pages validity, only called in DEBUG
1691 * mode.
1692 */
1693 static int
agp_check_pfns(agp_arc_type_t arc_type,pfn_t * pfnarray,int items)1694 agp_check_pfns(agp_arc_type_t arc_type, pfn_t *pfnarray, int items)
1695 {
1696 int count;
1697 uint32_t ret;
1698
1699 for (count = 0; count < items; count++) {
1700 if (pfn2gartentry(arc_type, pfnarray[count], &ret))
1701 break;
1702 }
1703 if (count < items)
1704 return (-1);
1705 else
1706 return (0);
1707 }
1708
1709 /*
1710 * kmem_getpfns()
1711 *
1712 * Description:
1713 * This function gets page frame numbers from dma handle.
1714 *
1715 * Arguments:
1716 * dma_handle dma hanle allocated by ddi_dma_alloc_handle
1717 * dma_cookip dma cookie pointer
1718 * cookies_num cookies number
1719 * pfnarray array to store page frames
1720 *
1721 * Returns:
1722 * 0 success
1723 */
1724 static int
kmem_getpfns(ddi_dma_handle_t dma_handle,ddi_dma_cookie_t * dma_cookiep,int cookies_num,pfn_t * pfnarray)1725 kmem_getpfns(
1726 ddi_dma_handle_t dma_handle,
1727 ddi_dma_cookie_t *dma_cookiep,
1728 int cookies_num,
1729 pfn_t *pfnarray)
1730 {
1731 int num_cookies;
1732 int index = 0;
1733
1734 num_cookies = cookies_num;
1735
1736 while (num_cookies > 0) {
1737 uint64_t ck_startaddr, ck_length, ck_end;
1738 ck_startaddr = dma_cookiep->dmac_address;
1739 ck_length = dma_cookiep->dmac_size;
1740
1741 ck_end = ck_startaddr + ck_length;
1742 while (ck_startaddr < ck_end) {
1743 pfnarray[index] = (pfn_t)ck_startaddr >> AGP_PAGE_SHIFT;
1744 ck_startaddr += AGP_PAGE_SIZE;
1745 index++;
1746 }
1747
1748 num_cookies--;
1749 if (num_cookies > 0) {
1750 ddi_dma_nextcookie(dma_handle, dma_cookiep);
1751 }
1752 }
1753
1754 return (0);
1755 }
1756
1757 static int
copyinfo(agpgart_softstate_t * softstate,agp_info_t * info)1758 copyinfo(agpgart_softstate_t *softstate, agp_info_t *info)
1759 {
1760 switch (softstate->asoft_devreg.agprd_arctype) {
1761 case ARC_IGD810:
1762 case ARC_IGD830:
1763 info->agpi_version.agpv_major = 0;
1764 info->agpi_version.agpv_minor = 0;
1765 info->agpi_devid = softstate->asoft_info.agpki_mdevid;
1766 info->agpi_mode = 0;
1767 break;
1768 case ARC_INTELAGP:
1769 case ARC_AMD64AGP:
1770 info->agpi_version = softstate->asoft_info.agpki_tver;
1771 info->agpi_devid = softstate->asoft_info.agpki_tdevid;
1772 info->agpi_mode = softstate->asoft_info.agpki_tstatus;
1773 break;
1774 default:
1775 AGPDB_PRINT2((CE_WARN, "copyinfo: UNKNOW ARC"));
1776 return (-1);
1777 }
1778 /*
1779 * 64bit->32bit conversion possible
1780 */
1781 info->agpi_aperbase = softstate->asoft_info.agpki_aperbase;
1782 info->agpi_apersize = softstate->asoft_info.agpki_apersize;
1783 info->agpi_pgtotal = softstate->asoft_pgtotal;
1784 info->agpi_pgsystem = info->agpi_pgtotal;
1785 info->agpi_pgused = softstate->asoft_pgused;
1786
1787 return (0);
1788 }
1789
1790 static uint32_t
agp_v2_setup(uint32_t tstatus,uint32_t mstatus,uint32_t mode)1791 agp_v2_setup(uint32_t tstatus, uint32_t mstatus, uint32_t mode)
1792 {
1793 uint32_t cmd;
1794 int rq, sba, over4g, fw, rate;
1795
1796 /*
1797 * tstatus: target device status
1798 * mstatus: master device status
1799 * mode: the agp mode to be sent
1800 */
1801
1802 /*
1803 * RQ - Request Queue size
1804 * set RQ to the min of mode and tstatus
1805 * if mode set a RQ larger than hardware can support,
1806 * use the max RQ which hardware can support.
1807 * tstatus & AGPSTAT_RQ_MASK is the max RQ hardware can support
1808 * Corelogic will enqueue agp transaction
1809 */
1810 rq = mode & AGPSTAT_RQ_MASK;
1811 if ((tstatus & AGPSTAT_RQ_MASK) < rq)
1812 rq = tstatus & AGPSTAT_RQ_MASK;
1813
1814 /*
1815 * SBA - Sideband Addressing
1816 *
1817 * Sideband Addressing provides an additional bus to pass requests
1818 * (address and command) to the target from the master.
1819 *
1820 * set SBA if all three support it
1821 */
1822 sba = (tstatus & AGPSTAT_SBA) & (mstatus & AGPSTAT_SBA)
1823 & (mode & AGPSTAT_SBA);
1824
1825 /* set OVER4G if all three support it */
1826 over4g = (tstatus & AGPSTAT_OVER4G) & (mstatus & AGPSTAT_OVER4G)
1827 & (mode & AGPSTAT_OVER4G);
1828
1829 /*
1830 * FW - fast write
1831 *
1832 * acceleration of memory write transactions from the corelogic to the
1833 * A.G.P. master device acting like a PCI target.
1834 *
1835 * set FW if all three support it
1836 */
1837 fw = (tstatus & AGPSTAT_FW) & (mstatus & AGPSTAT_FW)
1838 & (mode & AGPSTAT_FW);
1839
1840 /*
1841 * figure out the max rate
1842 * AGP v2 support: 4X, 2X, 1X speed
1843 * status bit meaning
1844 * ---------------------------------------------
1845 * 7:3 others
1846 * 3 0 stand for V2 support
1847 * 0:2 001:1X, 010:2X, 100:4X
1848 * ----------------------------------------------
1849 */
1850 rate = (tstatus & AGPSTAT_RATE_MASK) & (mstatus & AGPSTAT_RATE_MASK)
1851 & (mode & AGPSTAT_RATE_MASK);
1852 if (rate & AGP2_RATE_4X)
1853 rate = AGP2_RATE_4X;
1854 else if (rate & AGP2_RATE_2X)
1855 rate = AGP2_RATE_2X;
1856 else
1857 rate = AGP2_RATE_1X;
1858
1859 cmd = rq | sba | over4g | fw | rate;
1860 /* enable agp mode */
1861 cmd |= AGPCMD_AGPEN;
1862
1863 return (cmd);
1864 }
1865
1866 static uint32_t
agp_v3_setup(uint32_t tstatus,uint32_t mstatus,uint32_t mode)1867 agp_v3_setup(uint32_t tstatus, uint32_t mstatus, uint32_t mode)
1868 {
1869 uint32_t cmd = 0;
1870 uint32_t rq, arqsz, cal, sba, over4g, fw, rate;
1871
1872 /*
1873 * tstatus: target device status
1874 * mstatus: master device status
1875 * mode: the agp mode to be set
1876 */
1877
1878 /*
1879 * RQ - Request Queue size
1880 * Set RQ to the min of mode and tstatus
1881 * If mode set a RQ larger than hardware can support,
1882 * use the max RQ which hardware can support.
1883 * tstatus & AGPSTAT_RQ_MASK is the max RQ hardware can support
1884 * Corelogic will enqueue agp transaction;
1885 */
1886 rq = mode & AGPSTAT_RQ_MASK;
1887 if ((tstatus & AGPSTAT_RQ_MASK) < rq)
1888 rq = tstatus & AGPSTAT_RQ_MASK;
1889
1890 /*
1891 * ARQSZ - Asynchronous Request Queue size
1892 * Set the value equal to tstatus.
1893 * Don't allow the mode register to override values
1894 */
1895 arqsz = tstatus & AGPSTAT_ARQSZ_MASK;
1896
1897 /*
1898 * CAL - Calibration cycle
1899 * Set to the min of tstatus and mstatus
1900 * Don't allow override by mode register
1901 */
1902 cal = tstatus & AGPSTAT_CAL_MASK;
1903 if ((mstatus & AGPSTAT_CAL_MASK) < cal)
1904 cal = mstatus & AGPSTAT_CAL_MASK;
1905
1906 /*
1907 * SBA - Sideband Addressing
1908 *
1909 * Sideband Addressing provides an additional bus to pass requests
1910 * (address and command) to the target from the master.
1911 *
1912 * SBA in agp v3.0 must be set
1913 */
1914 sba = AGPCMD_SBAEN;
1915
1916 /* GART64B is not set since no hardware supports it now */
1917
1918 /* Set OVER4G if all three support it */
1919 over4g = (tstatus & AGPSTAT_OVER4G) & (mstatus & AGPSTAT_OVER4G)
1920 & (mode & AGPSTAT_OVER4G);
1921
1922 /*
1923 * FW - fast write
1924 *
1925 * Acceleration of memory write transactions from the corelogic to the
1926 * A.G.P. master device acting like a PCI target.
1927 *
1928 * Always set FW in AGP 3.0
1929 */
1930 fw = (tstatus & AGPSTAT_FW) & (mstatus & AGPSTAT_FW)
1931 & (mode & AGPSTAT_FW);
1932
1933 /*
1934 * Figure out the max rate
1935 *
1936 * AGP v3 support: 8X, 4X speed
1937 *
1938 * status bit meaning
1939 * ---------------------------------------------
1940 * 7:3 others
1941 * 3 1 stand for V3 support
1942 * 0:2 001:4X, 010:8X, 011:4X,8X
1943 * ----------------------------------------------
1944 */
1945 rate = (tstatus & AGPSTAT_RATE_MASK) & (mstatus & AGPSTAT_RATE_MASK)
1946 & (mode & AGPSTAT_RATE_MASK);
1947 if (rate & AGP3_RATE_8X)
1948 rate = AGP3_RATE_8X;
1949 else
1950 rate = AGP3_RATE_4X;
1951
1952 cmd = rq | arqsz | cal | sba | over4g | fw | rate;
1953 /* Enable AGP mode */
1954 cmd |= AGPCMD_AGPEN;
1955
1956 return (cmd);
1957 }
1958
1959 static int
agp_setup(agpgart_softstate_t * softstate,uint32_t mode)1960 agp_setup(agpgart_softstate_t *softstate, uint32_t mode)
1961 {
1962 uint32_t tstatus, mstatus;
1963 uint32_t agp_mode;
1964
1965 tstatus = softstate->asoft_info.agpki_tstatus;
1966 mstatus = softstate->asoft_info.agpki_mstatus;
1967
1968 /*
1969 * There are three kinds of AGP mode. AGP mode 1.0, 2.0, 3.0
1970 * AGP mode 2.0 is fully compatible with AGP mode 1.0, so we
1971 * only check 2.0 and 3.0 mode. AGP 3.0 device can work in
1972 * two AGP 2.0 or AGP 3.0 mode. By checking AGP status register,
1973 * we can get which mode it is working at. The working mode of
1974 * AGP master and AGP target must be consistent. That is, both
1975 * of them must work on AGP 3.0 mode or AGP 2.0 mode.
1976 */
1977 if ((softstate->asoft_info.agpki_tver.agpv_major == 3) &&
1978 (tstatus & AGPSTAT_MODE3)) {
1979 /* Master device should be 3.0 mode, too */
1980 if ((softstate->asoft_info.agpki_mver.agpv_major != 3) ||
1981 ((mstatus & AGPSTAT_MODE3) == 0))
1982 return (EIO);
1983
1984 agp_mode = agp_v3_setup(tstatus, mstatus, mode);
1985 /* Write to the AGPCMD register of target and master devices */
1986 if (lyr_set_agp_cmd(agp_mode,
1987 &softstate->asoft_devreg))
1988 return (EIO);
1989
1990 softstate->asoft_mode = agp_mode;
1991
1992 return (0);
1993 }
1994
1995 /*
1996 * If agp taget device doesn't work in AGP 3.0 mode,
1997 * it must work in AGP 2.0 mode. And make sure
1998 * master device work in AGP 2.0 mode too
1999 */
2000 if ((softstate->asoft_info.agpki_mver.agpv_major == 3) &&
2001 (mstatus & AGPSTAT_MODE3))
2002 return (EIO);
2003
2004 agp_mode = agp_v2_setup(tstatus, mstatus, mode);
2005 if (lyr_set_agp_cmd(agp_mode, &softstate->asoft_devreg))
2006 return (EIO);
2007 softstate->asoft_mode = agp_mode;
2008
2009 return (0);
2010 }
2011
2012 /*
2013 * agp_alloc_kmem()
2014 *
2015 * Description:
2016 * This function allocates physical memory for userland applications
2017 * by ddi interfaces. This function can also be called to allocate
2018 * small phsyical contiguous pages, usually tens of kilobytes.
2019 *
2020 * Arguments:
2021 * softsate driver soft state pointer
2022 * length memory size
2023 *
2024 * Returns:
2025 * entryp new keytable entity pointer
2026 * NULL no keytable slot available or no physical
2027 * memory available
2028 */
2029 static keytable_ent_t *
agp_alloc_kmem(agpgart_softstate_t * softstate,size_t length,int type)2030 agp_alloc_kmem(agpgart_softstate_t *softstate, size_t length, int type)
2031 {
2032 keytable_ent_t keyentry;
2033 keytable_ent_t *entryp;
2034 int ret;
2035
2036 ASSERT(AGP_ALIGNED(length));
2037
2038 bzero(&keyentry, sizeof (keytable_ent_t));
2039
2040 keyentry.kte_pages = AGP_BYTES2PAGES(length);
2041 keyentry.kte_type = type;
2042
2043 /*
2044 * Set dma_attr_sgllen to assure contiguous physical pages
2045 */
2046 if (type == AGP_PHYSICAL)
2047 agpgart_dma_attr.dma_attr_sgllen = 1;
2048 else
2049 agpgart_dma_attr.dma_attr_sgllen = (int)keyentry.kte_pages;
2050
2051 /* 4k size pages */
2052 keyentry.kte_memhdl = kmem_zalloc(sizeof (agp_kmem_handle_t), KM_SLEEP);
2053
2054 if (ddi_dma_alloc_handle(softstate->asoft_dip,
2055 &agpgart_dma_attr,
2056 DDI_DMA_SLEEP, NULL,
2057 &(KMEMP(keyentry.kte_memhdl)->kmem_handle))) {
2058 AGPDB_PRINT2((CE_WARN,
2059 "agp_alloc_kmem: ddi_dma_allco_hanlde error"));
2060 goto err4;
2061 }
2062
2063 if ((ret = ddi_dma_mem_alloc(
2064 KMEMP(keyentry.kte_memhdl)->kmem_handle,
2065 length,
2066 &gart_dev_acc_attr,
2067 DDI_DMA_CONSISTENT,
2068 DDI_DMA_SLEEP, NULL,
2069 &KMEMP(keyentry.kte_memhdl)->kmem_kvaddr,
2070 &KMEMP(keyentry.kte_memhdl)->kmem_reallen,
2071 &KMEMP(keyentry.kte_memhdl)->kmem_acchdl)) != 0) {
2072 AGPDB_PRINT2((CE_WARN,
2073 "agp_alloc_kmem: ddi_dma_mem_alloc error"));
2074
2075 goto err3;
2076 }
2077
2078 ret = ddi_dma_addr_bind_handle(
2079 KMEMP(keyentry.kte_memhdl)->kmem_handle,
2080 NULL,
2081 KMEMP(keyentry.kte_memhdl)->kmem_kvaddr,
2082 length,
2083 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2084 DDI_DMA_SLEEP,
2085 NULL,
2086 &KMEMP(keyentry.kte_memhdl)->kmem_dcookie,
2087 &KMEMP(keyentry.kte_memhdl)->kmem_cookies_num);
2088
2089 /*
2090 * Even dma_attr_sgllen = 1, ddi_dma_addr_bind_handle may return more
2091 * than one cookie, we check this in the if statement.
2092 */
2093
2094 if ((ret != DDI_DMA_MAPPED) ||
2095 ((agpgart_dma_attr.dma_attr_sgllen == 1) &&
2096 (KMEMP(keyentry.kte_memhdl)->kmem_cookies_num != 1))) {
2097 AGPDB_PRINT2((CE_WARN,
2098 "agp_alloc_kmem: can not alloc physical memory properly"));
2099 goto err2;
2100 }
2101
2102 keyentry.kte_pfnarray = (pfn_t *)kmem_zalloc(sizeof (pfn_t) *
2103 keyentry.kte_pages, KM_SLEEP);
2104
2105 if (kmem_getpfns(
2106 KMEMP(keyentry.kte_memhdl)->kmem_handle,
2107 &KMEMP(keyentry.kte_memhdl)->kmem_dcookie,
2108 KMEMP(keyentry.kte_memhdl)->kmem_cookies_num,
2109 keyentry.kte_pfnarray)) {
2110 AGPDB_PRINT2((CE_WARN, "agp_alloc_kmem: get pfn array error"));
2111 goto err1;
2112 }
2113
2114 ASSERT(!agp_check_pfns(softstate->asoft_devreg.agprd_arctype,
2115 keyentry.kte_pfnarray, keyentry.kte_pages));
2116 if (agp_check_pfns(softstate->asoft_devreg.agprd_arctype,
2117 keyentry.kte_pfnarray, keyentry.kte_pages))
2118 goto err1;
2119 entryp = agp_fill_empty_keyent(softstate, &keyentry);
2120 if (!entryp) {
2121 AGPDB_PRINT2((CE_WARN,
2122 "agp_alloc_kmem: agp_fill_empty_keyent error"));
2123
2124 goto err1;
2125 }
2126 ASSERT((entryp->kte_key >= 0) && (entryp->kte_key < AGP_MAXKEYS));
2127
2128 return (entryp);
2129
2130 err1:
2131 kmem_free(keyentry.kte_pfnarray, sizeof (pfn_t) * keyentry.kte_pages);
2132 keyentry.kte_pfnarray = NULL;
2133 (void) ddi_dma_unbind_handle(KMEMP(keyentry.kte_memhdl)->kmem_handle);
2134 KMEMP(keyentry.kte_memhdl)->kmem_cookies_num = 0;
2135 err2:
2136 ddi_dma_mem_free(&KMEMP(keyentry.kte_memhdl)->kmem_acchdl);
2137 KMEMP(keyentry.kte_memhdl)->kmem_acchdl = NULL;
2138 KMEMP(keyentry.kte_memhdl)->kmem_reallen = 0;
2139 KMEMP(keyentry.kte_memhdl)->kmem_kvaddr = NULL;
2140 err3:
2141 ddi_dma_free_handle(&(KMEMP(keyentry.kte_memhdl)->kmem_handle));
2142 KMEMP(keyentry.kte_memhdl)->kmem_handle = NULL;
2143 err4:
2144 kmem_free(keyentry.kte_memhdl, sizeof (agp_kmem_handle_t));
2145 keyentry.kte_memhdl = NULL;
2146 return (NULL);
2147
2148 }
2149
2150 /*
2151 * agp_alloc_mem()
2152 *
2153 * Description:
2154 * This function allocate physical memory for userland applications,
2155 * in order to save kernel virtual space, we use the direct mapping
2156 * memory interface if it is available.
2157 *
2158 * Arguments:
2159 * st driver soft state pointer
2160 * length memory size
2161 * type AGP_NORMAL: normal agp memory, AGP_PHISYCAL: specical
2162 * memory type for intel i810 IGD
2163 *
2164 * Returns:
2165 * NULL Invalid memory type or can not allocate memory
2166 * Keytable entry pointer returned by agp_alloc_kmem
2167 */
2168 static keytable_ent_t *
agp_alloc_mem(agpgart_softstate_t * st,size_t length,int type)2169 agp_alloc_mem(agpgart_softstate_t *st, size_t length, int type)
2170 {
2171
2172 /*
2173 * AGP_PHYSICAL type require contiguous physical pages exported
2174 * to X drivers, like i810 HW cursor, ARGB cursor. the number of
2175 * pages needed is usuallysmall and contiguous, 4K, 16K. So we
2176 * use DDI interface to allocated such memory. And X use xsvc
2177 * drivers to map this memory into its own address space.
2178 */
2179 ASSERT(st);
2180
2181 switch (type) {
2182 case AGP_NORMAL:
2183 case AGP_PHYSICAL:
2184 return (agp_alloc_kmem(st, length, type));
2185 default:
2186 return (NULL);
2187 }
2188 }
2189
2190 /*
2191 * free_gart_table()
2192 *
2193 * Description:
2194 * This function frees the gart table memory allocated by driver.
2195 * Must disable gart table before calling this function.
2196 *
2197 * Arguments:
2198 * softstate driver soft state pointer
2199 *
2200 */
2201 static void
free_gart_table(agpgart_softstate_t * st)2202 free_gart_table(agpgart_softstate_t *st)
2203 {
2204
2205 if (st->gart_dma_handle == NULL)
2206 return;
2207
2208 (void) ddi_dma_unbind_handle(st->gart_dma_handle);
2209 ddi_dma_mem_free(&st->gart_dma_acc_handle);
2210 st->gart_dma_acc_handle = NULL;
2211 ddi_dma_free_handle(&st->gart_dma_handle);
2212 st->gart_dma_handle = NULL;
2213 st->gart_vbase = 0;
2214 st->gart_size = 0;
2215 }
2216
2217 /*
2218 * alloc_gart_table()
2219 *
2220 * Description:
2221 * This function allocates one physical continuous gart table.
2222 * INTEL integrated video device except i810 have their special
2223 * video bios; No need to allocate gart table for them.
2224 *
2225 * Arguments:
2226 * st driver soft state pointer
2227 *
2228 * Returns:
2229 * 0 success
2230 * -1 can not allocate gart tabl
2231 */
2232 static int
alloc_gart_table(agpgart_softstate_t * st)2233 alloc_gart_table(agpgart_softstate_t *st)
2234 {
2235 int num_pages;
2236 size_t table_size;
2237 int ret = DDI_SUCCESS;
2238 ddi_dma_cookie_t cookie;
2239 uint32_t num_cookies;
2240
2241 num_pages = AGP_MB2PAGES(st->asoft_info.agpki_apersize);
2242
2243 /*
2244 * Only 40-bit maximum physical memory is supported by today's
2245 * AGP hardware (32-bit gart tables can hold 40-bit memory addresses).
2246 * No one supports 64-bit gart entries now, so the size of gart
2247 * entries defaults to 32-bit though AGP3.0 specifies the possibility
2248 * of 64-bit gart entries.
2249 */
2250
2251 table_size = num_pages * (sizeof (uint32_t));
2252
2253 /*
2254 * Only AMD64 can put gart table above 4G, 40 bits at maximum
2255 */
2256 if (st->asoft_devreg.agprd_arctype == ARC_AMD64AGP)
2257 garttable_dma_attr.dma_attr_addr_hi = 0xffffffffffLL;
2258 else
2259 garttable_dma_attr.dma_attr_addr_hi = 0xffffffffU;
2260 /* Allocate physical continuous page frame for gart table */
2261 if (ret = ddi_dma_alloc_handle(st->asoft_dip,
2262 &garttable_dma_attr,
2263 DDI_DMA_SLEEP,
2264 NULL, &st->gart_dma_handle)) {
2265 AGPDB_PRINT2((CE_WARN,
2266 "alloc_gart_table: ddi_dma_alloc_handle failed"));
2267 goto err3;
2268 }
2269
2270 if (ret = ddi_dma_mem_alloc(st->gart_dma_handle,
2271 table_size,
2272 &gart_dev_acc_attr,
2273 DDI_DMA_CONSISTENT,
2274 DDI_DMA_SLEEP, NULL,
2275 &st->gart_vbase,
2276 &st->gart_size,
2277 &st->gart_dma_acc_handle)) {
2278 AGPDB_PRINT2((CE_WARN,
2279 "alloc_gart_table: ddi_dma_mem_alloc failed"));
2280 goto err2;
2281
2282 }
2283
2284 ret = ddi_dma_addr_bind_handle(st->gart_dma_handle,
2285 NULL, st->gart_vbase,
2286 table_size,
2287 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
2288 DDI_DMA_SLEEP, NULL,
2289 &cookie, &num_cookies);
2290
2291 st->gart_pbase = cookie.dmac_address;
2292
2293 if ((ret != DDI_DMA_MAPPED) || (num_cookies != 1)) {
2294 if (num_cookies > 1)
2295 (void) ddi_dma_unbind_handle(st->gart_dma_handle);
2296 AGPDB_PRINT2((CE_WARN,
2297 "alloc_gart_table: alloc contiguous phys memory failed"));
2298 goto err1;
2299 }
2300
2301 return (0);
2302 err1:
2303 ddi_dma_mem_free(&st->gart_dma_acc_handle);
2304 st->gart_dma_acc_handle = NULL;
2305 err2:
2306 ddi_dma_free_handle(&st->gart_dma_handle);
2307 st->gart_dma_handle = NULL;
2308 err3:
2309 st->gart_pbase = 0;
2310 st->gart_size = 0;
2311 st->gart_vbase = 0;
2312
2313 return (-1);
2314 }
2315
2316 /*
2317 * agp_add_to_gart()
2318 *
2319 * Description:
2320 * This function fills the gart table entries by a given page frame number
2321 * array and set up the agp aperture page to physical memory page
2322 * translation.
2323 * Arguments:
2324 * type valid sytem arc types ARC_AMD64AGP, ARC_INTELAGP,
2325 * ARC_AMD64AGP
2326 * pfnarray allocated physical page frame number array
2327 * pg_offset agp aperture start page to be bound
2328 * entries the number of pages to be bound
2329 * dma_hdl gart table dma memory handle
2330 * tablep gart table kernel virtual address
2331 * Returns:
2332 * -1 failed
2333 * 0 success
2334 */
2335 static int
agp_add_to_gart(agp_arc_type_t type,pfn_t * pfnarray,uint32_t pg_offset,uint32_t entries,ddi_dma_handle_t dma_hdl,uint32_t * tablep)2336 agp_add_to_gart(
2337 agp_arc_type_t type,
2338 pfn_t *pfnarray,
2339 uint32_t pg_offset,
2340 uint32_t entries,
2341 ddi_dma_handle_t dma_hdl,
2342 uint32_t *tablep)
2343 {
2344 int items = 0;
2345 uint32_t *entryp;
2346 uint32_t itemv;
2347
2348 entryp = tablep + pg_offset;
2349 while (items < entries) {
2350 if (pfn2gartentry(type, pfnarray[items], &itemv))
2351 break;
2352 *(entryp + items) = itemv;
2353 items++;
2354 }
2355 if (items < entries)
2356 return (-1);
2357
2358 (void) ddi_dma_sync(dma_hdl, pg_offset * sizeof (uint32_t),
2359 entries * sizeof (uint32_t), DDI_DMA_SYNC_FORDEV);
2360
2361 return (0);
2362 }
2363
2364 /*
2365 * agp_bind_key()
2366 *
2367 * Description:
2368 * This function will call low level gart table access functions to
2369 * set up gart table translation. Also it will do some sanity
2370 * checking on key table entry.
2371 *
2372 * Arguments:
2373 * softstate driver soft state pointer
2374 * keyent key table entity pointer to be bound
2375 * pg_offset aperture start page to be bound
2376 * Returns:
2377 * EINVAL not a valid operation
2378 */
2379 static int
agp_bind_key(agpgart_softstate_t * softstate,keytable_ent_t * keyent,uint32_t pg_offset)2380 agp_bind_key(agpgart_softstate_t *softstate,
2381 keytable_ent_t *keyent, uint32_t pg_offset)
2382 {
2383 uint64_t pg_end;
2384 int ret = 0;
2385
2386 ASSERT(keyent);
2387 ASSERT((keyent->kte_key >= 0) && (keyent->kte_key < AGP_MAXKEYS));
2388 ASSERT(mutex_owned(&softstate->asoft_instmutex));
2389
2390 pg_end = pg_offset + keyent->kte_pages;
2391
2392 if (pg_end > AGP_MB2PAGES(softstate->asoft_info.agpki_apersize)) {
2393 AGPDB_PRINT2((CE_WARN,
2394 "agp_bind_key: key=0x%x,exceed aper range",
2395 keyent->kte_key));
2396
2397 return (EINVAL);
2398 }
2399
2400 if (agp_check_off(softstate->asoft_table,
2401 pg_offset, keyent->kte_pages)) {
2402 AGPDB_PRINT2((CE_WARN,
2403 "agp_bind_key: pg_offset=0x%x, pages=0x%lx overlaped",
2404 pg_offset, keyent->kte_pages));
2405 return (EINVAL);
2406 }
2407
2408 ASSERT(keyent->kte_pfnarray != NULL);
2409
2410 switch (softstate->asoft_devreg.agprd_arctype) {
2411 case ARC_IGD810:
2412 case ARC_IGD830:
2413 ret = lyr_i8xx_add_to_gtt(pg_offset, keyent,
2414 &softstate->asoft_devreg);
2415 if (ret)
2416 return (EIO);
2417 break;
2418 case ARC_INTELAGP:
2419 case ARC_AMD64AGP:
2420 ret = agp_add_to_gart(
2421 softstate->asoft_devreg.agprd_arctype,
2422 keyent->kte_pfnarray,
2423 pg_offset,
2424 keyent->kte_pages,
2425 softstate->gart_dma_handle,
2426 (uint32_t *)softstate->gart_vbase);
2427 if (ret)
2428 return (EINVAL);
2429 /* Flush GTLB table */
2430 lyr_flush_gart_cache(&softstate->asoft_devreg);
2431 break;
2432 default:
2433 AGPDB_PRINT2((CE_WARN,
2434 "agp_bind_key: arc type = 0x%x unsupported",
2435 softstate->asoft_devreg.agprd_arctype));
2436 return (EINVAL);
2437 }
2438 return (0);
2439 }
2440
2441 static int
agpgart_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2442 agpgart_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2443 {
2444 int instance;
2445 agpgart_softstate_t *softstate;
2446
2447 if (cmd != DDI_ATTACH) {
2448 AGPDB_PRINT2((CE_WARN,
2449 "agpgart_attach: only attach op supported"));
2450 return (DDI_FAILURE);
2451 }
2452 instance = ddi_get_instance(dip);
2453
2454 if (ddi_soft_state_zalloc(agpgart_glob_soft_handle, instance)
2455 != DDI_SUCCESS) {
2456 AGPDB_PRINT2((CE_WARN,
2457 "agpgart_attach: soft state zalloc failed"));
2458 goto err1;
2459
2460 }
2461 softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
2462 mutex_init(&softstate->asoft_instmutex, NULL, MUTEX_DRIVER, NULL);
2463 softstate->asoft_dip = dip;
2464 /*
2465 * Allocate LDI identifier for agpgart driver
2466 * Agpgart driver is the kernel consumer
2467 */
2468 if (ldi_ident_from_dip(dip, &softstate->asoft_li)) {
2469 AGPDB_PRINT2((CE_WARN,
2470 "agpgart_attach: LDI indentifier allcation failed"));
2471 goto err2;
2472 }
2473
2474 softstate->asoft_devreg.agprd_arctype = ARC_UNKNOWN;
2475 /* Install agp kstat */
2476 if (agp_init_kstats(softstate)) {
2477 AGPDB_PRINT2((CE_WARN, "agpgart_attach: init kstats error"));
2478 goto err3;
2479 }
2480 /*
2481 * devfs will create /dev/agpgart
2482 * and /devices/agpgart:agpgart
2483 */
2484
2485 if (ddi_create_minor_node(dip, AGPGART_DEVNODE, S_IFCHR,
2486 AGP_INST2MINOR(instance),
2487 DDI_NT_AGP_PSEUDO, 0)) {
2488 AGPDB_PRINT2((CE_WARN,
2489 "agpgart_attach: Can not create minor node"));
2490 goto err4;
2491 }
2492
2493 softstate->asoft_table = kmem_zalloc(
2494 AGP_MAXKEYS * (sizeof (keytable_ent_t)),
2495 KM_SLEEP);
2496
2497 list_head_init(&softstate->mapped_list);
2498
2499 return (DDI_SUCCESS);
2500 err4:
2501 agp_fini_kstats(softstate);
2502 err3:
2503 ldi_ident_release(softstate->asoft_li);
2504 err2:
2505 ddi_soft_state_free(agpgart_glob_soft_handle, instance);
2506 err1:
2507 return (DDI_FAILURE);
2508 }
2509
2510 static int
agpgart_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2511 agpgart_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2512 {
2513 int instance;
2514 agpgart_softstate_t *st;
2515
2516 instance = ddi_get_instance(dip);
2517
2518 st = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
2519
2520 if (cmd != DDI_DETACH)
2521 return (DDI_FAILURE);
2522
2523 /*
2524 * Caller should free all the memory allocated explicitly.
2525 * We release the memory allocated by caller which is not
2526 * properly freed. mutex_enter here make sure assertion on
2527 * softstate mutex success in agp_dealloc_mem.
2528 */
2529 mutex_enter(&st->asoft_instmutex);
2530 if (agp_del_allkeys(st)) {
2531 AGPDB_PRINT2((CE_WARN, "agpgart_detach: agp_del_allkeys err"));
2532 AGPDB_PRINT2((CE_WARN,
2533 "you might free agp memory exported to your applications"));
2534
2535 mutex_exit(&st->asoft_instmutex);
2536 return (DDI_FAILURE);
2537 }
2538 mutex_exit(&st->asoft_instmutex);
2539 if (st->asoft_table) {
2540 kmem_free(st->asoft_table,
2541 AGP_MAXKEYS * (sizeof (keytable_ent_t)));
2542 st->asoft_table = 0;
2543 }
2544
2545 struct list_head *entry, *temp, *head;
2546 igd_gtt_seg_t *gttseg;
2547 list_head_for_each_safe(entry, temp, &st->mapped_list) {
2548 gttseg = entry->gttseg;
2549 list_head_del(entry);
2550 kmem_free(entry, sizeof (*entry));
2551 kmem_free(gttseg->igs_phyaddr,
2552 sizeof (uint32_t) * gttseg->igs_npage);
2553 kmem_free(gttseg, sizeof (igd_gtt_seg_t));
2554 }
2555 head = &st->mapped_list;
2556 kmem_free(head->next,
2557 AGP_HASH_NODE * sizeof (struct list_head));
2558 head->next = NULL;
2559
2560 ddi_remove_minor_node(dip, AGPGART_DEVNODE);
2561 agp_fini_kstats(st);
2562 ldi_ident_release(st->asoft_li);
2563 mutex_destroy(&st->asoft_instmutex);
2564 ddi_soft_state_free(agpgart_glob_soft_handle, instance);
2565
2566 return (DDI_SUCCESS);
2567 }
2568
2569 /*ARGSUSED*/
2570 static int
agpgart_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)2571 agpgart_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
2572 void **resultp)
2573 {
2574 agpgart_softstate_t *st;
2575 int instance, rval = DDI_FAILURE;
2576 dev_t dev;
2577
2578 switch (cmd) {
2579 case DDI_INFO_DEVT2DEVINFO:
2580 dev = (dev_t)arg;
2581 instance = AGP_DEV2INST(dev);
2582 st = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
2583 if (st != NULL) {
2584 mutex_enter(&st->asoft_instmutex);
2585 *resultp = st->asoft_dip;
2586 mutex_exit(&st->asoft_instmutex);
2587 rval = DDI_SUCCESS;
2588 } else
2589 *resultp = NULL;
2590
2591 break;
2592 case DDI_INFO_DEVT2INSTANCE:
2593 dev = (dev_t)arg;
2594 instance = AGP_DEV2INST(dev);
2595 *resultp = (void *)(uintptr_t)instance;
2596 rval = DDI_SUCCESS;
2597
2598 break;
2599 default:
2600 break;
2601 }
2602
2603 return (rval);
2604 }
2605
2606 /*
2607 * agpgart_open()
2608 *
2609 * Description:
2610 * This function is the driver open entry point. If it is the
2611 * first time the agpgart driver is opened, the driver will
2612 * open other agp related layered drivers and set up the agpgart
2613 * table properly.
2614 *
2615 * Arguments:
2616 * dev device number pointer
2617 * openflags open flags
2618 * otyp OTYP_BLK, OTYP_CHR
2619 * credp user's credential's struct pointer
2620 *
2621 * Returns:
2622 * ENXIO operation error
2623 * EAGAIN resoure temporarily unvailable
2624 * 0 success
2625 */
2626 /*ARGSUSED*/
2627 static int
agpgart_open(dev_t * dev,int openflags,int otyp,cred_t * credp)2628 agpgart_open(dev_t *dev, int openflags, int otyp, cred_t *credp)
2629 {
2630 int instance = AGP_DEV2INST(*dev);
2631 agpgart_softstate_t *softstate;
2632 int rc = 0;
2633 uint32_t devid;
2634
2635 if (secpolicy_gart_access(credp)) {
2636 AGPDB_PRINT2((CE_WARN, "agpgart_open: permission denied"));
2637 return (EPERM);
2638 }
2639 softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
2640 if (softstate == NULL) {
2641 AGPDB_PRINT2((CE_WARN, "agpgart_open: get soft state err"));
2642 return (ENXIO);
2643 }
2644
2645 mutex_enter(&softstate->asoft_instmutex);
2646
2647 if (softstate->asoft_opened) {
2648 softstate->asoft_opened++;
2649 mutex_exit(&softstate->asoft_instmutex);
2650 return (0);
2651 }
2652
2653 /*
2654 * The driver is opened first time, so we initialize layered
2655 * driver interface and softstate member here.
2656 */
2657 softstate->asoft_pgused = 0;
2658 if (lyr_init(&softstate->asoft_devreg, softstate->asoft_li)) {
2659 AGPDB_PRINT2((CE_WARN, "agpgart_open: lyr_init failed"));
2660 mutex_exit(&softstate->asoft_instmutex);
2661 return (EAGAIN);
2662 }
2663
2664 /* Call into layered driver */
2665 if (lyr_get_info(&softstate->asoft_info, &softstate->asoft_devreg)) {
2666 AGPDB_PRINT2((CE_WARN, "agpgart_open: lyr_get_info error"));
2667 lyr_end(&softstate->asoft_devreg);
2668 mutex_exit(&softstate->asoft_instmutex);
2669 return (EIO);
2670 }
2671
2672 /*
2673 * BIOS already set up gtt table for ARC_IGD830
2674 */
2675 if (IS_INTEL_830(softstate->asoft_devreg.agprd_arctype)) {
2676 softstate->asoft_opened++;
2677
2678 softstate->asoft_pgtotal =
2679 get_max_pages(softstate->asoft_info.agpki_apersize);
2680
2681 if (lyr_config_devices(&softstate->asoft_devreg)) {
2682 AGPDB_PRINT2((CE_WARN,
2683 "agpgart_open: lyr_config_devices error"));
2684 lyr_end(&softstate->asoft_devreg);
2685 mutex_exit(&softstate->asoft_instmutex);
2686
2687 return (EIO);
2688 }
2689 devid = softstate->asoft_info.agpki_mdevid;
2690 if (IS_INTEL_915(devid) ||
2691 IS_INTEL_965(devid) ||
2692 IS_INTEL_X33(devid) ||
2693 IS_INTEL_G4X(devid)) {
2694 rc = ldi_ioctl(softstate->asoft_devreg.agprd_targethdl,
2695 INTEL_CHIPSET_FLUSH_SETUP, 0, FKIOCTL, kcred, 0);
2696 }
2697 if (rc) {
2698 AGPDB_PRINT2((CE_WARN,
2699 "agpgart_open: Intel chipset flush setup error"));
2700 lyr_end(&softstate->asoft_devreg);
2701 mutex_exit(&softstate->asoft_instmutex);
2702 return (EIO);
2703 }
2704 mutex_exit(&softstate->asoft_instmutex);
2705 return (0);
2706 }
2707
2708 rc = alloc_gart_table(softstate);
2709
2710 /*
2711 * Allocate physically contiguous pages for AGP arc or
2712 * i810 arc. If failed, divide aper_size by 2 to
2713 * reduce gart table size until 4 megabytes. This
2714 * is just a workaround for systems with very few
2715 * physically contiguous memory.
2716 */
2717 if (rc) {
2718 while ((softstate->asoft_info.agpki_apersize >= 4) &&
2719 (alloc_gart_table(softstate))) {
2720 softstate->asoft_info.agpki_apersize >>= 1;
2721 }
2722 if (softstate->asoft_info.agpki_apersize >= 4)
2723 rc = 0;
2724 }
2725
2726 if (rc != 0) {
2727 AGPDB_PRINT2((CE_WARN,
2728 "agpgart_open: alloc gart table failed"));
2729 lyr_end(&softstate->asoft_devreg);
2730 mutex_exit(&softstate->asoft_instmutex);
2731 return (EAGAIN);
2732 }
2733
2734 softstate->asoft_pgtotal =
2735 get_max_pages(softstate->asoft_info.agpki_apersize);
2736 /*
2737 * BIOS doesn't initialize GTT for i810,
2738 * So i810 GTT must be created by driver.
2739 *
2740 * Set up gart table and enable it.
2741 */
2742 if (lyr_set_gart_addr(softstate->gart_pbase,
2743 &softstate->asoft_devreg)) {
2744 AGPDB_PRINT2((CE_WARN,
2745 "agpgart_open: set gart table addr failed"));
2746 free_gart_table(softstate);
2747 lyr_end(&softstate->asoft_devreg);
2748 mutex_exit(&softstate->asoft_instmutex);
2749 return (EIO);
2750 }
2751 if (lyr_config_devices(&softstate->asoft_devreg)) {
2752 AGPDB_PRINT2((CE_WARN,
2753 "agpgart_open: lyr_config_devices failed"));
2754 free_gart_table(softstate);
2755 lyr_end(&softstate->asoft_devreg);
2756 mutex_exit(&softstate->asoft_instmutex);
2757 return (EIO);
2758 }
2759
2760 softstate->asoft_opened++;
2761 mutex_exit(&softstate->asoft_instmutex);
2762
2763 return (0);
2764 }
2765
2766 /*
2767 * agpgart_close()
2768 *
2769 * Description:
2770 * agpgart_close will release resources allocated in the first open
2771 * and close other open layered drivers. Also it frees the memory
2772 * allocated by ioctls.
2773 *
2774 * Arguments:
2775 * dev device number
2776 * flag file status flag
2777 * otyp OTYP_BLK, OTYP_CHR
2778 * credp user's credential's struct pointer
2779 *
2780 * Returns:
2781 * ENXIO not an error, to support "deferred attach"
2782 * 0 success
2783 */
2784 /*ARGSUSED*/
2785 static int
agpgart_close(dev_t dev,int flag,int otyp,cred_t * credp)2786 agpgart_close(dev_t dev, int flag, int otyp, cred_t *credp)
2787 {
2788 int instance = AGP_DEV2INST(dev);
2789 agpgart_softstate_t *softstate;
2790 int rc = 0;
2791 uint32_t devid;
2792
2793 softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
2794 if (softstate == NULL) {
2795 AGPDB_PRINT2((CE_WARN, "agpgart_close: get soft state err"));
2796 return (ENXIO);
2797 }
2798
2799 mutex_enter(&softstate->asoft_instmutex);
2800 ASSERT(softstate->asoft_opened);
2801
2802
2803 /*
2804 * If the last process close this device is not the controlling
2805 * process, also release the control over agpgart driver here if the
2806 * the controlling process fails to release the control before it
2807 * close the driver.
2808 */
2809 if (softstate->asoft_acquired == 1) {
2810 AGPDB_PRINT2((CE_WARN,
2811 "agpgart_close: auto release control over driver"));
2812 release_control(softstate);
2813 }
2814
2815 devid = softstate->asoft_info.agpki_mdevid;
2816 if (IS_INTEL_915(devid) ||
2817 IS_INTEL_965(devid) ||
2818 IS_INTEL_X33(devid) ||
2819 IS_INTEL_G4X(devid)) {
2820 rc = ldi_ioctl(softstate->asoft_devreg.agprd_targethdl,
2821 INTEL_CHIPSET_FLUSH_FREE, 0, FKIOCTL, kcred, 0);
2822 }
2823 if (rc) {
2824 AGPDB_PRINT2((CE_WARN,
2825 "agpgart_open: Intel chipset flush free error"));
2826 }
2827
2828 if (lyr_unconfig_devices(&softstate->asoft_devreg)) {
2829 AGPDB_PRINT2((CE_WARN,
2830 "agpgart_close: lyr_unconfig_device error"));
2831 mutex_exit(&softstate->asoft_instmutex);
2832 return (EIO);
2833 }
2834 softstate->asoft_agpen = 0;
2835
2836 if (!IS_INTEL_830(softstate->asoft_devreg.agprd_arctype)) {
2837 free_gart_table(softstate);
2838 }
2839
2840 lyr_end(&softstate->asoft_devreg);
2841
2842 /*
2843 * This statement must be positioned before agp_del_allkeys
2844 * agp_dealloc_mem indirectly called by agp_del_allkeys
2845 * will test this variable.
2846 */
2847 softstate->asoft_opened = 0;
2848
2849 /*
2850 * Free the memory allocated by user applications which
2851 * was never deallocated.
2852 */
2853 (void) agp_del_allkeys(softstate);
2854
2855 mutex_exit(&softstate->asoft_instmutex);
2856
2857 return (0);
2858 }
2859
2860 static int
ioctl_agpgart_info(agpgart_softstate_t * softstate,void * arg,int flags)2861 ioctl_agpgart_info(agpgart_softstate_t *softstate, void *arg, int flags)
2862 {
2863 agp_info_t infostruct;
2864 #ifdef _MULTI_DATAMODEL
2865 agp_info32_t infostruct32;
2866 #endif
2867
2868 bzero(&infostruct, sizeof (agp_info_t));
2869
2870 #ifdef _MULTI_DATAMODEL
2871 bzero(&infostruct32, sizeof (agp_info32_t));
2872 if (ddi_model_convert_from(flags & FMODELS) == DDI_MODEL_ILP32) {
2873 if (copyinfo(softstate, &infostruct))
2874 return (EINVAL);
2875
2876 agpinfo_default_to_32(infostruct, infostruct32);
2877 if (ddi_copyout(&infostruct32, arg,
2878 sizeof (agp_info32_t), flags) != 0)
2879 return (EFAULT);
2880
2881 return (0);
2882 }
2883 #endif /* _MULTI_DATAMODEL */
2884 if (copyinfo(softstate, &infostruct))
2885 return (EINVAL);
2886
2887 if (ddi_copyout(&infostruct, arg, sizeof (agp_info_t), flags) != 0) {
2888 return (EFAULT);
2889 }
2890
2891 return (0);
2892 }
2893
2894 static int
ioctl_agpgart_acquire(agpgart_softstate_t * st)2895 ioctl_agpgart_acquire(agpgart_softstate_t *st)
2896 {
2897 if (st->asoft_acquired) {
2898 AGPDB_PRINT2((CE_WARN, "ioctl_acquire: already acquired"));
2899 return (EBUSY);
2900 }
2901 acquire_control(st);
2902 return (0);
2903 }
2904
2905 static int
ioctl_agpgart_release(agpgart_softstate_t * st)2906 ioctl_agpgart_release(agpgart_softstate_t *st)
2907 {
2908 if (is_controlling_proc(st) < 0) {
2909 AGPDB_PRINT2((CE_WARN,
2910 "ioctl_agpgart_release: not a controlling process"));
2911 return (EPERM);
2912 }
2913 release_control(st);
2914 return (0);
2915 }
2916
2917 static int
ioctl_agpgart_setup(agpgart_softstate_t * st,void * arg,int flags)2918 ioctl_agpgart_setup(agpgart_softstate_t *st, void *arg, int flags)
2919 {
2920 agp_setup_t data;
2921 int rc = 0;
2922
2923 if (is_controlling_proc(st) < 0) {
2924 AGPDB_PRINT2((CE_WARN,
2925 "ioctl_agpgart_setup: not a controlling process"));
2926 return (EPERM);
2927 }
2928
2929 if (!IS_TRUE_AGP(st->asoft_devreg.agprd_arctype)) {
2930 AGPDB_PRINT2((CE_WARN,
2931 "ioctl_agpgart_setup: no true agp bridge"));
2932 return (EINVAL);
2933 }
2934
2935 if (ddi_copyin(arg, &data, sizeof (agp_setup_t), flags) != 0)
2936 return (EFAULT);
2937
2938 if (rc = agp_setup(st, data.agps_mode))
2939 return (rc);
2940 /* Store agp mode status for kstat */
2941 st->asoft_agpen = 1;
2942 return (0);
2943 }
2944
2945 static int
ioctl_agpgart_alloc(agpgart_softstate_t * st,void * arg,int flags)2946 ioctl_agpgart_alloc(agpgart_softstate_t *st, void *arg, int flags)
2947 {
2948 agp_allocate_t alloc_info;
2949 keytable_ent_t *entryp;
2950 size_t length;
2951 uint64_t pg_num;
2952
2953 if (is_controlling_proc(st) < 0) {
2954 AGPDB_PRINT2((CE_WARN,
2955 "ioctl_agpgart_alloc: not a controlling process"));
2956 return (EPERM);
2957 }
2958
2959 if (ddi_copyin(arg, &alloc_info,
2960 sizeof (agp_allocate_t), flags) != 0) {
2961 return (EFAULT);
2962 }
2963 pg_num = st->asoft_pgused + alloc_info.agpa_pgcount;
2964 if (pg_num > st->asoft_pgtotal) {
2965 AGPDB_PRINT2((CE_WARN,
2966 "ioctl_agpgart_alloc: exceeding the memory pages limit"));
2967 AGPDB_PRINT2((CE_WARN,
2968 "ioctl_agpgart_alloc: request %x pages failed",
2969 alloc_info.agpa_pgcount));
2970 AGPDB_PRINT2((CE_WARN,
2971 "ioctl_agpgart_alloc: pages used %x total is %x",
2972 st->asoft_pgused, st->asoft_pgtotal));
2973
2974 return (EINVAL);
2975 }
2976
2977 length = AGP_PAGES2BYTES(alloc_info.agpa_pgcount);
2978 entryp = agp_alloc_mem(st, length, alloc_info.agpa_type);
2979 if (!entryp) {
2980 AGPDB_PRINT2((CE_WARN,
2981 "ioctl_agpgart_alloc: allocate 0x%lx bytes failed",
2982 length));
2983 return (ENOMEM);
2984 }
2985 ASSERT((entryp->kte_key >= 0) && (entryp->kte_key < AGP_MAXKEYS));
2986 alloc_info.agpa_key = entryp->kte_key;
2987 if (alloc_info.agpa_type == AGP_PHYSICAL) {
2988 alloc_info.agpa_physical =
2989 (uint32_t)(entryp->kte_pfnarray[0] << AGP_PAGE_SHIFT);
2990 }
2991 /* Update the memory pagse used */
2992 st->asoft_pgused += alloc_info.agpa_pgcount;
2993
2994 if (ddi_copyout(&alloc_info, arg,
2995 sizeof (agp_allocate_t), flags) != 0) {
2996
2997 return (EFAULT);
2998 }
2999
3000 return (0);
3001 }
3002
3003 static int
ioctl_agpgart_dealloc(agpgart_softstate_t * st,intptr_t arg)3004 ioctl_agpgart_dealloc(agpgart_softstate_t *st, intptr_t arg)
3005 {
3006 int key;
3007 keytable_ent_t *keyent;
3008
3009 if (is_controlling_proc(st) < 0) {
3010 AGPDB_PRINT2((CE_WARN,
3011 "ioctl_agpgart_dealloc: not a controlling process"));
3012 return (EPERM);
3013 }
3014 key = (int)arg;
3015 if ((key >= AGP_MAXKEYS) || key < 0) {
3016 return (EINVAL);
3017 }
3018 keyent = &st->asoft_table[key];
3019 if (!keyent->kte_memhdl) {
3020 return (EINVAL);
3021 }
3022
3023 if (agp_dealloc_mem(st, keyent))
3024 return (EINVAL);
3025
3026 /* Update the memory pages used */
3027 st->asoft_pgused -= keyent->kte_pages;
3028 bzero(keyent, sizeof (keytable_ent_t));
3029
3030 return (0);
3031 }
3032
3033 static int
ioctl_agpgart_bind(agpgart_softstate_t * st,void * arg,int flags)3034 ioctl_agpgart_bind(agpgart_softstate_t *st, void *arg, int flags)
3035 {
3036 agp_bind_t bind_info;
3037 keytable_ent_t *keyent;
3038 int key;
3039 uint32_t pg_offset;
3040 int retval = 0;
3041
3042 if (is_controlling_proc(st) < 0) {
3043 AGPDB_PRINT2((CE_WARN,
3044 "ioctl_agpgart_bind: not a controlling process"));
3045 return (EPERM);
3046 }
3047
3048 if (ddi_copyin(arg, &bind_info, sizeof (agp_bind_t), flags) != 0) {
3049 return (EFAULT);
3050 }
3051
3052 key = bind_info.agpb_key;
3053 if ((key >= AGP_MAXKEYS) || key < 0) {
3054 AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_bind: invalid key"));
3055 return (EINVAL);
3056 }
3057
3058 if (IS_INTEL_830(st->asoft_devreg.agprd_arctype)) {
3059 if (AGP_PAGES2KB(bind_info.agpb_pgstart) <
3060 st->asoft_info.agpki_presize) {
3061 AGPDB_PRINT2((CE_WARN,
3062 "ioctl_agpgart_bind: bind to prealloc area "
3063 "pgstart = %dKB < presize = %ldKB",
3064 AGP_PAGES2KB(bind_info.agpb_pgstart),
3065 st->asoft_info.agpki_presize));
3066 return (EINVAL);
3067 }
3068 }
3069
3070 pg_offset = bind_info.agpb_pgstart;
3071 keyent = &st->asoft_table[key];
3072 if (!keyent->kte_memhdl) {
3073 AGPDB_PRINT2((CE_WARN,
3074 "ioctl_agpgart_bind: Key = 0x%x can't get keyenty",
3075 key));
3076 return (EINVAL);
3077 }
3078
3079 if (keyent->kte_bound != 0) {
3080 AGPDB_PRINT2((CE_WARN,
3081 "ioctl_agpgart_bind: Key = 0x%x already bound",
3082 key));
3083 return (EINVAL);
3084 }
3085 retval = agp_bind_key(st, keyent, pg_offset);
3086
3087 if (retval == 0) {
3088 keyent->kte_pgoff = pg_offset;
3089 keyent->kte_bound = 1;
3090 }
3091
3092 return (retval);
3093 }
3094
3095 static int
ioctl_agpgart_unbind(agpgart_softstate_t * st,void * arg,int flags)3096 ioctl_agpgart_unbind(agpgart_softstate_t *st, void *arg, int flags)
3097 {
3098 int key, retval = 0;
3099 agp_unbind_t unbindinfo;
3100 keytable_ent_t *keyent;
3101
3102 if (is_controlling_proc(st) < 0) {
3103 AGPDB_PRINT2((CE_WARN,
3104 "ioctl_agpgart_bind: not a controlling process"));
3105 return (EPERM);
3106 }
3107
3108 if (ddi_copyin(arg, &unbindinfo, sizeof (unbindinfo), flags) != 0) {
3109 return (EFAULT);
3110 }
3111 key = unbindinfo.agpu_key;
3112 if ((key >= AGP_MAXKEYS) || key < 0) {
3113 AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_unbind: invalid key"));
3114 return (EINVAL);
3115 }
3116 keyent = &st->asoft_table[key];
3117 if (!keyent->kte_bound) {
3118 return (EINVAL);
3119 }
3120
3121 if ((retval = agp_unbind_key(st, keyent)) != 0)
3122 return (retval);
3123
3124 return (0);
3125 }
3126
3127 static int
ioctl_agpgart_flush_chipset(agpgart_softstate_t * st)3128 ioctl_agpgart_flush_chipset(agpgart_softstate_t *st)
3129 {
3130 ldi_handle_t hdl;
3131 uint32_t devid;
3132 int rc = 0;
3133 devid = st->asoft_info.agpki_mdevid;
3134 hdl = st->asoft_devreg.agprd_targethdl;
3135 if (IS_INTEL_915(devid) ||
3136 IS_INTEL_965(devid) ||
3137 IS_INTEL_X33(devid) ||
3138 IS_INTEL_G4X(devid)) {
3139 rc = ldi_ioctl(hdl, INTEL_CHIPSET_FLUSH, 0, FKIOCTL, kcred, 0);
3140 }
3141 return (rc);
3142 }
3143
3144 static int
ioctl_agpgart_pages_bind(agpgart_softstate_t * st,void * arg,int flags)3145 ioctl_agpgart_pages_bind(agpgart_softstate_t *st, void *arg, int flags)
3146 {
3147 agp_bind_pages_t bind_info;
3148 uint32_t pg_offset;
3149 int err = 0;
3150 ldi_handle_t hdl;
3151 uint32_t npages;
3152 igd_gtt_seg_t *gttseg;
3153 uint32_t i;
3154 int rval;
3155 if (ddi_copyin(arg, &bind_info,
3156 sizeof (agp_bind_pages_t), flags) != 0) {
3157 return (EFAULT);
3158 }
3159
3160 gttseg = (igd_gtt_seg_t *)kmem_zalloc(sizeof (igd_gtt_seg_t),
3161 KM_SLEEP);
3162
3163 pg_offset = bind_info.agpb_pgstart;
3164
3165 gttseg->igs_pgstart = pg_offset;
3166 npages = (uint32_t)bind_info.agpb_pgcount;
3167 gttseg->igs_npage = npages;
3168
3169 gttseg->igs_type = AGP_NORMAL;
3170 gttseg->igs_phyaddr = (uint32_t *)kmem_zalloc
3171 (sizeof (uint32_t) * gttseg->igs_npage, KM_SLEEP);
3172
3173 for (i = 0; i < npages; i++) {
3174 gttseg->igs_phyaddr[i] = bind_info.agpb_pages[i] <<
3175 GTT_PAGE_SHIFT;
3176 }
3177
3178 hdl = st->asoft_devreg.agprd_masterhdl;
3179 if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)gttseg, FKIOCTL,
3180 kcred, &rval)) {
3181 AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: start0x%x",
3182 gttseg->igs_pgstart));
3183 AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: pages=0x%x",
3184 gttseg->igs_npage));
3185 AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: type=0x%x",
3186 gttseg->igs_type));
3187 err = -1;
3188 }
3189
3190 list_head_add_new(&st->mapped_list, gttseg);
3191 return (err);
3192 }
3193
3194 static int
ioctl_agpgart_pages_unbind(agpgart_softstate_t * st,void * arg,int flags)3195 ioctl_agpgart_pages_unbind(agpgart_softstate_t *st, void *arg, int flags)
3196 {
3197 agp_unbind_pages_t unbind_info;
3198 int rval;
3199 ldi_handle_t hdl;
3200 igd_gtt_seg_t *gttseg;
3201
3202 if (ddi_copyin(arg, &unbind_info, sizeof (unbind_info), flags) != 0) {
3203 return (EFAULT);
3204 }
3205
3206 struct list_head *entry, *temp;
3207 list_head_for_each_safe(entry, temp, &st->mapped_list) {
3208 if (entry->gttseg->igs_pgstart == unbind_info.agpb_pgstart) {
3209 gttseg = entry->gttseg;
3210 /* not unbind if VT switch */
3211 if (unbind_info.agpb_type) {
3212 list_head_del(entry);
3213 kmem_free(entry, sizeof (*entry));
3214 }
3215 break;
3216 }
3217 }
3218 ASSERT(gttseg != NULL);
3219 gttseg->igs_pgstart = unbind_info.agpb_pgstart;
3220 ASSERT(gttseg->igs_npage == unbind_info.agpb_pgcount);
3221
3222 hdl = st->asoft_devreg.agprd_masterhdl;
3223 if (ldi_ioctl(hdl, I8XX_REM_GTT, (intptr_t)gttseg, FKIOCTL,
3224 kcred, &rval))
3225 return (-1);
3226
3227 if (unbind_info.agpb_type) {
3228 kmem_free(gttseg->igs_phyaddr, sizeof (uint32_t) *
3229 gttseg->igs_npage);
3230 kmem_free(gttseg, sizeof (igd_gtt_seg_t));
3231 }
3232
3233 return (0);
3234 }
3235
3236 static int
ioctl_agpgart_pages_rebind(agpgart_softstate_t * st)3237 ioctl_agpgart_pages_rebind(agpgart_softstate_t *st)
3238 {
3239 int rval;
3240 ldi_handle_t hdl;
3241 igd_gtt_seg_t *gttseg;
3242 int err = 0;
3243
3244 hdl = st->asoft_devreg.agprd_masterhdl;
3245 struct list_head *entry, *temp;
3246 list_head_for_each_safe(entry, temp, &st->mapped_list) {
3247 gttseg = entry->gttseg;
3248 list_head_del(entry);
3249 kmem_free(entry, sizeof (*entry));
3250 if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)gttseg, FKIOCTL,
3251 kcred, &rval)) {
3252 AGPDB_PRINT2((CE_WARN, "agpgart_pages_rebind errori"));
3253 err = -1;
3254 break;
3255 }
3256 kmem_free(gttseg->igs_phyaddr, sizeof (uint32_t) *
3257 gttseg->igs_npage);
3258 kmem_free(gttseg, sizeof (igd_gtt_seg_t));
3259
3260 }
3261 return (err);
3262
3263 }
3264
3265 /*ARGSUSED*/
3266 static int
agpgart_ioctl(dev_t dev,int cmd,intptr_t intarg,int flags,cred_t * credp,int * rvalp)3267 agpgart_ioctl(dev_t dev, int cmd, intptr_t intarg, int flags,
3268 cred_t *credp, int *rvalp)
3269 {
3270 int instance;
3271 int retval = 0;
3272 void *arg = (void*)intarg;
3273
3274 agpgart_softstate_t *softstate;
3275
3276 instance = AGP_DEV2INST(dev);
3277 softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
3278 if (softstate == NULL) {
3279 AGPDB_PRINT2((CE_WARN, "agpgart_ioctl: get soft state err"));
3280 return (ENXIO);
3281 }
3282
3283 mutex_enter(&softstate->asoft_instmutex);
3284
3285 switch (cmd) {
3286 case AGPIOC_INFO:
3287 retval = ioctl_agpgart_info(softstate, arg, flags);
3288 break;
3289 case AGPIOC_ACQUIRE:
3290 retval = ioctl_agpgart_acquire(softstate);
3291 break;
3292 case AGPIOC_RELEASE:
3293 retval = ioctl_agpgart_release(softstate);
3294 break;
3295 case AGPIOC_SETUP:
3296 retval = ioctl_agpgart_setup(softstate, arg, flags);
3297 break;
3298 case AGPIOC_ALLOCATE:
3299 retval = ioctl_agpgart_alloc(softstate, arg, flags);
3300 break;
3301 case AGPIOC_DEALLOCATE:
3302 retval = ioctl_agpgart_dealloc(softstate, intarg);
3303 break;
3304 case AGPIOC_BIND:
3305 retval = ioctl_agpgart_bind(softstate, arg, flags);
3306 break;
3307 case AGPIOC_UNBIND:
3308 retval = ioctl_agpgart_unbind(softstate, arg, flags);
3309 break;
3310 case AGPIOC_FLUSHCHIPSET:
3311 retval = ioctl_agpgart_flush_chipset(softstate);
3312 break;
3313 case AGPIOC_PAGES_BIND:
3314 retval = ioctl_agpgart_pages_bind(softstate, arg, flags);
3315 break;
3316 case AGPIOC_PAGES_UNBIND:
3317 retval = ioctl_agpgart_pages_unbind(softstate, arg, flags);
3318 break;
3319 case AGPIOC_PAGES_REBIND:
3320 retval = ioctl_agpgart_pages_rebind(softstate);
3321 break;
3322 default:
3323 AGPDB_PRINT2((CE_WARN, "agpgart_ioctl: wrong argument"));
3324 retval = ENXIO;
3325 break;
3326 }
3327
3328 mutex_exit(&softstate->asoft_instmutex);
3329 return (retval);
3330 }
3331
3332 static int
agpgart_segmap(dev_t dev,off_t off,struct as * asp,caddr_t * addrp,off_t len,unsigned int prot,unsigned int maxprot,unsigned int flags,cred_t * credp)3333 agpgart_segmap(dev_t dev, off_t off, struct as *asp,
3334 caddr_t *addrp, off_t len, unsigned int prot,
3335 unsigned int maxprot, unsigned int flags, cred_t *credp)
3336 {
3337
3338 struct agpgart_softstate *softstate;
3339 int instance;
3340 int rc = 0;
3341
3342 instance = AGP_DEV2INST(dev);
3343 softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
3344 if (softstate == NULL) {
3345 AGPDB_PRINT2((CE_WARN, "agpgart_segmap: get soft state err"));
3346 return (ENXIO);
3347 }
3348 if (!AGP_ALIGNED(len))
3349 return (EINVAL);
3350
3351 mutex_enter(&softstate->asoft_instmutex);
3352
3353 rc = devmap_setup(dev, (offset_t)off, asp, addrp,
3354 (size_t)len, prot, maxprot, flags, credp);
3355
3356 mutex_exit(&softstate->asoft_instmutex);
3357 return (rc);
3358 }
3359
3360 /*ARGSUSED*/
3361 static int
agpgart_devmap(dev_t dev,devmap_cookie_t cookie,offset_t offset,size_t len,size_t * mappedlen,uint_t model)3362 agpgart_devmap(dev_t dev, devmap_cookie_t cookie, offset_t offset, size_t len,
3363 size_t *mappedlen, uint_t model)
3364 {
3365 struct agpgart_softstate *softstate;
3366 int instance, status;
3367 struct keytable_ent *mementry;
3368 offset_t local_offset;
3369
3370 instance = AGP_DEV2INST(dev);
3371 softstate = ddi_get_soft_state(agpgart_glob_soft_handle, instance);
3372 if (softstate == NULL) {
3373 AGPDB_PRINT2((CE_WARN, "agpgart_devmap: get soft state err"));
3374 return (ENXIO);
3375 }
3376
3377
3378 if (offset > MB2BYTES(softstate->asoft_info.agpki_apersize)) {
3379 AGPDB_PRINT2((CE_WARN, "agpgart_devmap: offset is too large"));
3380 return (EINVAL);
3381 }
3382
3383 /*
3384 * Can not find any memory now, so fail.
3385 */
3386
3387 mementry = agp_find_bound_keyent(softstate, AGP_BYTES2PAGES(offset));
3388
3389 if (mementry == NULL) {
3390 AGPDB_PRINT2((CE_WARN,
3391 "agpgart_devmap: can not find the proper keyent"));
3392 return (EINVAL);
3393 }
3394
3395 local_offset = offset - AGP_PAGES2BYTES(mementry->kte_pgoff);
3396
3397 if (len > (AGP_PAGES2BYTES(mementry->kte_pages) - local_offset)) {
3398 len = AGP_PAGES2BYTES(mementry->kte_pages) - local_offset;
3399 }
3400
3401 switch (mementry->kte_type) {
3402 case AGP_NORMAL:
3403 if (PMEMP(mementry->kte_memhdl)->pmem_cookie) {
3404 status = devmap_pmem_setup(cookie,
3405 softstate->asoft_dip,
3406 &agp_devmap_cb,
3407 PMEMP(mementry->kte_memhdl)->pmem_cookie,
3408 local_offset,
3409 len, PROT_ALL,
3410 (DEVMAP_DEFAULTS|IOMEM_DATA_UC_WR_COMBINE),
3411 &mem_dev_acc_attr);
3412 } else {
3413 AGPDB_PRINT2((CE_WARN,
3414 "agpgart_devmap: not a valid memory type"));
3415 return (EINVAL);
3416
3417 }
3418
3419 break;
3420 default:
3421 AGPDB_PRINT2((CE_WARN,
3422 "agpgart_devmap: not a valid memory type"));
3423 return (EINVAL);
3424 }
3425
3426
3427 if (status == 0) {
3428 *mappedlen = len;
3429 } else {
3430 *mappedlen = 0;
3431 AGPDB_PRINT2((CE_WARN,
3432 "agpgart_devmap: devmap interface failed"));
3433 return (EINVAL);
3434 }
3435
3436 return (0);
3437 }
3438
3439 static struct cb_ops agpgart_cb_ops = {
3440 agpgart_open, /* open() */
3441 agpgart_close, /* close() */
3442 nodev, /* strategy() */
3443 nodev, /* print routine */
3444 nodev, /* no dump routine */
3445 nodev, /* read() */
3446 nodev, /* write() */
3447 agpgart_ioctl, /* agpgart_ioctl */
3448 agpgart_devmap, /* devmap routine */
3449 nodev, /* no longer use mmap routine */
3450 agpgart_segmap, /* system segmap routine */
3451 nochpoll, /* no chpoll routine */
3452 ddi_prop_op, /* system prop operations */
3453 0, /* not a STREAMS driver */
3454 D_DEVMAP | D_MP, /* safe for multi-thread/multi-processor */
3455 CB_REV, /* cb_ops version? */
3456 nodev, /* cb_aread() */
3457 nodev, /* cb_awrite() */
3458 };
3459
3460 static struct dev_ops agpgart_ops = {
3461 DEVO_REV, /* devo_rev */
3462 0, /* devo_refcnt */
3463 agpgart_getinfo, /* devo_getinfo */
3464 nulldev, /* devo_identify */
3465 nulldev, /* devo_probe */
3466 agpgart_attach, /* devo_attach */
3467 agpgart_detach, /* devo_detach */
3468 nodev, /* devo_reset */
3469 &agpgart_cb_ops, /* devo_cb_ops */
3470 (struct bus_ops *)0, /* devo_bus_ops */
3471 NULL, /* devo_power */
3472 ddi_quiesce_not_needed, /* devo_quiesce */
3473 };
3474
3475 static struct modldrv modldrv = {
3476 &mod_driverops,
3477 "AGP driver",
3478 &agpgart_ops,
3479 };
3480
3481 static struct modlinkage modlinkage = {
3482 MODREV_1, /* MODREV_1 is indicated by manual */
3483 {&modldrv, NULL, NULL, NULL}
3484 };
3485
3486 static void *agpgart_glob_soft_handle;
3487
3488 int
_init(void)3489 _init(void)
3490 {
3491 int ret = DDI_SUCCESS;
3492
3493 ret = ddi_soft_state_init(&agpgart_glob_soft_handle,
3494 sizeof (agpgart_softstate_t),
3495 AGPGART_MAX_INSTANCES);
3496
3497 if (ret != 0) {
3498 AGPDB_PRINT2((CE_WARN,
3499 "_init: soft state init error code=0x%x", ret));
3500 return (ret);
3501 }
3502
3503 if ((ret = mod_install(&modlinkage)) != 0) {
3504 AGPDB_PRINT2((CE_WARN,
3505 "_init: mod install error code=0x%x", ret));
3506 ddi_soft_state_fini(&agpgart_glob_soft_handle);
3507 return (ret);
3508 }
3509
3510 return (DDI_SUCCESS);
3511 }
3512
3513 int
_info(struct modinfo * modinfop)3514 _info(struct modinfo *modinfop)
3515 {
3516 return (mod_info(&modlinkage, modinfop));
3517 }
3518
3519 int
_fini(void)3520 _fini(void)
3521 {
3522 int ret;
3523
3524 if ((ret = mod_remove(&modlinkage)) == 0) {
3525 ddi_soft_state_fini(&agpgart_glob_soft_handle);
3526 }
3527
3528 return (ret);
3529 }
3530