Merge branch '3.2-without-smb2' of git://git.samba.org/sfrench/cifs-2.6
[pandora-kernel.git] / drivers / gpu / drm / nouveau / nvc0_grhub.fuc
1 /* fuc microcode for nvc0 PGRAPH/HUB
2  *
3  * Copyright 2011 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: Ben Skeggs
24  */
25
26 /* To build:
27  *    m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h
28  */
29
30 .section nvc0_grhub_data
31 include(`nvc0_graph.fuc')
32 gpc_count:              .b32 0
33 rop_count:              .b32 0
34 cmd_queue:              queue_init
35 hub_mmio_list_head:     .b32 0
36 hub_mmio_list_tail:     .b32 0
37
38 ctx_current:            .b32 0
39
40 chipsets:
41 .b8  0xc0 0 0 0
42 .b16 nvc0_hub_mmio_head
43 .b16 nvc0_hub_mmio_tail
44 .b8  0xc1 0 0 0
45 .b16 nvc0_hub_mmio_head
46 .b16 nvc1_hub_mmio_tail
47 .b8  0xc3 0 0 0
48 .b16 nvc0_hub_mmio_head
49 .b16 nvc0_hub_mmio_tail
50 .b8  0xc4 0 0 0
51 .b16 nvc0_hub_mmio_head
52 .b16 nvc0_hub_mmio_tail
53 .b8  0xc8 0 0 0
54 .b16 nvc0_hub_mmio_head
55 .b16 nvc0_hub_mmio_tail
56 .b8  0xce 0 0 0
57 .b16 nvc0_hub_mmio_head
58 .b16 nvc0_hub_mmio_tail
59 .b8  0xcf 0 0 0
60 .b16 nvc0_hub_mmio_head
61 .b16 nvc0_hub_mmio_tail
62 .b8  0 0 0 0
63
64 nvc0_hub_mmio_head:
65 mmctx_data(0x17e91c, 2)
66 mmctx_data(0x400204, 2)
67 mmctx_data(0x404004, 11)
68 mmctx_data(0x404044, 1)
69 mmctx_data(0x404094, 14)
70 mmctx_data(0x4040d0, 7)
71 mmctx_data(0x4040f8, 1)
72 mmctx_data(0x404130, 3)
73 mmctx_data(0x404150, 3)
74 mmctx_data(0x404164, 2)
75 mmctx_data(0x404174, 3)
76 mmctx_data(0x404200, 8)
77 mmctx_data(0x404404, 14)
78 mmctx_data(0x404460, 4)
79 mmctx_data(0x404480, 1)
80 mmctx_data(0x404498, 1)
81 mmctx_data(0x404604, 4)
82 mmctx_data(0x404618, 32)
83 mmctx_data(0x404698, 21)
84 mmctx_data(0x4046f0, 2)
85 mmctx_data(0x404700, 22)
86 mmctx_data(0x405800, 1)
87 mmctx_data(0x405830, 3)
88 mmctx_data(0x405854, 1)
89 mmctx_data(0x405870, 4)
90 mmctx_data(0x405a00, 2)
91 mmctx_data(0x405a18, 1)
92 mmctx_data(0x406020, 1)
93 mmctx_data(0x406028, 4)
94 mmctx_data(0x4064a8, 2)
95 mmctx_data(0x4064b4, 2)
96 mmctx_data(0x407804, 1)
97 mmctx_data(0x40780c, 6)
98 mmctx_data(0x4078bc, 1)
99 mmctx_data(0x408000, 7)
100 mmctx_data(0x408064, 1)
101 mmctx_data(0x408800, 3)
102 mmctx_data(0x408900, 4)
103 mmctx_data(0x408980, 1)
104 nvc0_hub_mmio_tail:
105 mmctx_data(0x4064c0, 2)
106 nvc1_hub_mmio_tail:
107
108 .align 256
109 chan_data:
110 chan_mmio_count:        .b32 0
111 chan_mmio_address:      .b32 0
112
113 .align 256
114 xfer_data:              .b32 0
115
116 .section nvc0_grhub_code
117 bra init
118 define(`include_code')
119 include(`nvc0_graph.fuc')
120
121 // reports an exception to the host
122 //
123 // In: $r15 error code (see nvc0_graph.fuc)
124 //
125 error:
126         push $r14
127         mov $r14 0x814
128         shl b32 $r14 6
129         iowr I[$r14 + 0x000] $r15       // CC_SCRATCH[5] = error code
130         mov $r14 0xc1c
131         shl b32 $r14 6
132         mov $r15 1
133         iowr I[$r14 + 0x000] $r15       // INTR_UP_SET
134         pop $r14
135         ret
136
137 // HUB fuc initialisation, executed by triggering ucode start, will
138 // fall through to main loop after completion.
139 //
140 // Input:
141 //   CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh)
142 //
143 // Output:
144 //   CC_SCRATCH[0]:
145 //           31:31: set to signal completion
146 //   CC_SCRATCH[1]:
147 //            31:0: total PGRAPH context size
148 //
149 init:
150         clear b32 $r0
151         mov $sp $r0
152         mov $xdbase $r0
153
154         // enable fifo access
155         mov $r1 0x1200
156         mov $r2 2
157         iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE
158
159         // setup i0 handler, and route all interrupts to it
160         mov $r1 ih
161         mov $iv0 $r1
162         mov $r1 0x400
163         iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH
164
165         // route HUB_CHANNEL_SWITCH to fuc interrupt 8
166         mov $r3 0x404
167         shl b32 $r3 6
168         mov $r2 0x2003          // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8
169         iowr I[$r3 + 0x000] $r2
170
171         // not sure what these are, route them because NVIDIA does, and
172         // the IRQ handler will signal the host if we ever get one.. we
173         // may find out if/why we need to handle these if so..
174         //
175         mov $r2 0x2004
176         iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9
177         mov $r2 0x200b
178         iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10
179         mov $r2 0x200c
180         iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15
181
182         // enable all INTR_UP interrupts
183         mov $r2 0xc24
184         shl b32 $r2 6
185         not b32 $r3 $r0
186         iowr I[$r2] $r3
187
188         // enable fifo, ctxsw, 9, 10, 15 interrupts
189         mov $r2 -0x78fc         // 0x8704
190         sethi $r2 0
191         iowr I[$r1 + 0x000] $r2 // INTR_EN_SET
192
193         // fifo level triggered, rest edge
194         sub b32 $r1 0x100
195         mov $r2 4
196         iowr I[$r1] $r2
197
198         // enable interrupts
199         bset $flags ie0
200
201         // fetch enabled GPC/ROP counts
202         mov $r14 -0x69fc        // 0x409604
203         sethi $r14 0x400000
204         call nv_rd32
205         extr $r1 $r15 16:20
206         st b32 D[$r0 + rop_count] $r1
207         and $r15 0x1f
208         st b32 D[$r0 + gpc_count] $r15
209
210         // set BAR_REQMASK to GPC mask
211         mov $r1 1
212         shl b32 $r1 $r15
213         sub b32 $r1 1
214         mov $r2 0x40c
215         shl b32 $r2 6
216         iowr I[$r2 + 0x000] $r1
217         iowr I[$r2 + 0x100] $r1
218
219         // find context data for this chipset
220         mov $r2 0x800
221         shl b32 $r2 6
222         iord $r2 I[$r2 + 0x000]         // CC_SCRATCH[0]
223         mov $r15 chipsets - 8
224         init_find_chipset:
225                 add b32 $r15 8
226                 ld b32 $r3 D[$r15 + 0x00]
227                 cmpu b32 $r3 $r2
228                 bra e init_context
229                 cmpu b32 $r3 0
230                 bra ne init_find_chipset
231                 // unknown chipset
232                 ret
233
234         // context size calculation, reserve first 256 bytes for use by fuc
235         init_context:
236         mov $r1 256
237
238         // calculate size of mmio context data
239         ld b16 $r14 D[$r15 + 4]
240         ld b16 $r15 D[$r15 + 6]
241         sethi $r14 0
242         st b32 D[$r0 + hub_mmio_list_head] $r14
243         st b32 D[$r0 + hub_mmio_list_tail] $r15
244         call mmctx_size
245
246         // set mmctx base addresses now so we don't have to do it later,
247         // they don't (currently) ever change
248         mov $r3 0x700
249         shl b32 $r3 6
250         shr b32 $r4 $r1 8
251         iowr I[$r3 + 0x000] $r4         // MMCTX_SAVE_SWBASE
252         iowr I[$r3 + 0x100] $r4         // MMCTX_LOAD_SWBASE
253         add b32 $r3 0x1300
254         add b32 $r1 $r15
255         shr b32 $r15 2
256         iowr I[$r3 + 0x000] $r15        // MMCTX_LOAD_COUNT, wtf for?!?
257
258         // strands, base offset needs to be aligned to 256 bytes
259         shr b32 $r1 8
260         add b32 $r1 1
261         shl b32 $r1 8
262         mov b32 $r15 $r1
263         call strand_ctx_init
264         add b32 $r1 $r15
265
266         // initialise each GPC in sequence by passing in the offset of its
267         // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which
268         // has previously been uploaded by the host) running.
269         //
270         // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31
271         // when it has completed, and return the size of its context data
272         // in GPCn_CC_SCRATCH[1]
273         //
274         ld b32 $r3 D[$r0 + gpc_count]
275         mov $r4 0x2000
276         sethi $r4 0x500000
277         init_gpc:
278                 // setup, and start GPC ucode running
279                 add b32 $r14 $r4 0x804
280                 mov b32 $r15 $r1
281                 call nv_wr32                    // CC_SCRATCH[1] = ctx offset
282                 add b32 $r14 $r4 0x800
283                 mov b32 $r15 $r2
284                 call nv_wr32                    // CC_SCRATCH[0] = chipset
285                 add b32 $r14 $r4 0x10c
286                 clear b32 $r15
287                 call nv_wr32
288                 add b32 $r14 $r4 0x104
289                 call nv_wr32                    // ENTRY
290                 add b32 $r14 $r4 0x100
291                 mov $r15 2                      // CTRL_START_TRIGGER
292                 call nv_wr32                    // CTRL
293
294                 // wait for it to complete, and adjust context size
295                 add b32 $r14 $r4 0x800
296                 init_gpc_wait:
297                         call nv_rd32
298                         xbit $r15 $r15 31
299                         bra e init_gpc_wait
300                 add b32 $r14 $r4 0x804
301                 call nv_rd32
302                 add b32 $r1 $r15
303
304                 // next!
305                 add b32 $r4 0x8000
306                 sub b32 $r3 1
307                 bra ne init_gpc
308
309         // save context size, and tell host we're ready
310         mov $r2 0x800
311         shl b32 $r2 6
312         iowr I[$r2 + 0x100] $r1         // CC_SCRATCH[1]  = context size
313         add b32 $r2 0x800
314         clear b32 $r1
315         bset $r1 31
316         iowr I[$r2 + 0x000] $r1         // CC_SCRATCH[0] |= 0x80000000
317
318 // Main program loop, very simple, sleeps until woken up by the interrupt
319 // handler, pulls a command from the queue and executes its handler
320 //
321 main:
322         // sleep until we have something to do
323         bset $flags $p0
324         sleep $p0
325         mov $r13 cmd_queue
326         call queue_get
327         bra $p1 main
328
329         // context switch, requested by GPU?
330         cmpu b32 $r14 0x4001
331         bra ne main_not_ctx_switch
332                 trace_set(T_AUTO)
333                 mov $r1 0xb00
334                 shl b32 $r1 6
335                 iord $r2 I[$r1 + 0x100]         // CHAN_NEXT
336                 iord $r1 I[$r1 + 0x000]         // CHAN_CUR
337
338                 xbit $r3 $r1 31
339                 bra e chsw_no_prev
340                         xbit $r3 $r2 31
341                         bra e chsw_prev_no_next
342                                 push $r2
343                                 mov b32 $r2 $r1
344                                 trace_set(T_SAVE)
345                                 bclr $flags $p1
346                                 bset $flags $p2
347                                 call ctx_xfer
348                                 trace_clr(T_SAVE);
349                                 pop $r2
350                                 trace_set(T_LOAD);
351                                 bset $flags $p1
352                                 call ctx_xfer
353                                 trace_clr(T_LOAD);
354                                 bra chsw_done
355                         chsw_prev_no_next:
356                                 push $r2
357                                 mov b32 $r2 $r1
358                                 bclr $flags $p1
359                                 bclr $flags $p2
360                                 call ctx_xfer
361                                 pop $r2
362                                 mov $r1 0xb00
363                                 shl b32 $r1 6
364                                 iowr I[$r1] $r2
365                                 bra chsw_done
366                 chsw_no_prev:
367                         xbit $r3 $r2 31
368                         bra e chsw_done
369                                 bset $flags $p1
370                                 bclr $flags $p2
371                                 call ctx_xfer
372
373                 // ack the context switch request
374                 chsw_done:
375                 mov $r1 0xb0c
376                 shl b32 $r1 6
377                 mov $r2 1
378                 iowr I[$r1 + 0x000] $r2         // 0x409b0c
379                 trace_clr(T_AUTO)
380                 bra main
381
382         // request to set current channel? (*not* a context switch)
383         main_not_ctx_switch:
384         cmpu b32 $r14 0x0001
385         bra ne main_not_ctx_chan
386                 mov b32 $r2 $r15
387                 call ctx_chan
388                 bra main_done
389
390         // request to store current channel context?
391         main_not_ctx_chan:
392         cmpu b32 $r14 0x0002
393         bra ne main_not_ctx_save
394                 trace_set(T_SAVE)
395                 bclr $flags $p1
396                 bclr $flags $p2
397                 call ctx_xfer
398                 trace_clr(T_SAVE)
399                 bra main_done
400
401         main_not_ctx_save:
402                 shl b32 $r15 $r14 16
403                 or $r15 E_BAD_COMMAND
404                 call error
405                 bra main
406
407         main_done:
408         mov $r1 0x820
409         shl b32 $r1 6
410         clear b32 $r2
411         bset $r2 31
412         iowr I[$r1 + 0x000] $r2         // CC_SCRATCH[0] |= 0x80000000
413         bra main
414
415 // interrupt handler
416 ih:
417         push $r8
418         mov $r8 $flags
419         push $r8
420         push $r9
421         push $r10
422         push $r11
423         push $r13
424         push $r14
425         push $r15
426
427         // incoming fifo command?
428         iord $r10 I[$r0 + 0x200]        // INTR
429         and $r11 $r10 0x00000004
430         bra e ih_no_fifo
431                 // queue incoming fifo command for later processing
432                 mov $r11 0x1900
433                 mov $r13 cmd_queue
434                 iord $r14 I[$r11 + 0x100]       // FIFO_CMD
435                 iord $r15 I[$r11 + 0x000]       // FIFO_DATA
436                 call queue_put
437                 add b32 $r11 0x400
438                 mov $r14 1
439                 iowr I[$r11 + 0x000] $r14       // FIFO_ACK
440
441         // context switch request?
442         ih_no_fifo:
443         and $r11 $r10 0x00000100
444         bra e ih_no_ctxsw
445                 // enqueue a context switch for later processing
446                 mov $r13 cmd_queue
447                 mov $r14 0x4001
448                 call queue_put
449
450         // anything we didn't handle, bring it to the host's attention
451         ih_no_ctxsw:
452         mov $r11 0x104
453         not b32 $r11
454         and $r11 $r10 $r11
455         bra e ih_no_other
456                 mov $r10 0xc1c
457                 shl b32 $r10 6
458                 iowr I[$r10] $r11       // INTR_UP_SET
459
460         // ack, and wake up main()
461         ih_no_other:
462         iowr I[$r0 + 0x100] $r10        // INTR_ACK
463
464         pop $r15
465         pop $r14
466         pop $r13
467         pop $r11
468         pop $r10
469         pop $r9
470         pop $r8
471         mov $flags $r8
472         pop $r8
473         bclr $flags $p0
474         iret
475
476 // Not real sure, but, MEM_CMD 7 will hang forever if this isn't done
477 ctx_4160s:
478         mov $r14 0x4160
479         sethi $r14 0x400000
480         mov $r15 1
481         call nv_wr32
482         ctx_4160s_wait:
483                 call nv_rd32
484                 xbit $r15 $r15 4
485                 bra e ctx_4160s_wait
486         ret
487
488 // Without clearing again at end of xfer, some things cause PGRAPH
489 // to hang with STATUS=0x00000007 until it's cleared.. fbcon can
490 // still function with it set however...
491 ctx_4160c:
492         mov $r14 0x4160
493         sethi $r14 0x400000
494         clear b32 $r15
495         call nv_wr32
496         ret
497
498 // Again, not real sure
499 //
500 // In: $r15 value to set 0x404170 to
501 //
502 ctx_4170s:
503         mov $r14 0x4170
504         sethi $r14 0x400000
505         or $r15 0x10
506         call nv_wr32
507         ret
508
509 // Waits for a ctx_4170s() call to complete
510 //
511 ctx_4170w:
512         mov $r14 0x4170
513         sethi $r14 0x400000
514         call nv_rd32
515         and $r15 0x10
516         bra ne ctx_4170w
517         ret
518
519 // Disables various things, waits a bit, and re-enables them..
520 //
521 // Not sure how exactly this helps, perhaps "ENABLE" is not such a
522 // good description for the bits we turn off?  Anyways, without this,
523 // funny things happen.
524 //
525 ctx_redswitch:
526         mov $r14 0x614
527         shl b32 $r14 6
528         mov $r15 0x270
529         iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL
530         mov $r15 8
531         ctx_redswitch_delay:
532                 sub b32 $r15 1
533                 bra ne ctx_redswitch_delay
534         mov $r15 0x770
535         iowr I[$r14] $r15       // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL
536         ret
537
538 // Not a clue what this is for, except that unless the value is 0x10, the
539 // strand context is saved (and presumably restored) incorrectly..
540 //
541 // In: $r15 value to set to (0x00/0x10 are used)
542 //
543 ctx_86c:
544         mov $r14 0x86c
545         shl b32 $r14 6
546         iowr I[$r14] $r15       // HUB(0x86c) = val
547         mov $r14 -0x75ec
548         sethi $r14 0x400000
549         call nv_wr32            // ROP(0xa14) = val
550         mov $r14 -0x5794
551         sethi $r14 0x410000
552         call nv_wr32            // GPC(0x86c) = val
553         ret
554
555 // ctx_load - load's a channel's ctxctl data, and selects its vm
556 //
557 // In: $r2 channel address
558 //
559 ctx_load:
560         trace_set(T_CHAN)
561
562         // switch to channel, somewhat magic in parts..
563         mov $r10 12             // DONE_UNK12
564         call wait_donez
565         mov $r1 0xa24
566         shl b32 $r1 6
567         iowr I[$r1 + 0x000] $r0 // 0x409a24
568         mov $r3 0xb00
569         shl b32 $r3 6
570         iowr I[$r3 + 0x100] $r2 // CHAN_NEXT
571         mov $r1 0xa0c
572         shl b32 $r1 6
573         mov $r4 7
574         iowr I[$r1 + 0x000] $r2 // MEM_CHAN
575         iowr I[$r1 + 0x100] $r4 // MEM_CMD
576         ctx_chan_wait_0:
577                 iord $r4 I[$r1 + 0x100]
578                 and $r4 0x1f
579                 bra ne ctx_chan_wait_0
580         iowr I[$r3 + 0x000] $r2 // CHAN_CUR
581
582         // load channel header, fetch PGRAPH context pointer
583         mov $xtargets $r0
584         bclr $r2 31
585         shl b32 $r2 4
586         add b32 $r2 2
587
588         trace_set(T_LCHAN)
589         mov $r1 0xa04
590         shl b32 $r1 6
591         iowr I[$r1 + 0x000] $r2         // MEM_BASE
592         mov $r1 0xa20
593         shl b32 $r1 6
594         mov $r2 0x0002
595         sethi $r2 0x80000000
596         iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vram
597         mov $r1 0x10                    // chan + 0x0210
598         mov $r2 xfer_data
599         sethi $r2 0x00020000            // 16 bytes
600         xdld $r1 $r2
601         xdwait
602         trace_clr(T_LCHAN)
603
604         // update current context
605         ld b32 $r1 D[$r0 + xfer_data + 4]
606         shl b32 $r1 24
607         ld b32 $r2 D[$r0 + xfer_data + 0]
608         shr b32 $r2 8
609         or $r1 $r2
610         st b32 D[$r0 + ctx_current] $r1
611
612         // set transfer base to start of context, and fetch context header
613         trace_set(T_LCTXH)
614         mov $r2 0xa04
615         shl b32 $r2 6
616         iowr I[$r2 + 0x000] $r1         // MEM_BASE
617         mov $r2 1
618         mov $r1 0xa20
619         shl b32 $r1 6
620         iowr I[$r1 + 0x000] $r2         // MEM_TARGET = vm
621         mov $r1 chan_data
622         sethi $r1 0x00060000            // 256 bytes
623         xdld $r0 $r1
624         xdwait
625         trace_clr(T_LCTXH)
626
627         trace_clr(T_CHAN)
628         ret
629
630 // ctx_chan - handler for HUB_SET_CHAN command, will set a channel as
631 //            the active channel for ctxctl, but not actually transfer
632 //            any context data.  intended for use only during initial
633 //            context construction.
634 //
635 // In: $r2 channel address
636 //
637 ctx_chan:
638         call ctx_4160s
639         call ctx_load
640         mov $r10 12                     // DONE_UNK12
641         call wait_donez
642         mov $r1 0xa10
643         shl b32 $r1 6
644         mov $r2 5
645         iowr I[$r1 + 0x000] $r2         // MEM_CMD = 5 (???)
646         ctx_chan_wait:
647                 iord $r2 I[$r1 + 0x000]
648                 or $r2 $r2
649                 bra ne ctx_chan_wait
650         call ctx_4160c
651         ret
652
653 // Execute per-context state overrides list
654 //
655 // Only executed on the first load of a channel.  Might want to look into
656 // removing this and having the host directly modify the channel's context
657 // to change this state...  The nouveau DRM already builds this list as
658 // it's definitely needed for NVIDIA's, so we may as well use it for now
659 //
660 // Input: $r1 mmio list length
661 //
662 ctx_mmio_exec:
663         // set transfer base to be the mmio list
664         ld b32 $r3 D[$r0 + chan_mmio_address]
665         mov $r2 0xa04
666         shl b32 $r2 6
667         iowr I[$r2 + 0x000] $r3         // MEM_BASE
668
669         clear b32 $r3
670         ctx_mmio_loop:
671                 // fetch next 256 bytes of mmio list if necessary
672                 and $r4 $r3 0xff
673                 bra ne ctx_mmio_pull
674                         mov $r5 xfer_data
675                         sethi $r5 0x00060000    // 256 bytes
676                         xdld $r3 $r5
677                         xdwait
678
679                 // execute a single list entry
680                 ctx_mmio_pull:
681                 ld b32 $r14 D[$r4 + xfer_data + 0x00]
682                 ld b32 $r15 D[$r4 + xfer_data + 0x04]
683                 call nv_wr32
684
685                 // next!
686                 add b32 $r3 8
687                 sub b32 $r1 1
688                 bra ne ctx_mmio_loop
689
690         // set transfer base back to the current context
691         ctx_mmio_done:
692         ld b32 $r3 D[$r0 + ctx_current]
693         iowr I[$r2 + 0x000] $r3         // MEM_BASE
694
695         // disable the mmio list now, we don't need/want to execute it again
696         st b32 D[$r0 + chan_mmio_count] $r0
697         mov $r1 chan_data
698         sethi $r1 0x00060000            // 256 bytes
699         xdst $r0 $r1
700         xdwait
701         ret
702
703 // Transfer HUB context data between GPU and storage area
704 //
705 // In: $r2 channel address
706 //     $p1 clear on save, set on load
707 //     $p2 set if opposite direction done/will be done, so:
708 //              on save it means: "a load will follow this save"
709 //              on load it means: "a save preceeded this load"
710 //
711 ctx_xfer:
712         bra not $p1 ctx_xfer_pre
713         bra $p2 ctx_xfer_pre_load
714         ctx_xfer_pre:
715                 mov $r15 0x10
716                 call ctx_86c
717                 call ctx_4160s
718                 bra not $p1 ctx_xfer_exec
719
720         ctx_xfer_pre_load:
721                 mov $r15 2
722                 call ctx_4170s
723                 call ctx_4170w
724                 call ctx_redswitch
725                 clear b32 $r15
726                 call ctx_4170s
727                 call ctx_load
728
729         // fetch context pointer, and initiate xfer on all GPCs
730         ctx_xfer_exec:
731         ld b32 $r1 D[$r0 + ctx_current]
732         mov $r2 0x414
733         shl b32 $r2 6
734         iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset
735         mov $r14 -0x5b00
736         sethi $r14 0x410000
737         mov b32 $r15 $r1
738         call nv_wr32            // GPC_BCAST_WRCMD_DATA = ctx pointer
739         add b32 $r14 4
740         xbit $r15 $flags $p1
741         xbit $r2 $flags $p2
742         shl b32 $r2 1
743         or $r15 $r2
744         call nv_wr32            // GPC_BCAST_WRCMD_CMD = GPC_XFER(type)
745
746         // strands
747         mov $r1 0x4afc
748         sethi $r1 0x20000
749         mov $r2 0xc
750         iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x0c
751         call strand_wait
752         mov $r2 0x47fc
753         sethi $r2 0x20000
754         iowr I[$r2] $r0         // STRAND_FIRST_GENE(0x3f) = 0x00
755         xbit $r2 $flags $p1
756         add b32 $r2 3
757         iowr I[$r1] $r2         // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD)
758
759         // mmio context
760         xbit $r10 $flags $p1    // direction
761         or $r10 6               // first, last
762         mov $r11 0              // base = 0
763         ld b32 $r12 D[$r0 + hub_mmio_list_head]
764         ld b32 $r13 D[$r0 + hub_mmio_list_tail]
765         mov $r14 0              // not multi
766         call mmctx_xfer
767
768         // wait for GPCs to all complete
769         mov $r10 8              // DONE_BAR
770         call wait_doneo
771
772         // wait for strand xfer to complete
773         call strand_wait
774
775         // post-op
776         bra $p1 ctx_xfer_post
777                 mov $r10 12             // DONE_UNK12
778                 call wait_donez
779                 mov $r1 0xa10
780                 shl b32 $r1 6
781                 mov $r2 5
782                 iowr I[$r1] $r2         // MEM_CMD
783                 ctx_xfer_post_save_wait:
784                         iord $r2 I[$r1]
785                         or $r2 $r2
786                         bra ne ctx_xfer_post_save_wait
787
788         bra $p2 ctx_xfer_done
789         ctx_xfer_post:
790                 mov $r15 2
791                 call ctx_4170s
792                 clear b32 $r15
793                 call ctx_86c
794                 call strand_post
795                 call ctx_4170w
796                 clear b32 $r15
797                 call ctx_4170s
798
799                 bra not $p1 ctx_xfer_no_post_mmio
800                 ld b32 $r1 D[$r0 + chan_mmio_count]
801                 or $r1 $r1
802                 bra e ctx_xfer_no_post_mmio
803                         call ctx_mmio_exec
804
805                 ctx_xfer_no_post_mmio:
806                 call ctx_4160c
807
808         ctx_xfer_done:
809         ret
810
811 .align 256