nouveau: move channel creation into pipe drivers
diff --git a/src/gallium/drivers/nouveau/nouveau_push.h b/src/gallium/drivers/nouveau/nouveau_push.h
index afe4668..0f2c429 100644
--- a/src/gallium/drivers/nouveau/nouveau_push.h
+++ b/src/gallium/drivers/nouveau/nouveau_push.h
@@ -9,13 +9,13 @@
 
 #define OUT_RING(data) do {                                                    \
 	NOUVEAU_PUSH_CONTEXT(pc);                                              \
-	(*pc->nvws->channel->pushbuf->cur++) = (data);                         \
+	(*pc->base.channel->pushbuf->cur++) = (data);                          \
 } while(0)
 
 #define OUT_RINGp(src,size) do {                                               \
 	NOUVEAU_PUSH_CONTEXT(pc);                                              \
-	memcpy(pc->nvws->channel->pushbuf->cur, (src), (size) * 4);            \
-	pc->nvws->channel->pushbuf->cur += (size);                             \
+	memcpy(pc->base.channel->pushbuf->cur, (src), (size) * 4);             \
+	pc->base.channel->pushbuf->cur += (size);                              \
 } while(0)
 
 #define OUT_RINGf(data) do {                                                   \
@@ -26,7 +26,7 @@
 
 #define BEGIN_RING(obj,mthd,size) do {                                         \
 	NOUVEAU_PUSH_CONTEXT(pc);                                              \
-	struct nouveau_channel *chan = pc->nvws->channel;                      \
+	struct nouveau_channel *chan = pc->base.channel;                       \
 	if (chan->pushbuf->remaining < ((size) + 1))                           \
 		nouveau_pushbuf_flush(chan, ((size) + 1));                     \
 	OUT_RING((pc->obj->subc << 13) | ((size) << 18) | (mthd));             \
@@ -47,14 +47,13 @@
 
 #define FIRE_RING(fence) do {                                                  \
 	NOUVEAU_PUSH_CONTEXT(pc);                                              \
-	DO_FIRE_RING(pc->nvws->channel, fence);                                \
+	DO_FIRE_RING(pc->base.channel, fence);                                 \
 } while(0)
 
 #define OUT_RELOC(bo,data,flags,vor,tor) do {                                  \
 	NOUVEAU_PUSH_CONTEXT(pc);                                              \
-	struct nouveau_channel *chan = pc->nvws->channel;                      \
-	nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++,                 \
-				   pc->nvws->get_bo(bo),                       \
+	struct nouveau_channel *chan = pc->base.channel;                       \
+	nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, nouveau_bo(bo), \
 				   (data), (flags), (vor), (tor));             \
 } while(0)
 
@@ -66,8 +65,8 @@
 /* FB/TT object handle */
 #define OUT_RELOCo(bo,flags) do {                                              \
 	OUT_RELOC((bo), 0, (flags) | NOUVEAU_BO_OR,                            \
-		  pc->nvws->channel->vram->handle,                             \
-		  pc->nvws->channel->gart->handle);                            \
+		  pc->base.channel->vram->handle,                              \
+		  pc->base.channel->gart->handle);                             \
 } while(0)
 
 /* Low 32-bits of offset */
@@ -83,7 +82,7 @@
 /* A reloc which'll recombine into a NV_DMA_METHOD packet header */
 #define OUT_RELOCm(bo, flags, obj, mthd, size) do {                            \
 	NOUVEAU_PUSH_CONTEXT(pc);                                              \
-	struct nouveau_channel *chan = pc->nvws->channel;                      \
+	struct nouveau_channel *chan = pc->base.channel;                       \
 	if (chan->pushbuf->remaining < ((size) + 1))                           \
 		nouveau_pushbuf_flush(chan, ((size) + 1));                     \
 	OUT_RELOCd((bo), (pc->obj->subc << 13) | ((size) << 18) | (mthd),      \
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index 3cab83e..ab522a1 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -212,7 +212,12 @@
 nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
 {
 	struct pipe_screen *pscreen = &screen->base;
+	int ret;
 
+	ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
+				    &screen->channel);
+	if (ret)
+		return ret;
 	screen->device = dev;
 
 	pscreen->get_name = nouveau_screen_get_name;
diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h
index de3ba9c..8e818d9 100644
--- a/src/gallium/drivers/nouveau/nouveau_stateobj.h
+++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
@@ -107,21 +107,21 @@
 }
 
 static INLINE void
-so_emit(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
+so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so)
 {
-	struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
+	struct nouveau_pushbuf *pb = chan->pushbuf;
 	unsigned nr, i;
 
 	nr = so->cur - so->push;
 	if (pb->remaining < nr)
-		nouveau_pushbuf_flush(nvws->channel, nr);
+		nouveau_pushbuf_flush(chan, nr);
 	pb->remaining -= nr;
 
 	memcpy(pb->cur, so->push, nr * 4);
 	for (i = 0; i < so->cur_reloc; i++) {
 		struct nouveau_stateobj_reloc *r = &so->reloc[i];
 
-		nouveau_pushbuf_emit_reloc(nvws->channel, pb->cur + r->offset,
+		nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
 					   r->bo, r->data, r->flags, r->vor,
 					   r->tor);
 	}
@@ -129,30 +129,29 @@
 }
 
 static INLINE void
-so_emit_reloc_markers(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
+so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so)
 {
-	struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
+	struct nouveau_pushbuf *pb = chan->pushbuf;
 	unsigned i;
 
 	if (!so)
 		return;
 
 	i = so->cur_reloc << 1;
-	if (nvws->channel->pushbuf->remaining < i)
-		nouveau_pushbuf_flush(nvws->channel, i);
-	nvws->channel->pushbuf->remaining -= i;
+	if (pb->remaining < i)
+		nouveau_pushbuf_flush(chan, i);
+	pb->remaining -= i;
 
 	for (i = 0; i < so->cur_reloc; i++) {
 		struct nouveau_stateobj_reloc *r = &so->reloc[i];
 
-		nouveau_pushbuf_emit_reloc(nvws->channel, pb->cur++, r->bo,
-					   r->packet,
+		nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->packet,
 					   (r->flags & (NOUVEAU_BO_VRAM |
 							NOUVEAU_BO_GART |
 							NOUVEAU_BO_RDWR)) |
 					   NOUVEAU_BO_DUMMY, 0, 0);
-		nouveau_pushbuf_emit_reloc(nvws->channel, pb->cur++, r->bo,
-					   r->data, r->flags | NOUVEAU_BO_DUMMY,
+		nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->data,
+					   r->flags | NOUVEAU_BO_DUMMY,
 					   r->vor, r->tor);
 	}
 }
diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h
index 7998497..42c77e5 100644
--- a/src/gallium/drivers/nouveau/nouveau_winsys.h
+++ b/src/gallium/drivers/nouveau/nouveau_winsys.h
@@ -23,44 +23,38 @@
 #define NOUVEAU_BUFFER_USAGE_ZETA     (1 << 17)
 #define NOUVEAU_BUFFER_USAGE_TRANSFER (1 << 18)
 
