diff options
Diffstat (limited to 'usr/src/uts')
-rw-r--r-- | usr/src/uts/common/sys/Makefile | 18 | ||||
-rw-r--r-- | usr/src/uts/common/sys/THIRDPARTYLICENSE.agpgart | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/agp/agpdefs.h | 19 | ||||
-rw-r--r-- | usr/src/uts/common/sys/agp/agpgart_impl.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/sys/agp/agpmaster_io.h | 7 | ||||
-rw-r--r-- | usr/src/uts/common/sys/agp/agptarget_io.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/sys/agpgart.h | 24 | ||||
-rw-r--r-- | usr/src/uts/intel/agpgart/Makefile | 10 | ||||
-rw-r--r-- | usr/src/uts/intel/agpmaster/Makefile | 10 | ||||
-rw-r--r-- | usr/src/uts/intel/agptarget/Makefile | 10 | ||||
-rw-r--r-- | usr/src/uts/intel/amd64_gart/Makefile | 11 | ||||
-rw-r--r-- | usr/src/uts/intel/io/agpgart/agpgart.c | 227 | ||||
-rw-r--r-- | usr/src/uts/intel/io/agpgart/agptarget.c | 97 | ||||
-rw-r--r-- | usr/src/uts/intel/io/agpmaster/agpmaster.c | 127 |
14 files changed, 376 insertions, 188 deletions
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile index 40ba9fb..c43bcf2 100644 --- a/usr/src/uts/common/sys/Makefile +++ b/usr/src/uts/common/sys/Makefile @@ -34,7 +34,15 @@ FILEMODE=644 # unix_bb_info.h: Private interface to kcov # -i386_HDRS= +i386_HDRS= \ + agp/agpamd64gart_io.h \ + agp/agpdefs.h \ + agp/agpgart_impl.h \ + agp/agpmaster_io.h \ + agp/agptarget_io.h \ + agpgart.h \ + gfx_private.h + sparc_HDRS= # Generated headers @@ -49,7 +57,7 @@ HDRS= $(GENHDRS) $(CHKHDRS) # from Makefile.syshdrs ROOTDIR= $(ROOT)/usr/include/sys sparc_ROOTDIRS= -i386_ROOTDIRS= +i386_ROOTDIRS= $(ROOTDIR)/agp sparc_ROOTHDRS= i386_ROOTHDRS= @@ -61,9 +69,15 @@ ROOTHDRS= \ $($(MACH)_HDRS:%=$(ROOTDIR)/%) \ $(HDRS:%=$(ROOTDIR)/%) +agp/%.check: agp/%.h + $(DOT_H_CHECK) + $(ROOTDIR)/%: % $(INS.file) +$(ROOTDIR)/agp/%: agp/% + $(INS.file) + $(ROOTDIRS): $(INS.dir) diff --git a/usr/src/uts/common/sys/THIRDPARTYLICENSE.agpgart b/usr/src/uts/common/sys/THIRDPARTYLICENSE.agpgart index 3bcf0d3..8bf5829 100644 --- a/usr/src/uts/common/sys/THIRDPARTYLICENSE.agpgart +++ b/usr/src/uts/common/sys/THIRDPARTYLICENSE.agpgart @@ -1,4 +1,5 @@ * Copyright (c) 2000 Doug Rabson + * Copyright (c) 2009, Intel Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/usr/src/uts/common/sys/agp/agpdefs.h b/usr/src/uts/common/sys/agp/agpdefs.h index adda870..3d7caa5 100644 --- a/usr/src/uts/common/sys/agp/agpdefs.h +++ b/usr/src/uts/common/sys/agp/agpdefs.h @@ -187,14 +187,16 @@ extern "C" { #define INTEL_IGD_B43 0x2e428086 /* Intel 915 and 945 series */ -#define IS_INTEL_915(device) ((device == INTEL_IGD_915) || \ +#define IS_INTEL_915(device) ( \ + (device == INTEL_IGD_915) || \ (device == INTEL_IGD_915GM) || \ (device == INTEL_IGD_945) || \ (device == INTEL_IGD_945GM) || \ (device == INTEL_IGD_945GME)) /* Intel 965 series */ -#define IS_INTEL_965(device) ((device == INTEL_IGD_946GZ) || \ +#define IS_INTEL_965(device) ( \ + (device == INTEL_IGD_946GZ) || \ (device == INTEL_IGD_965G1) || \ (device == INTEL_IGD_965Q) || \ (device == INTEL_IGD_965G2) || \ @@ -204,20 +206,23 @@ extern "C" { IS_INTEL_G4X(device)) /* Intel G33 series */ -#define IS_INTEL_X33(device) ((device == INTEL_IGD_Q35) || \ +#define IS_INTEL_X33(device) ( \ + (device == INTEL_IGD_Q35) || \ (device == INTEL_IGD_G33) || \ (device == INTEL_IGD_Q33)) /* IGDNG */ -#define IS_IGDNG(device) ((device == INTEL_IGD_IGDNG_D) || \ - (device == INTEL_IGD_IGDNG_M)) +#define IS_INTEL_IGDNG(device) ( \ + (device == INTEL_IGD_IGDNG_D) || \ + (device == INTEL_IGD_IGDNG_M)) /* Intel G4X series */ -#define IS_INTEL_G4X(device) ((device == INTEL_IGD_EL) || \ +#define IS_INTEL_G4X(device) ( \ + (device == INTEL_IGD_EL) || \ (device == INTEL_IGD_Q45) || \ (device == INTEL_IGD_G45) || \ (device == INTEL_IGD_G41) || \ - IS_IGDNG(device) || \ + IS_INTEL_IGDNG(device) || \ (device == INTEL_IGD_B43)) /* register offsets in PCI config space */ diff --git a/usr/src/uts/common/sys/agp/agpgart_impl.h b/usr/src/uts/common/sys/agp/agpgart_impl.h index a8f5b6b..5c93eb7 100644 --- a/usr/src/uts/common/sys/agp/agpgart_impl.h +++ b/usr/src/uts/common/sys/agp/agpgart_impl.h @@ -156,7 +156,6 @@ typedef struct agpgart_softstate { /* all registered agp device in here */ agp_registered_dev_t asoft_devreg; kstat_t *asoft_ksp; - struct list_head mapped_list; } agpgart_softstate_t; typedef struct agpgart_ctx { diff --git a/usr/src/uts/common/sys/agp/agpmaster_io.h b/usr/src/uts/common/sys/agp/agpmaster_io.h index 1202e76..e492fae 100644 --- a/usr/src/uts/common/sys/agp/agpmaster_io.h +++ b/usr/src/uts/common/sys/agp/agpmaster_io.h @@ -48,16 +48,21 @@ extern "C" { #define I810_SET_GTT_BASE _IOW(AGPMASTERIOC_BASE, 12, uint32_t) #define I8XX_ADD2GTT _IOW(AGPMASTERIOC_BASE, 13, igd_gtt_seg_t) #define I8XX_REM_GTT _IOW(AGPMASTERIOC_BASE, 14, igd_gtt_seg_t) +#define I8XX_RW_GTT _IOW(AGPMASTERIOC_BASE, 15, igd_gtt_seg_t) #define I8XX_UNCONFIG _IO(AGPMASTERIOC_BASE, 16) #define AGP_MASTER_GETINFO _IOR(AGPMASTERIOC_BASE, 20, agp_info_t) #define AGP_MASTER_SETCMD _IOW(AGPMASTERIOC_BASE, 21, uint32_t) -/* used for IGD to bind/unbind gtt entries */ +/* + * used for IGD to bind/unbind gtt entries, and RW_GTT + */ typedef struct igd_gtt_seg { uint32_t igs_pgstart; uint32_t igs_npage; uint32_t *igs_phyaddr; /* pointer to address array */ uint32_t igs_type; /* reserved for other memory type */ + uint32_t igs_flags; + uint32_t igs_scratch; } igd_gtt_seg_t; /* used for IGD to get info */ diff --git a/usr/src/uts/common/sys/agp/agptarget_io.h b/usr/src/uts/common/sys/agp/agptarget_io.h index 316e2ab..c68e3d7 100644 --- a/usr/src/uts/common/sys/agp/agptarget_io.h +++ b/usr/src/uts/common/sys/agp/agptarget_io.h @@ -28,6 +28,8 @@ extern "C" { #define INTEL_CHIPSET_FLUSH_SETUP _IO(AGPTARGETIOC_BASE, 38) #define INTEL_CHIPSET_FLUSH _IO(AGPTARGETIOC_BASE, 39) #define INTEL_CHIPSET_FLUSH_FREE _IO(AGPTARGETIOC_BASE, 40) +#define AGP_TARGET_PCICONFIG_GET16 _IOWR(AGPTARGETIOC_BASE, 41, uint16_t) +#define AGP_TARGET_PCICONFIG_SET16 _IOW(AGPTARGETIOC_BASE, 42, uint32_t) /* Internal agp info struct */ typedef struct _i_agp_info { diff --git a/usr/src/uts/common/sys/agpgart.h b/usr/src/uts/common/sys/agpgart.h index c8770ae..cf25bf0 100644 --- a/usr/src/uts/common/sys/agpgart.h +++ b/usr/src/uts/common/sys/agpgart.h @@ -70,14 +70,16 @@ typedef struct _agp_allocate { typedef struct _agp_bind_pages { uint32_t agpb_pgstart; + uint32_t agpb_pgcount; pfn_t *agpb_pages; - unsigned long agpb_pgcount; + uint32_t agpb_type; /* AGP_USER_MEMORY */ } agp_bind_pages_t; typedef struct _agp_unbind_pages { - uint32_t agpb_pgstart; - unsigned long agpb_pgcount; - uint32_t agpb_type; + uint32_t agpu_pgstart; + uint32_t agpu_pgcount; + pfn_t agpu_scratch; + uint32_t agpu_flags; } agp_unbind_pages_t; typedef struct _agp_bind { @@ -90,6 +92,13 @@ typedef struct _agp_unbind { uint32_t agpu_pri; /* no use in solaris */ } agp_unbind_t; +typedef struct _agp_rw_gtt { + uint32_t agprw_pgstart; + uint32_t agprw_pgcount; + void *agprw_addr; /* buffer */ + uint32_t agprw_flags; /* 0:read, 1:write */ +} agp_rw_gtt_t; + #define AGPIOC_BASE 'G' #define AGPIOC_INFO _IOR(AGPIOC_BASE, 0, 100) #define AGPIOC_ACQUIRE _IO(AGPIOC_BASE, 1) @@ -106,7 +115,12 @@ typedef struct _agp_unbind { #define AGPIOC_FLUSHCHIPSET _IO(AGPIOC_BASE, 12) #define AGPIOC_PAGES_BIND _IOW(AGPIOC_BASE, 13, agp_bind_pages_t) #define AGPIOC_PAGES_UNBIND _IOW(AGPIOC_BASE, 14, agp_unbind_pages_t) -#define AGPIOC_PAGES_REBIND _IO(AGPIOC_BASE, 15) +#define AGPIOC_RW_GTT _IOW(AGPIOC_BASE, 15, agp_rw_gtt_t) + +/* AGP bind pages type values */ +#define AGP_USER_TYPES (1 << 16) +#define AGP_USER_MEMORY (AGP_USER_TYPES) +#define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1) /* AGP status register bits definition */ #define AGPSTAT_RQ_MASK 0xff000000 /* target only */ diff --git a/usr/src/uts/intel/agpgart/Makefile b/usr/src/uts/intel/agpgart/Makefile index e80b1db..eb0c20d 100644 --- a/usr/src/uts/intel/agpgart/Makefile +++ b/usr/src/uts/intel/agpgart/Makefile @@ -27,6 +27,7 @@ CONF_SRCDIR = $(UTSBASE)/intel/io/agpgart # Include common rules. # include $(UTSBASE)/intel/Makefile.intel +AGPGART_OBJS += agpgart.o agp_kstat.o # # Define targets @@ -35,9 +36,7 @@ ALL_TARGET = $(BINARY) $(SRC_CONFILE) LINT_TARGET = $(MODULE).lint INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) -CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-parentheses -CERRWARN += -_gcc=-Wno-uninitialized # # For now, disable these lint checks; maintainers should endeavor @@ -67,6 +66,13 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/agpgart/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/agpgart/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + # # Include common targets. # diff --git a/usr/src/uts/intel/agpmaster/Makefile b/usr/src/uts/intel/agpmaster/Makefile index c6a25d3..826608b 100644 --- a/usr/src/uts/intel/agpmaster/Makefile +++ b/usr/src/uts/intel/agpmaster/Makefile @@ -24,7 +24,7 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" + # # This makefile drives the production of the common graphics # interface kernel module. @@ -55,6 +55,7 @@ LDFLAGS += -dy -Nmisc/pci_autoconfig # Include common rules. # include $(UTSBASE)/intel/Makefile.intel +AGP_OBJS += agpmaster.o # # Define targets @@ -91,6 +92,13 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/agpmaster/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/agpmaster/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + # # Include common targets. # diff --git a/usr/src/uts/intel/agptarget/Makefile b/usr/src/uts/intel/agptarget/Makefile index 8cf479a..74bda0e 100644 --- a/usr/src/uts/intel/agptarget/Makefile +++ b/usr/src/uts/intel/agptarget/Makefile @@ -30,8 +30,7 @@ LDFLAGS += -dy -Nmisc/busra # Include common rules. # include $(UTSBASE)/intel/Makefile.intel - -CERRWARN += -_gcc=-Wno-uninitialized +AGPTARGET_OBJS += agptarget.o # # Define targets @@ -61,6 +60,13 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/agpgart/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/agpgart/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + # # Include common targets. # diff --git a/usr/src/uts/intel/amd64_gart/Makefile b/usr/src/uts/intel/amd64_gart/Makefile index f2a2200..9aa5df8 100644 --- a/usr/src/uts/intel/amd64_gart/Makefile +++ b/usr/src/uts/intel/amd64_gart/Makefile @@ -4,8 +4,7 @@ # # uts/intel/amd64_gart/Makefile # -# -#ident "%Z%%M% %I% %E% SMI" + # # This makefile drives the framework of agp protocol # (amd64_gart) kernel module. @@ -27,6 +26,7 @@ ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) # Include common rules. # include $(UTSBASE)/intel/Makefile.intel +AMD64GART_OBJS += amd64_gart.o # # Define targets @@ -56,6 +56,13 @@ clean.lint: $(CLEAN_LINT_DEPS) install: $(INSTALL_DEPS) +$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/agpgart/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +$(LINTS_DIR)/%.ln: $(UTSBASE)/intel/io/agpgart/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + # # Include common targets. # diff --git a/usr/src/uts/intel/io/agpgart/agpgart.c b/usr/src/uts/intel/io/agpgart/agpgart.c index 7df0518..34f5ca5 100644 --- a/usr/src/uts/intel/io/agpgart/agpgart.c +++ b/usr/src/uts/intel/io/agpgart/agpgart.c @@ -64,52 +64,6 @@ static void *agpgart_glob_soft_handle; #define IS_TRUE_AGP(type) (((type) == ARC_INTELAGP) || \ ((type) == ARC_AMD64AGP)) -#define AGP_HASH_NODE 1024 - -static void -list_head_init(struct list_head *head) { - struct list_head *entry, *tmp; - /* HASH for accelerate */ - entry = kmem_zalloc(AGP_HASH_NODE * - sizeof (struct list_head), KM_SLEEP); - head->next = entry; - for (int i = 0; i < AGP_HASH_NODE; i++) { - tmp = &entry[i]; - tmp->next = tmp; - tmp->prev = tmp; - tmp->gttseg = NULL; - } -} - -static void -list_head_add_new(struct list_head *head, - igd_gtt_seg_t *gttseg) -{ - struct list_head *entry, *tmp; - int key; - entry = kmem_zalloc(sizeof (*entry), KM_SLEEP); - key = gttseg->igs_pgstart % AGP_HASH_NODE; - tmp = &head->next[key]; - tmp->next->prev = entry; - entry->next = tmp->next; - entry->prev = tmp; - tmp->next = entry; - entry->gttseg = gttseg; -} - -static void -list_head_del(struct list_head *entry) { - (entry)->next->prev = (entry)->prev; \ - (entry)->prev->next = (entry)->next; \ - (entry)->gttseg = NULL; \ -} - -#define list_head_for_each_safe(entry, temp, head) \ - for (int key = 0; key < AGP_HASH_NODE; key++) \ - for (entry = (&(head)->next[key])->next, temp = (entry)->next; \ - entry != &(head)->next[key]; \ - entry = temp, temp = temp->next) - #define agpinfo_default_to_32(v, v32) \ { \ @@ -1472,6 +1426,9 @@ agp_unbind_key(agpgart_softstate_t *softstate, keytable_ent_t *entryp) lyr_flush_gart_cache(&softstate->asoft_devreg); break; + default: + /* Never happens, but avoid gcc switch warning. */ + return (EIO); } entryp->kte_bound = 0; @@ -2494,8 +2451,6 @@ agpgart_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) AGP_MAXKEYS * (sizeof (keytable_ent_t)), KM_SLEEP); - list_head_init(&softstate->mapped_list); - return (DDI_SUCCESS); err4: agp_fini_kstats(softstate); @@ -2542,21 +2497,6 @@ agpgart_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) st->asoft_table = 0; } - struct list_head *entry, *temp, *head; - igd_gtt_seg_t *gttseg; - list_head_for_each_safe(entry, temp, &st->mapped_list) { - gttseg = entry->gttseg; - list_head_del(entry); - kmem_free(entry, sizeof (*entry)); - kmem_free(gttseg->igs_phyaddr, - sizeof (uint32_t) * gttseg->igs_npage); - kmem_free(gttseg, sizeof (igd_gtt_seg_t)); - } - head = &st->mapped_list; - kmem_free(head->next, - AGP_HASH_NODE * sizeof (struct list_head)); - head->next = NULL; - ddi_remove_minor_node(dip, AGPGART_DEVNODE); agp_fini_kstats(st); ldi_ident_release(st->asoft_li); @@ -3144,122 +3084,124 @@ ioctl_agpgart_flush_chipset(agpgart_softstate_t *st) static int ioctl_agpgart_pages_bind(agpgart_softstate_t *st, void *arg, int flags) { - agp_bind_pages_t bind_info; - uint32_t pg_offset; - int err = 0; - ldi_handle_t hdl; - uint32_t npages; - igd_gtt_seg_t *gttseg; - uint32_t i; - int rval; - if (ddi_copyin(arg, &bind_info, - sizeof (agp_bind_pages_t), flags) != 0) { + agp_bind_pages_t bind_info; + igd_gtt_seg_t gttseg; + size_t array_size; + ulong_t paddr; + uint32_t igs_type; + ldi_handle_t hdl; + int i, rval; + int rc = 0; + + if (ddi_copyin(arg, &bind_info, sizeof (bind_info), flags) != 0) { return (EFAULT); } - gttseg = (igd_gtt_seg_t *)kmem_zalloc(sizeof (igd_gtt_seg_t), - KM_SLEEP); - - pg_offset = bind_info.agpb_pgstart; + /* + * Convert agp_type to something the igs layer understands. + */ + switch (bind_info.agpb_type) { + case AGP_USER_MEMORY: + case AGP_USER_CACHED_MEMORY: /* Todo */ + igs_type = AGP_NORMAL; + break; + default: + return (EINVAL); + } - gttseg->igs_pgstart = pg_offset; - npages = (uint32_t)bind_info.agpb_pgcount; - gttseg->igs_npage = npages; + if (bind_info.agpb_pgcount == 0) + return (0); - gttseg->igs_type = AGP_NORMAL; - gttseg->igs_phyaddr = (uint32_t *)kmem_zalloc - (sizeof (uint32_t) * gttseg->igs_npage, KM_SLEEP); + gttseg.igs_pgstart = bind_info.agpb_pgstart; + gttseg.igs_npage = bind_info.agpb_pgcount; - for (i = 0; i < npages; i++) { - gttseg->igs_phyaddr[i] = bind_info.agpb_pages[i] << - GTT_PAGE_SHIFT; + array_size = bind_info.agpb_pgcount * sizeof (uint32_t); + gttseg.igs_phyaddr = kmem_zalloc(array_size, KM_SLEEP); + if (bind_info.agpb_pages != NULL) { + for (i = 0; i < bind_info.agpb_pgcount; i++) { + paddr = bind_info.agpb_pages[i] << GTT_PAGE_SHIFT; + gttseg.igs_phyaddr[i] = (uint32_t)paddr; + } } + gttseg.igs_type = igs_type; + gttseg.igs_flags = 0; /* not used */ + gttseg.igs_scratch = 0; /* not used */ + + /* See i8xx_add_to_gtt */ hdl = st->asoft_devreg.agprd_masterhdl; - if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)gttseg, FKIOCTL, + if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)>tseg, FKIOCTL, kcred, &rval)) { - AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: start0x%x", - gttseg->igs_pgstart)); - AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: pages=0x%x", - gttseg->igs_npage)); - AGPDB_PRINT2((CE_WARN, "ioctl_agpgart_pages_bind: type=0x%x", - gttseg->igs_type)); - err = -1; + rc = -1; } - list_head_add_new(&st->mapped_list, gttseg); - return (err); + kmem_free(gttseg.igs_phyaddr, array_size); + + return (rc); } static int ioctl_agpgart_pages_unbind(agpgart_softstate_t *st, void *arg, int flags) { agp_unbind_pages_t unbind_info; - int rval; + igd_gtt_seg_t gttseg; ldi_handle_t hdl; - igd_gtt_seg_t *gttseg; + int rval; if (ddi_copyin(arg, &unbind_info, sizeof (unbind_info), flags) != 0) { return (EFAULT); } - struct list_head *entry, *temp; - list_head_for_each_safe(entry, temp, &st->mapped_list) { - if (entry->gttseg->igs_pgstart == unbind_info.agpb_pgstart) { - gttseg = entry->gttseg; - /* not unbind if VT switch */ - if (unbind_info.agpb_type) { - list_head_del(entry); - kmem_free(entry, sizeof (*entry)); - } - break; - } - } - ASSERT(gttseg != NULL); - gttseg->igs_pgstart = unbind_info.agpb_pgstart; - ASSERT(gttseg->igs_npage == unbind_info.agpb_pgcount); + gttseg.igs_pgstart = unbind_info.agpu_pgstart; + gttseg.igs_npage = unbind_info.agpu_pgcount; + gttseg.igs_phyaddr = NULL; /* not used */ + gttseg.igs_type = AGP_NORMAL; + gttseg.igs_flags = unbind_info.agpu_flags; + gttseg.igs_scratch = (uint32_t) unbind_info.agpu_scratch; + /* See i8xx_remove_from_gtt */ hdl = st->asoft_devreg.agprd_masterhdl; - if (ldi_ioctl(hdl, I8XX_REM_GTT, (intptr_t)gttseg, FKIOCTL, + if (ldi_ioctl(hdl, I8XX_REM_GTT, (intptr_t)>tseg, FKIOCTL, kcred, &rval)) return (-1); - if (unbind_info.agpb_type) { - kmem_free(gttseg->igs_phyaddr, sizeof (uint32_t) * - gttseg->igs_npage); - kmem_free(gttseg, sizeof (igd_gtt_seg_t)); - } - return (0); } +/* + * Read or write GTT registers. In the DRM code, see: + * i915_gem_gtt.c:intel_rw_gtt + * + * Used to save/restore GTT state. + */ static int -ioctl_agpgart_pages_rebind(agpgart_softstate_t *st) +ioctl_agpgart_rw_gtt(agpgart_softstate_t *st, void *arg, int flags) { - int rval; + agp_rw_gtt_t rw_info; + igd_gtt_seg_t gttseg; ldi_handle_t hdl; - igd_gtt_seg_t *gttseg; - int err = 0; + int rval; - hdl = st->asoft_devreg.agprd_masterhdl; - struct list_head *entry, *temp; - list_head_for_each_safe(entry, temp, &st->mapped_list) { - gttseg = entry->gttseg; - list_head_del(entry); - kmem_free(entry, sizeof (*entry)); - if (ldi_ioctl(hdl, I8XX_ADD2GTT, (intptr_t)gttseg, FKIOCTL, - kcred, &rval)) { - AGPDB_PRINT2((CE_WARN, "agpgart_pages_rebind errori")); - err = -1; - break; - } - kmem_free(gttseg->igs_phyaddr, sizeof (uint32_t) * - gttseg->igs_npage); - kmem_free(gttseg, sizeof (igd_gtt_seg_t)); + if (ddi_copyin(arg, &rw_info, sizeof (rw_info), flags) != 0) { + return (EFAULT); + } + + gttseg.igs_pgstart = rw_info.agprw_pgstart; + gttseg.igs_npage = rw_info.agprw_pgcount; + gttseg.igs_phyaddr = rw_info.agprw_addr; + gttseg.igs_type = 0; /* not used */ + gttseg.igs_flags = rw_info.agprw_flags; + gttseg.igs_scratch = 0; /* not used */ + /* See: i8xx_read_gtt, i8xx_write_gtt */ + hdl = st->asoft_devreg.agprd_masterhdl; + if (ldi_ioctl(hdl, I8XX_RW_GTT, (intptr_t)>tseg, FKIOCTL, + kcred, &rval)) { + AGPDB_PRINT2((CE_WARN, "agpgart_rw_gtt error")); + return (-1); } - return (err); + return (0); } /*ARGSUSED*/ @@ -3316,9 +3258,10 @@ agpgart_ioctl(dev_t dev, int cmd, intptr_t intarg, int flags, case AGPIOC_PAGES_UNBIND: retval = ioctl_agpgart_pages_unbind(softstate, arg, flags); break; - case AGPIOC_PAGES_REBIND: - retval = ioctl_agpgart_pages_rebind(softstate); + case AGPIOC_RW_GTT: + retval = ioctl_agpgart_rw_gtt(softstate, arg, flags); break; + default: AGPDB_PRINT2((CE_WARN, "agpgart_ioctl: wrong argument")); retval = ENXIO; diff --git a/usr/src/uts/intel/io/agpgart/agptarget.c b/usr/src/uts/intel/io/agpgart/agptarget.c index d1366d6..5c19a7c 100644 --- a/usr/src/uts/intel/io/agpgart/agptarget.c +++ b/usr/src/uts/intel/io/agpgart/agptarget.c @@ -176,7 +176,7 @@ agp_target_cap_find(ddi_acc_handle_t pci_handle) static uint64_t agp_target_get_apbase(agp_target_softstate_t *softstate) { - uint64_t aper_base; + uint64_t aper_base = 0; if (is_intel_br(softstate)) { aper_base = pci_config_get32(softstate->tsoft_pcihdl, @@ -224,6 +224,12 @@ agp_target_get_apsize(agp_target_softstate_t *softstate) } else if (is_64bit_aper(softstate)) { value = pci_config_get16(softstate->tsoft_pcihdl, cap + AGP_CONF_APERSIZE); + } else { + /* + * Never happens, but avoid gcc warnings re. + * value used uninitialized. + */ + return (0); } if (value & AGP_APER_128M_MASK) { @@ -400,7 +406,13 @@ static gms_mode_t gms_modes[] = { GMS_SIZE(gms_G4X), gms_G4X}, {INTEL_BR_B43, I8XX_CONF_GC, I8XX_GC_MODE_MASK, GMS_SIZE(gms_G4X), gms_G4X} + /* + * Note: This module is not used for Intel Gen6 or later + * devices (Sandy Bridge etc.) so no need to add any + * PCI IDs here for those devices. + */ }; + static int get_chip_gms(uint32_t devid) { @@ -411,10 +423,10 @@ get_chip_gms(uint32_t devid) for (i = 0; i < num_modes; i++) { if (gms_modes[i].gm_devid == devid) - break; + return (i); } - return ((i == num_modes) ? -1 : i); + return (-1); } /* Returns the size (kbytes) of pre-allocated graphics memory */ @@ -557,8 +569,8 @@ agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) PCI_CONF_VENID); softstate->tsoft_gms_off = get_chip_gms(softstate->tsoft_devid); if (softstate->tsoft_gms_off < 0) { - TARGETDB_PRINT2((CE_WARN, "agp_target_attach:" - "read gms offset failed")); + TARGETDB_PRINT2((CE_WARN, "agp_target_attach: " + "unknown bridge ID 0x%x", softstate->tsoft_devid)); pci_config_teardown(&softstate->tsoft_pcihdl); ddi_soft_state_free(agptarget_glob_soft_handle, instance); @@ -627,6 +639,7 @@ agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, int *rval) { int instance = DEV2INST(dev); + int ret = 0; agp_target_softstate_t *st; static char kernel_only[] = "amd64_gart_ioctl: is a kernel only ioctl"; @@ -657,8 +670,8 @@ agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, } if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) { - mutex_exit(&st->tsoft_lock); - return (EFAULT); + ret = EFAULT; + break; } break; @@ -668,15 +681,15 @@ agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, size_t prealloc_size; if (!is_intel_br(st)) { - mutex_exit(&st->tsoft_lock); - return (EINVAL); + ret = EINVAL; + break; } prealloc_size = i8xx_biosmem_detect(st); if (ddi_copyout(&prealloc_size, (void *)data, sizeof (size_t), mode)) { - mutex_exit(&st->tsoft_lock); - return (EFAULT); + ret = EFAULT; + break; } break; @@ -701,8 +714,8 @@ agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, if (ddi_copyout(&info, (void *)data, sizeof (i_agp_info_t), mode)) { - mutex_exit(&st->tsoft_lock); - return (EFAULT); + ret = EFAULT; + break; } break; @@ -721,8 +734,8 @@ agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, if (ddi_copyin((void *)data, &gartaddr, sizeof (uint32_t), mode)) { - mutex_exit(&st->tsoft_lock); - return (EFAULT); + ret = EFAULT; + break; } agp_target_set_gartaddr(st, gartaddr); @@ -734,8 +747,8 @@ agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, if (ddi_copyin((void *)data, &command, sizeof (uint32_t), mode)) { - mutex_exit(&st->tsoft_lock); - return (EFAULT); + ret = EFAULT; + break; } ASSERT(st->tsoft_acaptr); @@ -822,14 +835,58 @@ agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode, case INTEL_CHIPSET_FLUSH: case INTEL_CHIPSET_FLUSH_FREE: break; + + /* See i915_bridge_dev_read_config_word */ + case AGP_TARGET_PCICONFIG_GET16: + { + uint16_t offset, value; + + if (ddi_copyin( + (void *)data, &offset, sizeof (uint16_t), mode)) { + ret = EFAULT; + break; + } + + value = pci_config_get16(st->tsoft_pcihdl, offset); + + if (ddi_copyout( + &value, (void *)data, sizeof (uint16_t), mode)) { + ret = EFAULT; + break; + } + + break; + } + + /* + * See i915_bridge_dev_write_config_word + * Offset + value come in as 32 bits: + * data = (offset << 16) | value; + */ + case AGP_TARGET_PCICONFIG_SET16: + { + uint32_t off_val; + uint16_t offset, value; + + if (ddi_copyin((void *)data, &off_val, + sizeof (off_val), mode)) { + ret = EFAULT; + break; + } + offset = (off_val >> 16) & 0xffff; + value = off_val & 0xffff; + pci_config_put16(st->tsoft_pcihdl, offset, value); + break; + } + default: - mutex_exit(&st->tsoft_lock); - return (ENXIO); + ret = ENXIO; + break; } /* end switch */ mutex_exit(&st->tsoft_lock); - return (0); + return (ret); } /*ARGSUSED*/ diff --git a/usr/src/uts/intel/io/agpmaster/agpmaster.c b/usr/src/uts/intel/io/agpmaster/agpmaster.c index 7a4de1e..a67094e 100644 --- a/usr/src/uts/intel/io/agpmaster/agpmaster.c +++ b/usr/src/uts/intel/io/agpmaster/agpmaster.c @@ -111,6 +111,8 @@ static int detect_i8xx_device(agp_master_softc_t *); static int detect_agp_devcice(agp_master_softc_t *, ddi_acc_handle_t); static int i8xx_add_to_gtt(gtt_impl_t *, igd_gtt_seg_t); static void i8xx_remove_from_gtt(gtt_impl_t *, igd_gtt_seg_t); +static int i8xx_read_gtt(gtt_impl_t *, igd_gtt_seg_t); +static int i8xx_write_gtt(gtt_impl_t *, igd_gtt_seg_t); int _init(void) @@ -439,6 +441,7 @@ agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, (void *)data, sizeof (int), mode)) return (EFAULT); break; + case AGP_MASTER_SETCMD: if (!(mode & FKIOCTL)) { AGPM_DEBUG((CE_CONT, kernel_only, "AGP_MASTER_SETCMD")); @@ -456,6 +459,7 @@ agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, softc->agpm_data.agpm_acaptr + AGP_CONF_COMMAND, command); break; + case AGP_MASTER_GETINFO: if (!(mode & FKIOCTL)) { AGPM_DEBUG((CE_CONT, kernel_only, @@ -478,6 +482,7 @@ agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, sizeof (agp_info_t), mode)) return (EFAULT); break; + case I810_SET_GTT_BASE: if (!(mode & FKIOCTL)) { AGPM_DEBUG((CE_CONT, kernel_only, "I810_SET_GTT_ADDR")); @@ -494,6 +499,7 @@ agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, AGPM_WRITE(softc, PGTBL_CTL, addr); break; + case I8XX_GET_INFO: if (!(mode & FKIOCTL)) { AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_GET_INFO")); @@ -506,6 +512,7 @@ agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, (void *)data, sizeof (igd_info_t), mode)) return (EFAULT); break; + case I8XX_ADD2GTT: if (!(mode & FKIOCTL)) { AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_ADD2GTT")); @@ -521,6 +528,7 @@ agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, if (i8xx_add_to_gtt(&softc->agpm_data.agpm_gtt, seg)) return (EINVAL); break; + case I8XX_REM_GTT: if (!(mode & FKIOCTL)) { AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_REM_GTT")); @@ -535,6 +543,33 @@ agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred, i8xx_remove_from_gtt(&softc->agpm_data.agpm_gtt, seg); break; + + case I8XX_RW_GTT: + if (!(mode & FKIOCTL)) { + AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_RW_GTT")); + return (ENXIO); + } + + CONFIRM(IS_IGD(softc)); + + if (ddi_copyin((void *)data, &seg, + sizeof (igd_gtt_seg_t), mode)) + return (EFAULT); + + /* + * Read or write based on flags set in + * ioctl_agpgart_rw_gtt() + * Used to save/restore GTT state. + */ + if (seg.igs_flags == 0) { + if (i8xx_read_gtt(&softc->agpm_data.agpm_gtt, seg)) + return (EINVAL); + } else { + if (i8xx_write_gtt(&softc->agpm_data.agpm_gtt, seg)) + return (EINVAL); + } + break; + case I8XX_UNCONFIG: if (!(mode & FKIOCTL)) { AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_UNCONFIG")); @@ -629,9 +664,16 @@ detect_i8xx_device(agp_master_softc_t *master_softc) case INTEL_IGD_IGDNG_D: case INTEL_IGD_IGDNG_M: case INTEL_IGD_B43: + /* + * Note: This module is not used for Intel Gen6 or later + * devices (Sandy Bridge etc.) so no need to add any + * PCI IDs here for those devices. + */ master_softc->agpm_dev_type = DEVICE_IS_I830; break; default: /* unknown id */ + AGPM_DEBUG((CE_CONT, "unknown i8xx_device 0x%x", + master_softc->agpm_id)); return (-1); } @@ -674,6 +716,7 @@ phys2entry(uint32_t type, uint32_t physaddr, uint32_t *entry) value = (physaddr & GTT_PTE_MASK) | GTT_PTE_VALID; break; default: + AGPM_DEBUG((CE_WARN, "phys2entry type %d", type)); return (-1); } @@ -693,12 +736,14 @@ i8xx_add_to_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg) maxpages = gtt->gtt_info.igd_apersize; maxpages = GTT_MB_TO_PAGES(maxpages); - paddr = seg.igs_phyaddr; - /* check if gtt max page number is reached */ if ((seg.igs_pgstart + seg.igs_npage) > maxpages) return (-1); + /* + * Note: Caller supplies a gtt address from which we + * extract a uint32_t gtt_pte_t to set in the GTT. + */ paddr = seg.igs_phyaddr; for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); i++, paddr++) { @@ -717,16 +762,92 @@ i8xx_remove_from_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg) { int i; uint32_t maxpages; + uint32_t entry; maxpages = gtt->gtt_info.igd_apersize; maxpages = GTT_MB_TO_PAGES(maxpages); + /* + * If non-zero, seg.igs_scratch is the pfn_t for a + * "scratch" page to use instead of zero. + */ + if (seg.igs_scratch == 0 || + phys2entry(seg.igs_type, seg.igs_scratch, &entry) != 0) { + entry = 0; + } + /* check if gtt max page number is reached */ if ((seg.igs_pgstart + seg.igs_npage) > maxpages) return; for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); i++) { ddi_put32(gtt->gtt_handle, - (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)), 0); + (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)), + entry); } } + +/* + * Low-level read GTT + */ +static int +i8xx_read_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg) +{ + int i; + uint32_t *paddr; + uint32_t maxpages; + + maxpages = gtt->gtt_info.igd_apersize; + maxpages = GTT_MB_TO_PAGES(maxpages); + + /* Buffer into which we'll read. */ + paddr = seg.igs_phyaddr; + if (paddr == NULL) + return (-1); + + /* check if gtt max page number is reached */ + if ((seg.igs_pgstart + seg.igs_npage) > maxpages) + return (-1); + + paddr = seg.igs_phyaddr; + for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); + i++, paddr++) { + *paddr = ddi_get32(gtt->gtt_handle, + (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t))); + } + + return (0); +} + +/* + * Low-level write GTT + */ +static int +i8xx_write_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg) +{ + int i; + uint32_t *paddr; + uint32_t maxpages; + + maxpages = gtt->gtt_info.igd_apersize; + maxpages = GTT_MB_TO_PAGES(maxpages); + + /* Buffer from which we'll write. */ + paddr = seg.igs_phyaddr; + if (paddr == NULL) + return (-1); + + /* check if gtt max page number is reached */ + if ((seg.igs_pgstart + seg.igs_npage) > maxpages) + return (-1); + + paddr = seg.igs_phyaddr; + for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); + i++, paddr++) { + ddi_put32(gtt->gtt_handle, + (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)), + *paddr); + } + + return (0); +} |