15025407bSBen Skeggs #ifndef __NVKM_OBJECT_H__
25025407bSBen Skeggs #define __NVKM_OBJECT_H__
3c39f472eSBen Skeggs #include <core/os.h>
453003941SBen Skeggs #include <core/debug.h>
5c39f472eSBen Skeggs 
6c39f472eSBen Skeggs #define NV_PARENT_CLASS 0x80000000
7c39f472eSBen Skeggs #define NV_NAMEDB_CLASS 0x40000000
8c39f472eSBen Skeggs #define NV_CLIENT_CLASS 0x20000000
9c39f472eSBen Skeggs #define NV_SUBDEV_CLASS 0x10000000
10c39f472eSBen Skeggs #define NV_ENGINE_CLASS 0x08000000
11c39f472eSBen Skeggs #define NV_MEMOBJ_CLASS 0x04000000
12c39f472eSBen Skeggs #define NV_GPUOBJ_CLASS 0x02000000
13c39f472eSBen Skeggs #define NV_ENGCTX_CLASS 0x01000000
14c39f472eSBen Skeggs #define NV_OBJECT_CLASS 0x0000ffff
15c39f472eSBen Skeggs 
165025407bSBen Skeggs struct nvkm_object {
175025407bSBen Skeggs 	struct nvkm_oclass *oclass;
185025407bSBen Skeggs 	struct nvkm_object *parent;
195025407bSBen Skeggs 	struct nvkm_engine *engine;
20c39f472eSBen Skeggs 	atomic_t refcount;
21c39f472eSBen Skeggs 	atomic_t usecount;
22c39f472eSBen Skeggs #if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
235025407bSBen Skeggs #define NVKM_OBJECT_MAGIC 0x75ef0bad
24c39f472eSBen Skeggs 	struct list_head list;
25c39f472eSBen Skeggs 	u32 _magic;
26c39f472eSBen Skeggs #endif
27c39f472eSBen Skeggs };
28c39f472eSBen Skeggs 
295025407bSBen Skeggs static inline struct nvkm_object *
30c39f472eSBen Skeggs nv_object(void *obj)
31c39f472eSBen Skeggs {
32c39f472eSBen Skeggs #if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
33c39f472eSBen Skeggs 	if (likely(obj)) {
345025407bSBen Skeggs 		struct nvkm_object *object = obj;
3553003941SBen Skeggs 		BUG_ON(object->_magic != NVKM_OBJECT_MAGIC);
36c39f472eSBen Skeggs 	}
37c39f472eSBen Skeggs #endif
38c39f472eSBen Skeggs 	return obj;
39c39f472eSBen Skeggs }
40c39f472eSBen Skeggs 
415025407bSBen Skeggs #define nvkm_object_create(p,e,c,s,d)                                       \
425025407bSBen Skeggs 	nvkm_object_create_((p), (e), (c), (s), sizeof(**d), (void **)d)
435025407bSBen Skeggs int  nvkm_object_create_(struct nvkm_object *, struct nvkm_object *,
445025407bSBen Skeggs 			    struct nvkm_oclass *, u32, int size, void **);
455025407bSBen Skeggs void nvkm_object_destroy(struct nvkm_object *);
465025407bSBen Skeggs int  nvkm_object_init(struct nvkm_object *);
475025407bSBen Skeggs int  nvkm_object_fini(struct nvkm_object *, bool suspend);
48c39f472eSBen Skeggs 
495025407bSBen Skeggs int _nvkm_object_ctor(struct nvkm_object *, struct nvkm_object *,
505025407bSBen Skeggs 			 struct nvkm_oclass *, void *, u32,
515025407bSBen Skeggs 			 struct nvkm_object **);
52c39f472eSBen Skeggs 
535025407bSBen Skeggs extern struct nvkm_ofuncs nvkm_object_ofuncs;
54c39f472eSBen Skeggs 
55c39f472eSBen Skeggs /* Don't allocate dynamically, because lockdep needs lock_class_keys to be in
56c39f472eSBen Skeggs  * ".data". */
575025407bSBen Skeggs struct nvkm_oclass {
58c39f472eSBen Skeggs 	u32 handle;
595025407bSBen Skeggs 	struct nvkm_ofuncs * const ofuncs;
605025407bSBen Skeggs 	struct nvkm_omthds * const omthds;
61c39f472eSBen Skeggs 	struct lock_class_key lock_class_key;
62c39f472eSBen Skeggs };
63c39f472eSBen Skeggs 
64c39f472eSBen Skeggs #define nv_oclass(o)    nv_object(o)->oclass
65c39f472eSBen Skeggs #define nv_hclass(o)    nv_oclass(o)->handle
66c39f472eSBen Skeggs #define nv_iclass(o,i) (nv_hclass(o) & (i))
67c39f472eSBen Skeggs #define nv_mclass(o)    nv_iclass(o, NV_OBJECT_CLASS)
68c39f472eSBen Skeggs 
695025407bSBen Skeggs static inline struct nvkm_object *
705025407bSBen Skeggs nv_pclass(struct nvkm_object *parent, u32 oclass)
71c39f472eSBen Skeggs {
72c39f472eSBen Skeggs 	while (parent && !nv_iclass(parent, oclass))
73c39f472eSBen Skeggs 		parent = parent->parent;
74c39f472eSBen Skeggs 	return parent;
75c39f472eSBen Skeggs }
76c39f472eSBen Skeggs 
775025407bSBen Skeggs struct nvkm_omthds {
78c39f472eSBen Skeggs 	u32 start;
79c39f472eSBen Skeggs 	u32 limit;
805025407bSBen Skeggs 	int (*call)(struct nvkm_object *, u32, void *, u32);
81c39f472eSBen Skeggs };
82c39f472eSBen Skeggs 
83c39f472eSBen Skeggs struct nvkm_event;
845025407bSBen Skeggs struct nvkm_ofuncs {
855025407bSBen Skeggs 	int  (*ctor)(struct nvkm_object *, struct nvkm_object *,
865025407bSBen Skeggs 		     struct nvkm_oclass *, void *data, u32 size,
875025407bSBen Skeggs 		     struct nvkm_object **);
885025407bSBen Skeggs 	void (*dtor)(struct nvkm_object *);
895025407bSBen Skeggs 	int  (*init)(struct nvkm_object *);
905025407bSBen Skeggs 	int  (*fini)(struct nvkm_object *, bool suspend);
915025407bSBen Skeggs 	int  (*mthd)(struct nvkm_object *, u32, void *, u32);
925025407bSBen Skeggs 	int  (*ntfy)(struct nvkm_object *, u32, struct nvkm_event **);
935025407bSBen Skeggs 	int  (* map)(struct nvkm_object *, u64 *, u32 *);
945025407bSBen Skeggs 	u8   (*rd08)(struct nvkm_object *, u64 offset);
955025407bSBen Skeggs 	u16  (*rd16)(struct nvkm_object *, u64 offset);
965025407bSBen Skeggs 	u32  (*rd32)(struct nvkm_object *, u64 offset);
975025407bSBen Skeggs 	void (*wr08)(struct nvkm_object *, u64 offset, u8 data);
985025407bSBen Skeggs 	void (*wr16)(struct nvkm_object *, u64 offset, u16 data);
995025407bSBen Skeggs 	void (*wr32)(struct nvkm_object *, u64 offset, u32 data);
100c39f472eSBen Skeggs };
101c39f472eSBen Skeggs 
1025025407bSBen Skeggs static inline struct nvkm_ofuncs *
103c39f472eSBen Skeggs nv_ofuncs(void *obj)
104c39f472eSBen Skeggs {
105c39f472eSBen Skeggs 	return nv_oclass(obj)->ofuncs;
106c39f472eSBen Skeggs }
107c39f472eSBen Skeggs 
1085025407bSBen Skeggs int  nvkm_object_ctor(struct nvkm_object *, struct nvkm_object *,
1095025407bSBen Skeggs 		      struct nvkm_oclass *, void *, u32,
1105025407bSBen Skeggs 		      struct nvkm_object **);
1115025407bSBen Skeggs void nvkm_object_ref(struct nvkm_object *, struct nvkm_object **);
1125025407bSBen Skeggs int  nvkm_object_inc(struct nvkm_object *);
1135025407bSBen Skeggs int  nvkm_object_dec(struct nvkm_object *, bool suspend);
114c39f472eSBen Skeggs 
115c39f472eSBen Skeggs static inline int
116c39f472eSBen Skeggs nv_exec(void *obj, u32 mthd, void *data, u32 size)
117c39f472eSBen Skeggs {
1185025407bSBen Skeggs 	struct nvkm_omthds *method = nv_oclass(obj)->omthds;
119c39f472eSBen Skeggs 
120c39f472eSBen Skeggs 	while (method && method->call) {
121c39f472eSBen Skeggs 		if (mthd >= method->start && mthd <= method->limit)
122c39f472eSBen Skeggs 			return method->call(obj, mthd, data, size);
123c39f472eSBen Skeggs 		method++;
124c39f472eSBen Skeggs 	}
125c39f472eSBen Skeggs 
126c39f472eSBen Skeggs 	return -EINVAL;
127c39f472eSBen Skeggs }
128c39f472eSBen Skeggs 
129c39f472eSBen Skeggs static inline int
130c39f472eSBen Skeggs nv_call(void *obj, u32 mthd, u32 data)
131c39f472eSBen Skeggs {
132c39f472eSBen Skeggs 	return nv_exec(obj, mthd, &data, sizeof(data));
133c39f472eSBen Skeggs }
134c39f472eSBen Skeggs 
135c39f472eSBen Skeggs static inline u8
136c39f472eSBen Skeggs nv_ro08(void *obj, u64 addr)
137c39f472eSBen Skeggs {
138c39f472eSBen Skeggs 	u8 data = nv_ofuncs(obj)->rd08(obj, addr);
139c39f472eSBen Skeggs 	return data;
140c39f472eSBen Skeggs }
141c39f472eSBen Skeggs 
142c39f472eSBen Skeggs static inline u16
143c39f472eSBen Skeggs nv_ro16(void *obj, u64 addr)
144c39f472eSBen Skeggs {
145c39f472eSBen Skeggs 	u16 data = nv_ofuncs(obj)->rd16(obj, addr);
146c39f472eSBen Skeggs 	return data;
147c39f472eSBen Skeggs }
148c39f472eSBen Skeggs 
149c39f472eSBen Skeggs static inline u32
150c39f472eSBen Skeggs nv_ro32(void *obj, u64 addr)
151c39f472eSBen Skeggs {
152c39f472eSBen Skeggs 	u32 data = nv_ofuncs(obj)->rd32(obj, addr);
153c39f472eSBen Skeggs 	return data;
154c39f472eSBen Skeggs }
155c39f472eSBen Skeggs 
156c39f472eSBen Skeggs static inline void
157c39f472eSBen Skeggs nv_wo08(void *obj, u64 addr, u8 data)
158c39f472eSBen Skeggs {
159c39f472eSBen Skeggs 	nv_ofuncs(obj)->wr08(obj, addr, data);
160c39f472eSBen Skeggs }
161c39f472eSBen Skeggs 
162c39f472eSBen Skeggs static inline void
163c39f472eSBen Skeggs nv_wo16(void *obj, u64 addr, u16 data)
164c39f472eSBen Skeggs {
165c39f472eSBen Skeggs 	nv_ofuncs(obj)->wr16(obj, addr, data);
166c39f472eSBen Skeggs }
167c39f472eSBen Skeggs 
168c39f472eSBen Skeggs static inline void
169c39f472eSBen Skeggs nv_wo32(void *obj, u64 addr, u32 data)
170c39f472eSBen Skeggs {
171c39f472eSBen Skeggs 	nv_ofuncs(obj)->wr32(obj, addr, data);
172c39f472eSBen Skeggs }
173c39f472eSBen Skeggs 
174c39f472eSBen Skeggs static inline u32
175c39f472eSBen Skeggs nv_mo32(void *obj, u64 addr, u32 mask, u32 data)
176c39f472eSBen Skeggs {
177c39f472eSBen Skeggs 	u32 temp = nv_ro32(obj, addr);
178c39f472eSBen Skeggs 	nv_wo32(obj, addr, (temp & ~mask) | data);
179c39f472eSBen Skeggs 	return temp;
180c39f472eSBen Skeggs }
181c39f472eSBen Skeggs 
182c39f472eSBen Skeggs static inline int
183c39f472eSBen Skeggs nv_memcmp(void *obj, u32 addr, const char *str, u32 len)
184c39f472eSBen Skeggs {
185c39f472eSBen Skeggs 	unsigned char c1, c2;
186c39f472eSBen Skeggs 
187c39f472eSBen Skeggs 	while (len--) {
188c39f472eSBen Skeggs 		c1 = nv_ro08(obj, addr++);
189c39f472eSBen Skeggs 		c2 = *(str++);
190c39f472eSBen Skeggs 		if (c1 != c2)
191c39f472eSBen Skeggs 			return c1 - c2;
192c39f472eSBen Skeggs 	}
193c39f472eSBen Skeggs 	return 0;
194c39f472eSBen Skeggs }
195c39f472eSBen Skeggs #endif
196