-struct nouveau_winsys {
-	struct pipe_winsys *ws;
-
-	struct nouveau_channel *channel;
-};
-
 extern struct pipe_screen *
-nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv04_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
 
 extern struct pipe_context *
 nv04_create(struct pipe_screen *, unsigned pctx_id);
 
 extern struct pipe_screen *
-nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
 
 extern struct pipe_context *
 nv10_create(struct pipe_screen *, unsigned pctx_id);
 
 extern struct pipe_screen *
-nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv20_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
 
 extern struct pipe_context *
 nv20_create(struct pipe_screen *, unsigned pctx_id);
 
 extern struct pipe_screen *
-nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
 
 extern struct pipe_context *
 nv30_create(struct pipe_screen *, unsigned pctx_id);
 
 extern struct pipe_screen *
-nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
 
 extern struct pipe_context *
 nv40_create(struct pipe_screen *, unsigned pctx_id);
 
 extern struct pipe_screen *
-nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
 
 extern struct pipe_context *
 nv50_create(struct pipe_screen *, unsigned pctx_id);
diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c
index 98e2daf..4bbedfb 100644
--- a/src/gallium/drivers/nv04/nv04_screen.c
+++ b/src/gallium/drivers/nv04/nv04_screen.c
@@ -122,10 +122,9 @@
 }
 
 struct pipe_screen *
-nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+nv04_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
 	struct nv04_screen *screen = CALLOC_STRUCT(nv04_screen);
-	struct nouveau_device *dev = nvws->channel->device;
 	struct nouveau_channel *chan;
 	struct pipe_screen *pscreen;
 	unsigned fahrenheit_class = 0, sub3d_class = 0;
@@ -140,9 +139,7 @@
 		nv04_screen_destroy(pscreen);
 		return NULL;
 	}
-	screen->base.channel = chan = nvws->channel;
-
-	screen->nvws = nvws;
+	chan = screen->base.channel;
 
 	pscreen->winsys = ws;
 	pscreen->destroy = nv04_screen_destroy;
@@ -188,7 +185,7 @@
 	BIND_RING(chan, screen->context_surfaces_3d, 6);
 
 	/* 2D engine setup */
-	screen->eng2d = nv04_surface_2d_init(nvws);
+	screen->eng2d = nv04_surface_2d_init(&screen->base);
 	screen->eng2d->buf = nv04_surface_buffer;
 
 	/* Notifier for sync purposes */
diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c
index fcb6501..5afd028 100644
--- a/src/gallium/drivers/nv04/nv04_surface_2d.c
+++ b/src/gallium/drivers/nv04/nv04_surface_2d.c
@@ -97,7 +97,7 @@
 			  struct pipe_surface *src, int sx, int sy,
 			  int w, int h)
 {
-	struct nouveau_channel *chan = ctx->nvws->channel;
+	struct nouveau_channel *chan = ctx->swzsurf->channel;
 	struct nouveau_grobj *swzsurf = ctx->swzsurf;
 	struct nouveau_grobj *sifm = ctx->sifm;
 	struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src));
@@ -168,7 +168,7 @@
 		       struct pipe_surface *dst, int dx, int dy,
 		       struct pipe_surface *src, int sx, int sy, int w, int h)
 {
-	struct nouveau_channel *chan = ctx->nvws->channel;
+	struct nouveau_channel *chan = ctx->m2mf->channel;
 	struct nouveau_grobj *m2mf = ctx->m2mf;
 	struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src));
 	struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst));
@@ -214,7 +214,7 @@
 		       int dx, int dy, struct pipe_surface *src, int sx, int sy,
 		       int w, int h)
 {
-	struct nouveau_channel *chan = ctx->nvws->channel;
+	struct nouveau_channel *chan = ctx->surf2d->channel;
 	struct nouveau_grobj *surf2d = ctx->surf2d;
 	struct nouveau_grobj *blit = ctx->blit;
 	struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src));
@@ -280,7 +280,7 @@
 nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst,
 		  int dx, int dy, int w, int h, unsigned value)
 {
-	struct nouveau_channel *chan = ctx->nvws->channel;
+	struct nouveau_channel *chan = ctx->surf2d->channel;
 	struct nouveau_grobj *surf2d = ctx->surf2d;
 	struct nouveau_grobj *rect = ctx->rect;
 	struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst));
@@ -335,10 +335,10 @@
 }
 
 struct nv04_surface_2d *
-nv04_surface_2d_init(struct nouveau_winsys *nvws)
+nv04_surface_2d_init(struct nouveau_screen *screen)
 {
 	struct nv04_surface_2d *ctx = CALLOC_STRUCT(nv04_surface_2d);
-	struct nouveau_channel *chan = nvws->channel;
+	struct nouveau_channel *chan = screen->channel;
 	unsigned handle = 0x88000000, class;
 	int ret;
 
@@ -461,7 +461,6 @@
 		return NULL;
 	}
 
-	ctx->nvws = nvws;
 	ctx->copy = nv04_surface_copy;
 	ctx->fill = nv04_surface_fill;
 	return ctx;
diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.h b/src/gallium/drivers/nv04/nv04_surface_2d.h
index 82ce718..02b3f56 100644
--- a/src/gallium/drivers/nv04/nv04_surface_2d.h
+++ b/src/gallium/drivers/nv04/nv04_surface_2d.h
@@ -7,7 +7,6 @@
 };
 
 struct nv04_surface_2d {
-	struct nouveau_winsys *nvws;
 	struct nouveau_notifier *ntfy;
 	struct nouveau_grobj *surf2d;
 	struct nouveau_grobj *swzsurf;
@@ -26,7 +25,7 @@
 };
 
 struct nv04_surface_2d *
-nv04_surface_2d_init(struct nouveau_winsys *nvws);
+nv04_surface_2d_init(struct nouveau_screen *screen);
 
 void
 nv04_surface_2d_takedown(struct nv04_surface_2d **);
diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c
index 3da8d2f..a127b13 100644
--- a/src/gallium/drivers/nv10/nv10_context.c
+++ b/src/gallium/drivers/nv10/nv10_context.c
@@ -30,18 +30,18 @@
 static void nv10_init_hwctx(struct nv10_context *nv10)
 {
 	struct nv10_screen *screen = nv10->screen;
-	struct nouveau_winsys *nvws = screen->nvws;
+	struct nouveau_channel *chan = screen->base.channel;
 	int i;
 	float projectionmatrix[16];
 
 	BEGIN_RING(celsius, NV10TCL_DMA_NOTIFY, 1);
 	OUT_RING  (screen->sync->handle);
 	BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY0, 2);
-	OUT_RING  (nvws->channel->vram->handle);
-	OUT_RING  (nvws->channel->gart->handle);
+	OUT_RING  (chan->vram->handle);
+	OUT_RING  (chan->gart->handle);
 	BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY2, 2);
-	OUT_RING  (nvws->channel->vram->handle);
-	OUT_RING  (nvws->channel->vram->handle);
+	OUT_RING  (chan->vram->handle);
+	OUT_RING  (chan->vram->handle);
 
 	BEGIN_RING(celsius, NV10TCL_NOP, 1);
 	OUT_RING  (0);
diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c
index f090d2b..b03c291 100644
--- a/src/gallium/drivers/nv10/nv10_screen.c
+++ b/src/gallium/drivers/nv10/nv10_screen.c
@@ -118,10 +118,9 @@
 }
 
 struct pipe_screen *
-nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
 	struct nv10_screen *screen = CALLOC_STRUCT(nv10_screen);
-	struct nouveau_device *dev = nvws->channel->device;
 	struct nouveau_channel *chan;
 	struct pipe_screen *pscreen;
 	unsigned celsius_class;
@@ -136,9 +135,7 @@
 		nv10_screen_destroy(pscreen);
 		return NULL;
 	}
-	screen->base.channel = chan = nvws->channel;
-
-	screen->nvws = nvws;
+	chan = screen->base.channel;
 
 	pscreen->winsys = ws;
 	pscreen->destroy = nv10_screen_destroy;
@@ -173,7 +170,7 @@
 	BIND_RING(chan, screen->celsius, 7);
 
 	/* 2D engine setup */
-	screen->eng2d = nv04_surface_2d_init(nvws);
+	screen->eng2d = nv04_surface_2d_init(&screen->base);
 	screen->eng2d->buf = nv10_surface_buffer;
 
 	/* Notifier for sync purposes */
diff --git a/src/gallium/drivers/nv20/nv20_context.c b/src/gallium/drivers/nv20/nv20_context.c
index cbc4170..b32d0d8 100644
--- a/src/gallium/drivers/nv20/nv20_context.c
+++ b/src/gallium/drivers/nv20/nv20_context.c
@@ -30,7 +30,7 @@
 static void nv20_init_hwctx(struct nv20_context *nv20)
 {
 	struct nv20_screen *screen = nv20->screen;
-	struct nouveau_winsys *nvws = screen->nvws;
+	struct nouveau_channel *chan = screen->base.channel;
 	int i;
 	float projectionmatrix[16];
 	const boolean is_nv25tcl = (nv20->screen->kelvin->grclass == NV25TCL);
@@ -38,11 +38,11 @@
 	BEGIN_RING(kelvin, NV20TCL_DMA_NOTIFY, 1);
 	OUT_RING  (screen->sync->handle);
 	BEGIN_RING(kelvin, NV20TCL_DMA_TEXTURE0, 2);
-	OUT_RING  (nvws->channel->vram->handle);
-	OUT_RING  (nvws->channel->gart->handle); /* TEXTURE1 */
+	OUT_RING  (chan->vram->handle);
+	OUT_RING  (chan->gart->handle); /* TEXTURE1 */
 	BEGIN_RING(kelvin, NV20TCL_DMA_COLOR, 2);
-	OUT_RING  (nvws->channel->vram->handle);
-	OUT_RING  (nvws->channel->vram->handle); /* ZETA */
+	OUT_RING  (chan->vram->handle);
+	OUT_RING  (chan->vram->handle); /* ZETA */
 
 	BEGIN_RING(kelvin, NV20TCL_DMA_QUERY, 1);
 	OUT_RING  (0); /* renouveau: beef0351, unique */
@@ -99,9 +99,9 @@
 		OUT_RING  (3);
 
 		BEGIN_RING(kelvin, NV25TCL_DMA_IN_MEMORY9, 1);
-		OUT_RING  (nvws->channel->vram->handle);
+		OUT_RING  (chan->vram->handle);
 		BEGIN_RING(kelvin, NV25TCL_DMA_IN_MEMORY8, 1);
-		OUT_RING  (nvws->channel->vram->handle);
+		OUT_RING  (chan->vram->handle);
 	}
 	BEGIN_RING(kelvin, NV20TCL_DMA_FENCE, 1);
 	OUT_RING  (0);	/* renouveau: beef1e10 */
diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c
index 4d99185..024356c 100644
--- a/src/gallium/drivers/nv20/nv20_screen.c
+++ b/src/gallium/drivers/nv20/nv20_screen.c
@@ -118,10 +118,9 @@
 }
 
 struct pipe_screen *
-nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+nv20_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
 	struct nv20_screen *screen = CALLOC_STRUCT(nv20_screen);
-	struct nouveau_device *dev = nvws->channel->device;
 	struct nouveau_channel *chan;
 	struct pipe_screen *pscreen;
 	unsigned kelvin_class = 0;
@@ -136,9 +135,7 @@
 		nv20_screen_destroy(pscreen);
 		return NULL;
 	}
-	screen->base.channel = chan = nvws->channel;
-
-	screen->nvws = nvws;
+	chan = screen->base.channel;
 
 	pscreen->winsys = ws;
 	pscreen->destroy = nv20_screen_destroy;
@@ -169,7 +166,7 @@
 	BIND_RING(chan, screen->kelvin, 7);
 
 	/* 2D engine setup */
-	screen->eng2d = nv04_surface_2d_init(nvws);
+	screen->eng2d = nv04_surface_2d_init(&screen->base);
 	screen->eng2d->buf = nv20_surface_buffer;
 
 	/* Notifier for sync purposes */
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
index 60e2f08..31bc1f3 100644
--- a/src/gallium/drivers/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nv30/nv30_screen.c
@@ -136,10 +136,9 @@
 }
 
 struct pipe_screen *
-nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
 	struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen);
-	struct nouveau_device *dev = nvws->channel->device;
 	struct nouveau_channel *chan;
 	struct pipe_screen *pscreen;
 	struct nouveau_stateobj *so;
@@ -155,9 +154,7 @@
 		nv30_screen_destroy(pscreen);
 		return NULL;
 	}
-	screen->base.channel = chan = nvws->channel;
-
-	screen->nvws = nvws;
+	chan = screen->base.channel;
 
 	pscreen->winsys = ws;
 	pscreen->destroy = nv30_screen_destroy;
@@ -198,7 +195,7 @@
 	BIND_RING(chan, screen->rankine, 7);
 
 	/* 2D engine setup */
-	screen->eng2d = nv04_surface_2d_init(nvws);
+	screen->eng2d = nv04_surface_2d_init(&screen->base);
 	screen->eng2d->buf = nv30_surface_buffer;
 
 	/* Notifier for sync purposes */
@@ -307,7 +304,7 @@
 	so_method(so, screen->rankine, 0x1e94, 1);
 	so_data  (so, 0x13);
 
-	so_emit(nvws, so);
+	so_emit(chan, so);
 	so_ref(NULL, &so);
 	nouveau_pushbuf_flush(chan, 0);
 
diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c
index c18be20..621b884 100644
--- a/src/gallium/drivers/nv30/nv30_state_emit.c
+++ b/src/gallium/drivers/nv30/nv30_state_emit.c
@@ -38,6 +38,7 @@
 void
 nv30_state_emit(struct nv30_context *nv30)
 {
+	struct nouveau_channel *chan = nv30->screen->base.channel;
 	struct nv30_state *state = &nv30->state;
 	struct nv30_screen *screen = nv30->screen;
 	unsigned i, samplers;
@@ -57,23 +58,23 @@
 			continue;
 		so_ref (state->hw[i], &nv30->screen->state[i]);
 		if (state->hw[i])
-			so_emit(nv30->nvws, nv30->screen->state[i]);
+			so_emit(chan, nv30->screen->state[i]);
 		states &= ~(1ULL << i);
 	}
 
 	state->dirty = 0;
 
-	so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FB]);
+	so_emit_reloc_markers(chan, state->hw[NV30_STATE_FB]);
 	for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
 		if (!(samplers & (1 << i)))
 			continue;
-		so_emit_reloc_markers(nv30->nvws,
+		so_emit_reloc_markers(chan,
 				      state->hw[NV30_STATE_FRAGTEX0+i]);
 		samplers &= ~(1ULL << i);
 	}
-	so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FRAGPROG]);
+	so_emit_reloc_markers(chan, state->hw[NV30_STATE_FRAGPROG]);
 	if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/)
-		so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_VTXBUF]);
+		so_emit_reloc_markers(chan, state->hw[NV30_STATE_VTXBUF]);
 }
 
 boolean
diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c
index 1be9168..cb1a260 100644
--- a/src/gallium/drivers/nv30/nv30_state_fb.c
+++ b/src/gallium/drivers/nv30/nv30_state_fb.c
@@ -5,6 +5,8 @@
 nv30_state_framebuffer_validate(struct nv30_context *nv30)
 {
 	struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+	struct nouveau_channel *chan = nv30->screen->base.channel;
+	struct nouveau_grobj *rankine = nv30->screen->rankine;
 	struct nv04_surface *rt[2], *zeta = NULL;
 	uint32_t rt_enable, rt_format;
 	int i, colour_format = 0, zeta_format = 0;
@@ -79,11 +81,10 @@
 		}
 
 		nv30mt = (struct nv30_miptree *)rt[0]->base.texture;
-		so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR0, 1);
+		so_method(so, rankine, NV34TCL_DMA_COLOR0, 1);
 		so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR,
-			      nv30->nvws->channel->vram->handle,
-			      nv30->nvws->channel->gart->handle);
-		so_method(so, nv30->screen->rankine, NV34TCL_COLOR0_PITCH, 2);
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, rankine, NV34TCL_COLOR0_PITCH, 2);
 		so_data  (so, pitch);
 		so_reloc (so, nouveau_bo(nv30mt->buffer), rt[0]->base.offset,
 			      rt_flags | NOUVEAU_BO_LOW, 0, 0);
@@ -91,11 +92,10 @@
 
 	if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) {
 		nv30mt = (struct nv30_miptree *)rt[1]->base.texture;
-		so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR1, 1);
+		so_method(so, rankine, NV34TCL_DMA_COLOR1, 1);
 		so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR,
-			      nv30->nvws->channel->vram->handle,
-			      nv30->nvws->channel->gart->handle);
-		so_method(so, nv30->screen->rankine, NV34TCL_COLOR1_OFFSET, 2);
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, rankine, NV34TCL_COLOR1_OFFSET, 2);
 		so_reloc (so, nouveau_bo(nv30mt->buffer), rt[1]->base.offset,
 			      rt_flags | NOUVEAU_BO_LOW, 0, 0);
 		so_data  (so, rt[1]->pitch);
@@ -103,32 +103,31 @@
 
 	if (zeta_format) {
 		nv30mt = (struct nv30_miptree *)zeta->base.texture;
-		so_method(so, nv30->screen->rankine, NV34TCL_DMA_ZETA, 1);
+		so_method(so, rankine, NV34TCL_DMA_ZETA, 1);
 		so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR,
-			      nv30->nvws->channel->vram->handle,
-			      nv30->nvws->channel->gart->handle);
-		so_method(so, nv30->screen->rankine, NV34TCL_ZETA_OFFSET, 1);
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, rankine, NV34TCL_ZETA_OFFSET, 1);
 		so_reloc (so, nouveau_bo(nv30mt->buffer), zeta->base.offset,
 			      rt_flags | NOUVEAU_BO_LOW, 0, 0);
 		/* TODO: allocate LMA depth buffer */
 	}
 
-	so_method(so, nv30->screen->rankine, NV34TCL_RT_ENABLE, 1);
+	so_method(so, rankine, NV34TCL_RT_ENABLE, 1);
 	so_data  (so, rt_enable);
-	so_method(so, nv30->screen->rankine, NV34TCL_RT_HORIZ, 3);
+	so_method(so, rankine, NV34TCL_RT_HORIZ, 3);
 	so_data  (so, (w << 16) | 0);
 	so_data  (so, (h << 16) | 0);
 	so_data  (so, rt_format);
-	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_HORIZ, 2);
+	so_method(so, rankine, NV34TCL_VIEWPORT_HORIZ, 2);
 	so_data  (so, (w << 16) | 0);
 	so_data  (so, (h << 16) | 0);
-	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+	so_method(so, rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
 	so_data  (so, ((w - 1) << 16) | 0);
 	so_data  (so, ((h - 1) << 16) | 0);
-	so_method(so, nv30->screen->rankine, 0x1d88, 1);
+	so_method(so, rankine, 0x1d88, 1);
 	so_data  (so, (1 << 12) | h);
 	/* Wonder why this is needed, context should all be set to zero on init */
-	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1);
+	so_method(so, rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1);
 	so_data  (so, 0);
 
 	so_ref(so, &nv30->state.hw[NV30_STATE_FB]);
diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c
index ff2bf6e..9b72bc3 100644
--- a/src/gallium/drivers/nv30/nv30_vbo.c
+++ b/src/gallium/drivers/nv30/nv30_vbo.c
@@ -168,7 +168,7 @@
 		 unsigned mode, unsigned start, unsigned count)
 {
 	struct nv30_context *nv30 = nv30_context(pipe);
-	struct nouveau_channel *chan = nv30->nvws->channel;
+	struct nouveau_channel *chan = nv30->screen->base.channel;
 	unsigned restart = 0;
 
 	nv30_vbo_set_idxbuf(nv30, NULL, 0);
@@ -228,7 +228,7 @@
 nv30_draw_elements_u08(struct nv30_context *nv30, void *ib,
 		       unsigned mode, unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv30->nvws->channel;
+	struct nouveau_channel *chan = nv30->screen->base.channel;
 
 	while (count) {
 		uint8_t *elts = (uint8_t *)ib + start;
@@ -277,7 +277,7 @@
 nv30_draw_elements_u16(struct nv30_context *nv30, void *ib,
 		       unsigned mode, unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv30->nvws->channel;
+	struct nouveau_channel *chan = nv30->screen->base.channel;
 
 	while (count) {
 		uint16_t *elts = (uint16_t *)ib + start;
@@ -326,7 +326,7 @@
 nv30_draw_elements_u32(struct nv30_context *nv30, void *ib,
 		       unsigned mode, unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv30->nvws->channel;
+	struct nouveau_channel *chan = nv30->screen->base.channel;
 
 	while (count) {
 		uint32_t *elts = (uint32_t *)ib + start;
@@ -401,7 +401,7 @@
 		       unsigned mode, unsigned start, unsigned count)
 {
 	struct nv30_context *nv30 = nv30_context(pipe);
-	struct nouveau_channel *chan = nv30->nvws->channel;
+	struct nouveau_channel *chan = nv30->screen->base.channel;
 	unsigned restart = 0;
 
 	while (count) {
diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c
index c83ff91..e7d8cf9 100644
--- a/src/gallium/drivers/nv40/nv40_draw.c
+++ b/src/gallium/drivers/nv40/nv40_draw.c
@@ -81,7 +81,7 @@
 {
 	struct nv40_render_stage *rs = nv40_render_stage(stage);
 	struct nv40_context *nv40 = rs->nv40;
-	struct nouveau_pushbuf *pb = nv40->nvws->channel->pushbuf;
+	struct nouveau_pushbuf *pb = nv40->screen->base.channel->pushbuf;
 	unsigned i;
 
 	/* Ensure there's room for 4xfloat32 + potentially 3 begin/end */
diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c
index 2114c93..b8b2af4 100644
--- a/src/gallium/drivers/nv40/nv40_screen.c
+++ b/src/gallium/drivers/nv40/nv40_screen.c
@@ -144,10 +144,9 @@
 }
 
 struct pipe_screen *
-nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
 	struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen);
-	struct nouveau_device *dev = nvws->channel->device;
 	struct nouveau_channel *chan;
 	struct pipe_screen *pscreen;
 	struct nouveau_stateobj *so;
@@ -163,9 +162,7 @@
 		nv40_screen_destroy(pscreen);
 		return NULL;
 	}
-	screen->base.channel = chan = nvws->channel;
-
-	screen->nvws = nvws;
+	chan = screen->base.channel;
 
 	pscreen->winsys = ws;
 	pscreen->destroy = nv40_screen_destroy;
@@ -204,7 +201,7 @@
 	BIND_RING(chan, screen->curie, 7);
 
 	/* 2D engine setup */
-	screen->eng2d = nv04_surface_2d_init(nvws);
+	screen->eng2d = nv04_surface_2d_init(&screen->base);
 	screen->eng2d->buf = nv40_surface_buffer;
 
 	/* Notifier for sync purposes */
@@ -242,25 +239,25 @@
 	so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1);
 	so_data  (so, screen->sync->handle);
 	so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2);
-	so_data  (so, nvws->channel->vram->handle);
-	so_data  (so, nvws->channel->gart->handle);
+	so_data  (so, chan->vram->handle);
+	so_data  (so, chan->gart->handle);
 	so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1);
-	so_data  (so, nvws->channel->vram->handle);
+	so_data  (so, chan->vram->handle);
 	so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2);
-	so_data  (so, nvws->channel->vram->handle);
-	so_data  (so, nvws->channel->vram->handle);
+	so_data  (so, chan->vram->handle);
+	so_data  (so, chan->vram->handle);
 	so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2);
-	so_data  (so, nvws->channel->vram->handle);
-	so_data  (so, nvws->channel->gart->handle);
+	so_data  (so, chan->vram->handle);
+	so_data  (so, chan->gart->handle);
 	so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2);
 	so_data  (so, 0);
 	so_data  (so, screen->query->handle);
 	so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2);
-	so_data  (so, nvws->channel->vram->handle);
-	so_data  (so, nvws->channel->vram->handle);
+	so_data  (so, chan->vram->handle);
+	so_data  (so, chan->vram->handle);
 	so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2);
-	so_data  (so, nvws->channel->vram->handle);
-	so_data  (so, nvws->channel->vram->handle);
+	so_data  (so, chan->vram->handle);
+	so_data  (so, chan->vram->handle);
 
 	so_method(so, screen->curie, 0x1ea4, 3);
 	so_data  (so, 0x00000010);
@@ -285,9 +282,9 @@
 	so_method(so, screen->curie, 0x1e94, 1);
 	so_data  (so, 0x00000001);
 
-	so_emit(nvws, so);
+	so_emit(chan, so);
 	so_ref(NULL, &so);
-	nouveau_pushbuf_flush(nvws->channel, 0);
+	nouveau_pushbuf_flush(chan, 0);
 
 	return pscreen;
 }
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
index 10aae29..1986929 100644
--- a/src/gallium/drivers/nv40/nv40_state_emit.c
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -54,6 +54,7 @@
 void
 nv40_state_emit(struct nv40_context *nv40)
 {
+	struct nouveau_channel *chan = nv40->screen->base.channel;
 	struct nv40_state *state = &nv40->state;
 	struct nv40_screen *screen = nv40->screen;
 	unsigned i, samplers;
@@ -73,7 +74,7 @@
 			continue;
 		so_ref (state->hw[i], &nv40->screen->state[i]);
 		if (state->hw[i])
-			so_emit(nv40->nvws, nv40->screen->state[i]);
+			so_emit(chan, nv40->screen->state[i]);
 		states &= ~(1ULL << i);
 	}
 
@@ -87,17 +88,17 @@
 
 	state->dirty = 0;
 
-	so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FB]);
+	so_emit_reloc_markers(chan, state->hw[NV40_STATE_FB]);
 	for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
 		if (!(samplers & (1 << i)))
 			continue;
-		so_emit_reloc_markers(nv40->nvws,
+		so_emit_reloc_markers(chan,
 				      state->hw[NV40_STATE_FRAGTEX0+i]);
 		samplers &= ~(1ULL << i);
 	}
-	so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FRAGPROG]);
+	so_emit_reloc_markers(chan, state->hw[NV40_STATE_FRAGPROG]);
 	if (state->hw[NV40_STATE_VTXBUF] && nv40->render_mode == HW)
-		so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_VTXBUF]);
+		so_emit_reloc_markers(chan, state->hw[NV40_STATE_VTXBUF]);
 }
 
 boolean
diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c
index d8364ff..273142f 100644
--- a/src/gallium/drivers/nv40/nv40_state_fb.c
+++ b/src/gallium/drivers/nv40/nv40_state_fb.c
@@ -13,6 +13,8 @@
 static boolean
 nv40_state_framebuffer_validate(struct nv40_context *nv40)
 {
+	struct nouveau_channel *chan = nv40->screen->base.channel;
+	struct nouveau_grobj *curie = nv40->screen->curie;
 	struct pipe_framebuffer_state *fb = &nv40->framebuffer;
 	struct nv04_surface *rt[4], *zeta;
 	uint32_t rt_enable, rt_format;
@@ -79,76 +81,80 @@
 	}
 
 	if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) {
-		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1);
-		so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, rt_flags | NOUVEAU_BO_OR,
-			  nv40->nvws->channel->vram->handle,
-			  nv40->nvws->channel->gart->handle);
-		so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2);
+		so_method(so, curie, NV40TCL_DMA_COLOR0, 1);
+		so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0,
+			      rt_flags | NOUVEAU_BO_OR,
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, curie, NV40TCL_COLOR0_PITCH, 2);
 		so_data  (so, rt[0]->pitch);
-		so_reloc (so, nv40_surface_buffer(&rt[0]->base), rt[0]->base.offset, rt_flags |
-			  NOUVEAU_BO_LOW, 0, 0);
+		so_reloc (so, nv40_surface_buffer(&rt[0]->base),
+			      rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+			      0, 0);
 	}
 
 	if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) {
-		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1);
-		so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, rt_flags | NOUVEAU_BO_OR,
-			  nv40->nvws->channel->vram->handle,
-			  nv40->nvws->channel->gart->handle);
-		so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2);
-		so_reloc (so, nv40_surface_buffer(&rt[1]->base), rt[1]->base.offset, rt_flags |
-			  NOUVEAU_BO_LOW, 0, 0);
+		so_method(so, curie, NV40TCL_DMA_COLOR1, 1);
+		so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0,
+			      rt_flags | NOUVEAU_BO_OR,
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, curie, NV40TCL_COLOR1_OFFSET, 2);
+		so_reloc (so, nv40_surface_buffer(&rt[1]->base),
+			      rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+			      0, 0);
 		so_data  (so, rt[1]->pitch);
 	}
 
 	if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) {
-		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1);
-		so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, rt_flags | NOUVEAU_BO_OR,
-			  nv40->nvws->channel->vram->handle,
-			  nv40->nvws->channel->gart->handle);
-		so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1);
-		so_reloc (so, nv40_surface_buffer(&rt[2]->base), rt[2]->base.offset, rt_flags |
-			  NOUVEAU_BO_LOW, 0, 0);
-		so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1);
+		so_method(so, curie, NV40TCL_DMA_COLOR2, 1);
+		so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0,
+			      rt_flags | NOUVEAU_BO_OR,
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, curie, NV40TCL_COLOR2_OFFSET, 1);
+		so_reloc (so, nv40_surface_buffer(&rt[2]->base),
+			      rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+			      0, 0);
+		so_method(so, curie, NV40TCL_COLOR2_PITCH, 1);
 		so_data  (so, rt[2]->pitch);
 	}
 
 	if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) {
-		so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1);
-		so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, rt_flags | NOUVEAU_BO_OR,
-			  nv40->nvws->channel->vram->handle,
-			  nv40->nvws->channel->gart->handle);
-		so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1);
-		so_reloc (so, nv40_surface_buffer(&rt[3]->base), rt[3]->base.offset, rt_flags |
-			  NOUVEAU_BO_LOW, 0, 0);
-		so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1);
+		so_method(so, curie, NV40TCL_DMA_COLOR3, 1);
+		so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0,
+			      rt_flags | NOUVEAU_BO_OR,
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, curie, NV40TCL_COLOR3_OFFSET, 1);
+		so_reloc (so, nv40_surface_buffer(&rt[3]->base),
+			      rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW,
+			      0, 0);
+		so_method(so, curie, NV40TCL_COLOR3_PITCH, 1);
 		so_data  (so, rt[3]->pitch);
 	}
 
 	if (zeta_format) {
-		so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1);
-		so_reloc (so, nv40_surface_buffer(&zeta->base), 0, rt_flags | NOUVEAU_BO_OR,
-			  nv40->nvws->channel->vram->handle,
-			  nv40->nvws->channel->gart->handle);
-		so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1);
-		so_reloc (so, nv40_surface_buffer(&zeta->base), zeta->base.offset, rt_flags |
-			  NOUVEAU_BO_LOW, 0, 0);
-		so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1);
+		so_method(so, curie, NV40TCL_DMA_ZETA, 1);
+		so_reloc (so, nv40_surface_buffer(&zeta->base), 0,
+			      rt_flags | NOUVEAU_BO_OR,
+			      chan->vram->handle, chan->gart->handle);
+		so_method(so, curie, NV40TCL_ZETA_OFFSET, 1);
+		so_reloc (so, nv40_surface_buffer(&zeta->base),
+			      zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0);
+		so_method(so, curie, NV40TCL_ZETA_PITCH, 1);
 		so_data  (so, zeta->pitch);
 	}
 
-	so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1);
+	so_method(so, curie, NV40TCL_RT_ENABLE, 1);
 	so_data  (so, rt_enable);
-	so_method(so, nv40->screen->curie, NV40TCL_RT_HORIZ, 3);
+	so_method(so, curie, NV40TCL_RT_HORIZ, 3);
 	so_data  (so, (w << 16) | 0);
 	so_data  (so, (h << 16) | 0);
 	so_data  (so, rt_format);
-	so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_HORIZ, 2);
+	so_method(so, curie, NV40TCL_VIEWPORT_HORIZ, 2);
 	so_data  (so, (w << 16) | 0);
 	so_data  (so, (h << 16) | 0);
-	so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
+	so_method(so, curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
 	so_data  (so, ((w - 1) << 16) | 0);
 	so_data  (so, ((h - 1) << 16) | 0);
-	so_method(so, nv40->screen->curie, 0x1d88, 1);
+	so_method(so, curie, 0x1d88, 1);
 	so_data  (so, (1 << 12) | h);
 
 	so_ref(so, &nv40->state.hw[NV40_STATE_FB]);
diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c
index 4abddba..24bd116 100644
--- a/src/gallium/drivers/nv40/nv40_vbo.c
+++ b/src/gallium/drivers/nv40/nv40_vbo.c
@@ -168,7 +168,7 @@
 		 unsigned mode, unsigned start, unsigned count)
 {
 	struct nv40_context *nv40 = nv40_context(pipe);
-	struct nouveau_channel *chan = nv40->nvws->channel;
+	struct nouveau_channel *chan = nv40->screen->base.channel;
 	unsigned restart;
 
 	nv40_vbo_set_idxbuf(nv40, NULL, 0);
@@ -227,7 +227,7 @@
 nv40_draw_elements_u08(struct nv40_context *nv40, void *ib,
 		       unsigned mode, unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv40->nvws->channel;
+	struct nouveau_channel *chan = nv40->screen->base.channel;
 
 	while (count) {
 		uint8_t *elts = (uint8_t *)ib + start;
@@ -276,7 +276,7 @@
 nv40_draw_elements_u16(struct nv40_context *nv40, void *ib,
 		       unsigned mode, unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv40->nvws->channel;
+	struct nouveau_channel *chan = nv40->screen->base.channel;
 
 	while (count) {
 		uint16_t *elts = (uint16_t *)ib + start;
@@ -325,7 +325,7 @@
 nv40_draw_elements_u32(struct nv40_context *nv40, void *ib,
 		       unsigned mode, unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv40->nvws->channel;
+	struct nouveau_channel *chan = nv40->screen->base.channel;
 
 	while (count) {
 		uint32_t *elts = (uint32_t *)ib + start;
@@ -400,7 +400,7 @@
 		       unsigned mode, unsigned start, unsigned count)
 {
 	struct nv40_context *nv40 = nv40_context(pipe);
-	struct nouveau_channel *chan = nv40->nvws->channel;
+	struct nouveau_channel *chan = nv40->screen->base.channel;
 	unsigned restart;
 
 	while (count) {
diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c
index 33427a1..e0b2d28 100644
--- a/src/gallium/drivers/nv50/nv50_clear.c
+++ b/src/gallium/drivers/nv50/nv50_clear.c
@@ -31,7 +31,7 @@
 	   const float *rgba, double depth, unsigned stencil)
 {
 	struct nv50_context *nv50 = nv50_context(pipe);
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->base.channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 	struct pipe_framebuffer_state *fb = &nv50->framebuffer;
 	unsigned mode = 0, i;
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
index a511f65..e02afc4 100644
--- a/src/gallium/drivers/nv50/nv50_context.c
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -33,7 +33,7 @@
 {
 	struct nv50_context *nv50 = (struct nv50_context *)pipe;
 	
-	FIRE_RING(nv50->screen->nvws->channel);
+	FIRE_RING(nv50->screen->base.channel);
 }
 
 static void
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index bc85329..9d6427e 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -2215,7 +2215,7 @@
 nv50_program_upload_data(struct nv50_context *nv50, float *map,
 			unsigned start, unsigned count, unsigned cbuf)
 {
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->base.channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 
 	while (count) {
@@ -2235,7 +2235,6 @@
 static void
 nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
 {
-	struct nouveau_winsys *nvws = nv50->screen->nvws;
 	struct pipe_winsys *ws = nv50->pipe.winsys;
 
 	if (!p->data[0] && p->immd_nr) {
@@ -2288,7 +2287,7 @@
 static void
 nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p)
 {
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->base.channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 	struct nv50_program_exec *e;
 	struct nouveau_stateobj *so;
@@ -2353,14 +2352,14 @@
 
 	start = 0; count = p->exec_size;
 	while (count) {
-		struct nouveau_winsys *nvws = nv50->screen->nvws;
+		struct nouveau_channel *chan = nv50->screen->base.channel;
 		unsigned nr;
 
-		so_emit(nvws, so);
+		so_emit(chan, so);
 
 		nr = MIN2(count, 2047);
-		nr = MIN2(nvws->channel->pushbuf->remaining, nr);
-		if (nvws->channel->pushbuf->remaining < (nr + 3)) {
+		nr = MIN2(chan->pushbuf->remaining, nr);
+		if (chan->pushbuf->remaining < (nr + 3)) {
 			FIRE_RING(chan);
 			continue;
 		}
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
index 4d05eea..c77ffe8 100644
--- a/src/gallium/drivers/nv50/nv50_query.c
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -71,7 +71,7 @@
 nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq)
 {
 	struct nv50_context *nv50 = nv50_context(pipe);
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->base.channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 	struct nv50_query *q = nv50_query(pq);
 
@@ -87,7 +87,7 @@
 nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
 {
 	struct nv50_context *nv50 = nv50_context(pipe);
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->base.channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 	struct nv50_query *q = nv50_query(pq);
 	struct nouveau_bo *bo = nouveau_bo(q->buffer);
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index 709b741..7904b51 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -145,10 +145,9 @@
 }
 
 struct pipe_screen *
-nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws)
+nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 {
 	struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen);
-	struct nouveau_device *dev = nvws->channel->device;
 	struct nouveau_channel *chan;
 	struct pipe_screen *pscreen;
 	struct nouveau_stateobj *so;
@@ -160,15 +159,12 @@
 		return NULL;
 	pscreen = &screen->base.base;
 
-	ret = nouveau_screen_init(&screen->base, nvws->channel->device);
+	ret = nouveau_screen_init(&screen->base, dev);
 	if (ret) {
 		nv50_screen_destroy(pscreen);
 		return NULL;
 	}
-	screen->base.channel = chan = nvws->channel;
-
-        /* Setup the pipe */
-	screen->nvws = nvws;
+	chan = screen->base.channel;
 
 	pscreen->winsys = ws;
 	pscreen->destroy = nv50_screen_destroy;
@@ -243,7 +239,7 @@
 	so_data  (so, screen->sync->handle);
 	so_data  (so, chan->vram->handle);
 	so_data  (so, chan->vram->handle);
-	so_emit(nvws, so);
+	so_emit(chan, so);
 	so_ref (NULL, &so);
 
 	/* Static 2D init */
@@ -259,7 +255,7 @@
 	so_data  (so, 0);
 	so_method(so, screen->eng2d, 0x0888, 1);
 	so_data  (so, 1);
-	so_emit(nvws, so);
+	so_emit(chan, so);
 	so_ref(NULL, &so);
 
 	/* Static tesla init */
@@ -411,7 +407,7 @@
 	so_method(so, screen->tesla, 0x1458, 1);
 	so_data  (so, 1);
 
-	so_emit(nvws, so);
+	so_emit(chan, so);
 	so_ref (so, &screen->static_init);
 	so_ref (NULL, &so);
 	nouveau_pushbuf_flush(chan, 0);
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
index d1f0ccd..9e70d4b 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -131,7 +131,7 @@
 nv50_state_emit(struct nv50_context *nv50)
 {
 	struct nv50_screen *screen = nv50->screen;
-	struct nouveau_winsys *nvws = screen->nvws;
+	struct nouveau_channel *chan = screen->base.channel;
 
 	if (nv50->pctx_id != screen->cur_pctx) {
 		nv50->state.dirty |= 0xffffffff;
@@ -139,40 +139,40 @@
 	}
 
 	if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER)
-		so_emit(nvws, nv50->state.fb);
+		so_emit(chan, nv50->state.fb);
 	if (nv50->state.dirty & NV50_NEW_BLEND)
-		so_emit(nvws, nv50->state.blend);
+		so_emit(chan, nv50->state.blend);
 	if (nv50->state.dirty & NV50_NEW_ZSA)
-		so_emit(nvws, nv50->state.zsa);
+		so_emit(chan, nv50->state.zsa);
 	if (nv50->state.dirty & NV50_NEW_VERTPROG)
-		so_emit(nvws, nv50->state.vertprog);
+		so_emit(chan, nv50->state.vertprog);
 	if (nv50->state.dirty & NV50_NEW_FRAGPROG)
-		so_emit(nvws, nv50->state.fragprog);
+		so_emit(chan, nv50->state.fragprog);
 	if (nv50->state.dirty & NV50_NEW_RASTERIZER)
-		so_emit(nvws, nv50->state.rast);
+		so_emit(chan, nv50->state.rast);
 	if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR)
-		so_emit(nvws, nv50->state.blend_colour);
+		so_emit(chan, nv50->state.blend_colour);
 	if (nv50->state.dirty & NV50_NEW_STIPPLE)
-		so_emit(nvws, nv50->state.stipple);
+		so_emit(chan, nv50->state.stipple);
 	if (nv50->state.dirty & NV50_NEW_SCISSOR)
-		so_emit(nvws, nv50->state.scissor);
+		so_emit(chan, nv50->state.scissor);
 	if (nv50->state.dirty & NV50_NEW_VIEWPORT)
-		so_emit(nvws, nv50->state.viewport);
+		so_emit(chan, nv50->state.viewport);
 	if (nv50->state.dirty & NV50_NEW_SAMPLER)
-		so_emit(nvws, nv50->state.tsc_upload);
+		so_emit(chan, nv50->state.tsc_upload);
 	if (nv50->state.dirty & NV50_NEW_TEXTURE)
-		so_emit(nvws, nv50->state.tic_upload);
+		so_emit(chan, nv50->state.tic_upload);
 	if (nv50->state.dirty & NV50_NEW_ARRAYS) {
-		so_emit(nvws, nv50->state.vtxfmt);
-		so_emit(nvws, nv50->state.vtxbuf);
+		so_emit(chan, nv50->state.vtxfmt);
+		so_emit(chan, nv50->state.vtxbuf);
 	}
 	nv50->state.dirty = 0;
 
-	so_emit_reloc_markers(nvws, nv50->state.fb);
-	so_emit_reloc_markers(nvws, nv50->state.vertprog);
-	so_emit_reloc_markers(nvws, nv50->state.fragprog);
-	so_emit_reloc_markers(nvws, nv50->state.vtxbuf);
-	so_emit_reloc_markers(nvws, nv50->screen->static_init);
+	so_emit_reloc_markers(chan, nv50->state.fb);
+	so_emit_reloc_markers(chan, nv50->state.vertprog);
+	so_emit_reloc_markers(chan, nv50->state.fragprog);
+	so_emit_reloc_markers(chan, nv50->state.vtxbuf);
+	so_emit_reloc_markers(chan, nv50->screen->static_init);
 }
 
 boolean
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index 121eddf..cd4e7ef 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -52,7 +52,7 @@
 nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
 {
 	struct nv50_miptree *mt = nv50_miptree(ps->texture);
-	struct nouveau_channel *chan = screen->nvws->channel;
+	struct nouveau_channel *chan = screen->eng2d->channel;
 	struct nouveau_grobj *eng2d = screen->eng2d;
 	struct nouveau_bo *bo = nouveau_bo(nv50_miptree(ps->texture)->buffer);
  	int format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT;
@@ -104,7 +104,7 @@
 		     int dx, int dy, struct pipe_surface *src, int sx, int sy,
 		     int w, int h)
 {
-	struct nouveau_channel *chan = screen->nvws->channel;
+	struct nouveau_channel *chan = screen->eng2d->channel;
 	struct nouveau_grobj *eng2d = screen->eng2d;
 	int ret;
 
@@ -161,7 +161,7 @@
 {
 	struct nv50_context *nv50 = (struct nv50_context *)pipe;
 	struct nv50_screen *screen = nv50->screen;
-	struct nouveau_channel *chan = screen->nvws->channel;
+	struct nouveau_channel *chan = screen->eng2d->channel;
 	struct nouveau_grobj *eng2d = screen->eng2d;
 	int format, ret;
 
diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
index 5f1e430..a0a2099 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -24,8 +24,7 @@
 			unsigned src_reloc, unsigned dst_reloc)
 {
 	struct nv50_screen *screen = nv50_screen(pscreen);
-	struct nouveau_winsys *nvws = screen->nvws;
-	struct nouveau_channel *chan = nvws->channel;
+	struct nouveau_channel *chan = screen->m2mf->channel;
 	struct nouveau_grobj *m2mf = screen->m2mf;
 	struct nouveau_bo *src_bo = nouveau_bo(src);
 	struct nouveau_bo *dst_bo = nouveau_bo(dst);
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
index 6f4981d..a9b53a0 100644
--- a/src/gallium/drivers/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -53,7 +53,7 @@
 		 unsigned count)
 {
 	struct nv50_context *nv50 = nv50_context(pipe);
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->tesla->channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 
 	nv50_state_validate(nv50);
@@ -83,7 +83,7 @@
 nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map,
 			      unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->tesla->channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 
 	map += start;
@@ -112,7 +112,7 @@
 nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map,
 			      unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->tesla->channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 
 	map += start;
@@ -141,7 +141,7 @@
 nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint8_t *map,
 			      unsigned start, unsigned count)
 {
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->tesla->channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 
 	map += start;
@@ -163,7 +163,7 @@
 		   unsigned mode, unsigned start, unsigned count)
 {
 	struct nv50_context *nv50 = nv50_context(pipe);
-	struct nouveau_channel *chan = nv50->screen->nvws->channel;
+	struct nouveau_channel *chan = nv50->screen->tesla->channel;
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 	struct pipe_winsys *ws = pipe->winsys;
 	void *map = ws->buffer_map(ws, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ);
diff --git a/src/gallium/winsys/drm/nouveau/drm/Makefile b/src/gallium/winsys/drm/nouveau/drm/Makefile
index 2da78d8..621ad2a 100644
--- a/src/gallium/winsys/drm/nouveau/drm/Makefile
+++ b/src/gallium/winsys/drm/nouveau/drm/Makefile
@@ -4,8 +4,7 @@
 LIBNAME = nouveaudrm
 
 C_SOURCES = nouveau_drm_api.c \
-	    nouveau_winsys_pipe.c \
-	    nouveau_winsys.c
+	    nouveau_winsys_pipe.c
 
 LIBRARY_INCLUDES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-I)
 LIBRARY_DEFINES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-other)
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
index b355a13..22c53f6 100644
--- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
@@ -70,10 +70,9 @@
 {
 	struct dri1_create_screen_arg *dri1 = (void *)arg;
 	struct pipe_winsys *ws;
-	struct nouveau_winsys *nvws;
 	struct nouveau_device *dev = NULL;
 	struct pipe_screen *(*init)(struct pipe_winsys *,
-				    struct nouveau_winsys *);
+				    struct nouveau_device *);
 	int ret;
 
 	ret = nouveau_device_open_existing(&dev, 0, fd, 0);
@@ -114,13 +113,7 @@
 		return NULL;
 	}
 
-	nvws = nouveau_winsys_new(ws);
-	if (!nvws) {
-		ws->destroy(ws);
-		return NULL;
-	}
-
-	nouveau_pipe_winsys(ws)->pscreen = init(ws, nvws);
+	nouveau_pipe_winsys(ws)->pscreen = init(ws, dev);
 	if (!nouveau_pipe_winsys(ws)->pscreen) {
 		ws->destroy(ws);
 		return NULL;
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c
deleted file mode 100644
index c03e6dd..0000000
--- a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "util/u_memory.h"
-
-#include "nouveau_winsys_pipe.h"
-
-struct nouveau_winsys *
-nouveau_winsys_new(struct pipe_winsys *ws)
-{
-	struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws);
-	struct nouveau_winsys *nvws;
-
-	nvws = CALLOC_STRUCT(nouveau_winsys);
-	if (!nvws)
-		return NULL;
-
-	nvws->ws		= ws;
-	nvws->channel		= nvpws->channel;
-
-	return nvws;
-}
-