Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / usb2 / hcd / ehci / qhtd.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: qhtd.fth
4\
5\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6\
7\ - Do no alter or remove copyright notices
8\
9\ - Redistribution and use of this software in source and binary forms, with
10\ or without modification, are permitted provided that the following
11\ conditions are met:
12\
13\ - Redistribution of source code must retain the above copyright notice,
14\ this list of conditions and the following disclaimer.
15\
16\ - Redistribution in binary form must reproduce the above copyright notice,
17\ this list of conditions and the following disclaimer in the
18\ documentation and/or other materials provided with the distribution.
19\
20\ Neither the name of Sun Microsystems, Inc. or the names of contributors
21\ may be used to endorse or promote products derived from this software
22\ without specific prior written permission.
23\
24\ This software is provided "AS IS," without a warranty of any kind.
25\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
26\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
27\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
28\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
29\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
30\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
31\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
32\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
33\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
34\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
35\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
36\
37\ You acknowledge that this software is not designed, licensed or
38\ intended for use in the design, construction, operation or maintenance of
39\ any nuclear facility.
40\
41\ ========== Copyright Header End ============================================
42id: @(#)qhtd.fth 1.1 07/01/24
43purpose: Data structures and manuipulation routines for EHCI USB Controller
44\ See license at end of file
45
46hex
47headers
48
49\ XXX Isochronous is not supported in the current version of the EHCI driver
50
51\ ---------------------------------------------------------------------------
52\ Data structures for this implementation of the EHCI USB Driver include:
53\ - qh-ptr pointer to the asynchronous list of QHs
54\ - framelist pointer to the Periodic Frame List
55\ - intr internal array of interrupts
56\ ---------------------------------------------------------------------------
57
58\ Constants common to most EHCI data structures
591 constant TERMINATE
60
610 constant TYP_ITD
622 constant TYP_QH
634 constant TYP_SITD
646 constant TYP_FSTN
65
66\ Pipe type
670 constant pt-ctrl
681 constant pt-bulk
692 constant pt-intr
703 constant pt-iso
71
72\ ---------------------------------------------------------------------------
73\ Periodic Frame List as defined by the EHCI Spec; 4-KB aligned
74\
75\ Each entry is composed of: bit 0 TERMINATE
76\ bits 2:1 Pipe type
77\ bits 31:5 Frame List Link Pointer
78\ ---------------------------------------------------------------------------
79
80h# 1000 constant /align4kb
81
82d# 1024 dup constant #framelist \ # of entries in framelist
834 * constant /framelist \ Size of framelist
84
850 value framelist
860 value framelist-unaligned
870 value framelist-phys
88
89: framelist! ( n idx -- ) 4 * framelist + le-l! ;
90
91: init-framelist ( -- )
92 \ Allocate framelist
93 /framelist /align4kb aligned-alloc ( unaligned virt )
94 swap to framelist-unaligned ( virt )
95 dup to framelist ( virt )
96 /framelist true dma-map-in to framelist-phys ( )
97
98 \ Initialize framelist
99 #framelist 0 do TERMINATE i framelist! loop
100 framelist-phys periodic!
101;
102
103\ ---------------------------------------------------------------------------
104\ Internal interrupt list corresponding with the Frame List
105\ ---------------------------------------------------------------------------
106
107struct
108 4 field >intr-head
109 4 field >intr-tail
110dup constant /intr-entry
111#framelist * constant /intr \ Size of intr
112
1130 value intr \ Internal array of interrupts
114
115: 'intr ( idx -- adr ) /intr-entry * intr + ;
116: intr-head@ ( idx -- adr ) 'intr >intr-head l@ ;
117: intr-head! ( adr idx -- ) 'intr >intr-head l! ;
118: intr-tail@ ( idx -- adr ) 'intr >intr-tail l@ ;
119: intr-tail! ( adr idx -- ) 'intr >intr-tail l! ;
120
121: init-intr ( -- )
122 /intr alloc-mem dup to intr \ Allocate intr
123 /intr erase \ Initialize intr
124;
125
126\ ---------------------------------------------------------------------------
127\ Queue Element Transfer Descriptor (qTD) as defined by the EHCI Spec; 32-byte aligned
128\ ---------------------------------------------------------------------------
129
130struct \ Beginning of qTD
131 4 field >hcqtd-next \ Next qTD pointer
132 4 field >hcqtd-next-alt \ Alternate next qTD pointer
133 4 field >hcqtd-token \ qTD token
134 4 field >hcqtd-bptr0 \ Buffer pointer 0 (4KB aligned)
135 4 field >hcqtd-bptr1 \ Buffer pointer 1
136 4 field >hcqtd-bptr2 \ Buffer pointer 2
137 4 field >hcqtd-bptr3 \ Buffer pointer 3
138 4 field >hcqtd-bptr4 \ Buffer pointer 4
139 4 5 * field >hcqtd-xbptrs \ 64-bit buffer pointer extensions
140dup constant /hcqtd
141 \ Driver specific fields
142 4 field >qtd-phys \ Physical address of qTD
143 4 field >qtd-next \ Next qTD virtual address
144 4 field >qtd-buf \ Buffer virtual address
145 4 field >qtd-pbuf \ Buffer physical address
146 4 field >qtd-/buf \ Buffer length (per qTD)
147 4 field >qtd-/buf-all \ Buffer length (size of the entire buffer)
148 \ Only the first qTD has the entire size of buffer
149 \ For bulk and intr qTDs
150d# 32 round-up
151constant /qtd
152
153\ >hcqtd-token constants
154h# 0000.0000 constant TD_TOGGLE_DATA0
155h# 8000.0000 constant TD_TOGGLE_DATA1
156h# 8000.0000 constant TD_TOGGLE_MASK
157h# 0000.8000 constant TD_IOC
158h# 0000.0c00 constant TD_C_ERR_MASK
159h# 0000.0400 constant TD_C_ERR1
160h# 0000.0800 constant TD_C_ERR2
161h# 0000.0c00 constant TD_C_ERR3
162h# 0000.0000 constant TD_PID_OUT
163h# 0000.0100 constant TD_PID_IN
164h# 0000.0200 constant TD_PID_SETUP
165h# 0000.00ff constant TD_STAT_MASK
166h# 0000.0080 constant TD_STAT_ACTIVE
167h# 0000.0040 constant TD_STAT_HALTED \ Babble, error count=0, STALL
168h# 0000.0020 constant TD_STAT_DBUFF \ Data buffer error
169h# 0000.0010 constant TD_STAT_BABBLE \ Babble
170h# 0000.0008 constant TD_STAT_XERR \ Timeout, CRC, bad pid, etc
171h# 0000.0004 constant TD_STAT_MISS_MF \ Missed micro-frame
172h# 0000.0000 constant TD_STAT_S_SPLIT \ Start split transaction
173h# 0000.0002 constant TD_STAT_C_SPLIT \ Complete split transaction
174h# 0000.0000 constant TD_STAT_OUT \ Do OUT
175h# 0000.0001 constant TD_STAT_PING \ Do ping
176h# 0000.0001 constant TD_STAT_SPLIT_ERR \ Periodic split transaction ERR
177
178: td-data>di-data ( n -- n' ) TD_TOGGLE_MASK and if 1 else 0 then ;
179: di-data>td-data ( n -- n' ) if TD_TOGGLE_DATA1 else TD_TOGGLE_DATA0 then ;
180
181\ ---------------------------------------------------------------------------
182\ Queue Head (QH) as defined by the EHCI Spec; 32-byte aligned
183\ ---------------------------------------------------------------------------
184
185struct \ Beginning of QH fields
186 4 field >hcqh-next \ QH horizontal link pointer
187 4 field >hcqh-endp-char \ Endpoint characteristics
188 4 field >hcqh-endp-cap \ Endpoint capabilities
189 4 field >hcqh-cur-pqtd \ Current transaction descriptor pointer
190/hcqtd field >hcqh-overlay \ Transfer overlay area
191dup constant /hcqh
192 \ Driver specific fields
193 4 field >qh-phys \ QH's physical address
194 4 field >qh-next \ Next QH's virtual address
195 4 field >qh-prev \ Previous QH's virtual address
196 4 field >qh-unaligned \ QH's unaligned address
197 4 field >qh-size \ Size of QH+qTDs
198 4 field >qh-#qtds \ # of qTDs in the list
199d# 32 round-up
200constant /qh
201
202\ >hcqh-endp-char constants
203h# 0800.0000 constant QH_CTRL_ENDP
204h# 0000.8000 constant QH_HEAD
205h# 0000.4000 constant QH_TD_TOGGLE
206h# 0000.0080 constant QH_INACTIVE_NEXT
207h# 0000.0000 constant QH_TUNE_RL_HS
208h# 0000.0000 constant QH_TUNE_RL_TT
209
210\ >hcqh-endp-cap constants
211h# 4000.0000 constant QH_MULT1
212h# 8000.0000 constant QH_MULT2
213h# c000.0000 constant QH_MULT3
214
215
2160 value qh-ptr \ Head of all QHs
217
218\ ---------------------------------------------------------------------------
219\ QH and TDs for bulk, control and interrupt operations.
220\ QH and its list of TDs are allocated as needed.
221\ ---------------------------------------------------------------------------
222
223: sync-qh ( qh -- ) dup >qh-phys l@ /hcqh dma-sync ;
224: sync-qtd ( qtd -- ) dup >qtd-phys l@ /hcqtd dma-sync ;
225: sync-qhqtds ( qh -- ) dup >qh-phys l@ over >qh-size l@ dma-sync ;
226
227: map-out-bptrs ( qtd -- )
228 dup >qtd-buf l@ over >qtd-pbuf l@ rot >qtd-/buf-all l@ hcd-map-out
229;
230
231: init-qh ( qh.u,v,p len #qtds -- )
232 3 pick >qh-#qtds l! ( qh.u,v,p len )
233 2 pick >qh-size l! ( qh.u,v,p )
234 over >qh-phys l! ( qh.u,v )
235 TERMINATE 2 pick >hcqh-next le-l! ( qh.u,v )
236 >qh-unaligned l! ( )
237;
238: link-qtds ( qtd.v qtd.p #qtds -- )
239 1- 0 ?do ( qtd.v qtd.p )
240 TERMINATE 2 pick >hcqtd-next-alt le-l! ( qtd.v qtd.p )
241 2dup swap >qtd-phys l! ( qtd.v qtd.p )
242 /qtd + ( qtd.v qtd.p' )
243 2dup swap >hcqtd-next le-l! ( qtd.v qtd.p )
244 swap dup /qtd + tuck swap >qtd-next l! ( qtd.p qtd.v' )
245 swap ( qtd.v qtd.p )
246 loop
247
248 \ Fix up the last qTD
249 over >qtd-phys l! ( qtd.v )
250 TERMINATE over >hcqtd-next le-l! ( qtd.v )
251 TERMINATE swap >hcqtd-next-alt le-l! ( )
252;
253: link-qhqtd ( qtd.p qh -- )
254 >hcqh-overlay tuck ( qh.overlay qtd.p qh.overlay )
255 >hcqtd-next le-l! ( qh.overlay )
256 TERMINATE over >hcqtd-next-alt le-l! ( qh.overlay)
257 TD_TOGGLE_DATA1 TD_STAT_PING or swap >hcqtd-token le-l! ( )
258;
259
260: link-qhqtds ( qtd.v qtd.p #qtds qh -- )
261 2 pick swap link-qhqtd ( qtd.v qtd.p #qtds ) \ Link QH to qTD
262 link-qtds ( ) \ Link qTDs
263;
264
265: alloc-qhqtds ( #qtds -- qh qtd )
266 dup >r /qtd * /qh + dup >r ( len ) ( R: #qtds len )
267 aligned32-alloc-map-in ( qh.u,v,p ) ( R: #qtds len )
268 over r@ erase ( qh.u,v,p ) ( R: #qtds )
269 3dup r> r@ init-qh ( qh.u,v,p ) ( R: #qtds )
270 rot drop ( qh.v,p ) ( R: #qtds )
271 over /qh + dup -rot ( qh qtd qh.p qtd ) ( R: #qtds )
272 swap /qh + ( qh qtd qtd.v,p ) ( R: #qtds )
273 r> 4 pick link-qhqtds ( qh qtd )
274;
275
276: free-qhqtds ( qh -- )
277 >r ( R: qh )
278 r@ >qh-unaligned l@ ( qh.u ) ( R: qh )
279 r@ dup >qh-phys l@ ( qh.u,v,p ) ( R: qh )
280 r> >qh-size l@ ( qh.u,v,p size )
281 aligned32-free-map-out ( )
282;
283
284\ ---------------------------------------------------------------------------
285\ qTD Buffer Pointers management
286\ ---------------------------------------------------------------------------
287
2885 constant #bptr \ There are 5 Buffer Pointers in qTD
289h# 1000 constant /bptr \ Size of buffer at each Buffer Pointer[i]
290/bptr 1- constant bptr-ofs-mask \ Current Offset mask
291bptr-ofs-mask invert constant bptr-mask \ Buffer Pointer mask
292/bptr #bptr * constant /maxbptrs \ Maximum size of transfer for a qTD
293/bptr #bptr 1- * constant /maxbptrs-1 \ Maximum size of 4 Buffer Pointers
294
295\ Determine the size of transfer for a qTD
296: cal-/bptr ( phys len -- /xfer )
297 over dup /bptr round-up = if ( phys len )
298 nip /maxbptrs min ( /xfer )
299 else
300 swap bptr-ofs-mask and ( len len0 )
301 tuck - /maxbptrs-1 min + ( /xfer )
302 then
303;
304
305\ Determine the number of Buffer Pointers necessary
306: cal-#bptr ( phys len -- #bptr )
307 dup 0= if nip exit then
308 swap dup /bptr round-up swap - ?dup if
309 ( len len0 )
310 - ( len-len0 )
311 /bptr round-up /bptr / 1+ ( #bptr )
312 else ( len )
313 /bptr round-up /bptr / ( #bptr )
314 then
315;
316
317\ Determine the number of qTDs necessary for the entire transfer
318: cal-#qtd ( phys len -- #qtds )
319 dup 0= if nip exit then
320 cal-#bptr #bptr /mod swap if 1+ then
321;
322
323: fill-qtd-bptrs ( buf phys len qtd -- actual )
324 >r rot r@ >qtd-buf l! ( phys len ) ( R: qtd )
325 dup r@ >qtd-/buf-all l! ( phys len ) ( R: qtd )
326 over r@ >qtd-pbuf l! ( phys len ) ( R: qtd )
327 over swap cal-/bptr tuck ( actual phys actual ) ( R: qtd )
328 dup r@ >qtd-/buf l! ( actual phys actual ) ( R: qtd )
329 over swap cal-#bptr ( actual phys #bptr ) ( R: qtd )
330 r> swap 0 ?do ( actual phys qtd )
331 2dup >hcqtd-bptr0 i 4 * + le-l! ( actual phys qtd )
332 swap /bptr + bptr-mask and swap ( actual phys' qtd )
333 loop 2drop ( actual )
334;
335
336\ ---------------------------------------------------------------------------
337\ Async scheduling
338\ ---------------------------------------------------------------------------
339
340: async-wait ( -- )
341 begin
342 usbcmd@ h# 20 and 5 >> usbsts@ h# 8000 and d# 15 >>
343 = until
344;
345: enable-async ( phys -- )
346 asynclist! async-wait
347 usbcmd@ h# 20 or usbcmd! async-wait
348;
349: disable-async ( -- )
350 async-wait usbcmd@ h# 20 invert and usbcmd! async-wait
351;
352
353: insert-qh ( qh -- )
354 >r
355 qh-ptr if
356 \ If there is another qh in the system, link the new qh to the existing
357 \ qh head.
358 qh-ptr r@ >qh-prev l!
359 qh-ptr >qh-next l@ r@ >qh-next l!
360 qh-ptr >hcqh-next le-l@ r@ >hcqh-next le-l!
361 r@ qh-ptr >qh-next l!
362 r@ >qh-phys l@ qh-ptr >hcqh-next le-l!
363 r> sync-qhqtds
364 qh-ptr sync-qh
365 else
366 \ If there is no qh in the system, link it to itself and mark it the
367 \ head.
368 r@ to qh-ptr
369 r@ >hcqh-endp-char dup le-l@ QH_HEAD or swap le-l!
370 r@ dup >qh-next l!
371 r@ >qh-phys l@ dup TYP_QH or r@ >hcqh-next le-l!
372 r> sync-qhqtds
373 enable-async
374 then
375;
376
377: remove-qh ( qh -- )
378 dup >qh-next l@ over = if
379 \ If qh is the only qh in the system, disable-async and exit
380 drop disable-async
381 0 to qh-ptr
382 else
383 \ Otherwise, qh.prev points to qh.next, fix up reclamation bits.
384 \ Ring doorbell, wait for answer.
385 \ Free qh, make sure the qh-ptr is up-to-date.
386 dup >qh-prev l@ ?dup if ( qh prev.qh )
387 over >hcqh-next le-l@ over >hcqh-next le-l!
388 over >qh-next l@ swap >qh-next l!
389 dup sync-qh
390 dup >qh-next l@ qh-ptr <> if
391 dup >qh-prev l@ swap >qh-next l@ >qh-prev l!
392 else
393 drop
394 then
395 else
396 >qh-next l@ to qh-ptr
397 qh-ptr >hcqh-endp-char dup le-l@ QH_HEAD or swap le-l!
398 0 qh-ptr >qh-prev l!
399 qh-ptr sync-qh
400 then
401 ring-doorbell
402 then
403;
404
405\ ---------------------------------------------------------------------------
406\ Interrupt scheduling
407\ XXX Make it simple for now and igore interval and make it a fixed poll
408\ XXX interval.
409\
410\ Empirically, the 4 ms poll interval works optimally with the usb keyboard.
411\ ---------------------------------------------------------------------------
412
4130 value #intr
414d# 32 constant intr-interval \ 4 ms poll interval
415
416: #intr++ ( -- ) #intr 1+ to #intr ;
417: #intr-- ( -- ) #intr 1- to #intr ;
418
419: periodic-wait ( -- )
420 begin
421 usbcmd@ h# 10 and 4 >> usbsts@ h# 4000 and d# 14 >>
422 = until
423;
424: enable-periodic ( -- )
425 periodic-wait usbcmd@ h# 10 or usbcmd! periodic-wait
426;
427: disable-periodic ( -- )
428 periodic-wait usbcmd@ h# 10 invert and usbcmd! periodic-wait
429;
430
431: (insert-intr-qh) ( qh idx -- )
432 dup >r ( qh idx ) ( R: idx )
433 intr-tail@ ?dup 0= if ( qh ) ( R: idx )
434 dup r@ intr-head! ( qh ) ( R: idx )
435 dup >qh-phys l@ TYP_QH or r@ framelist!
436 ( qh ) ( R: idx )
437 else ( qh tail ) ( R: idx )
438 2dup >qh-next l! ( qh tail ) ( R: idx )
439 over >qh-phys l@ TYP_QH or over >hcqh-next le-l!
440 ( qh tail ) ( R: idx )
441 over >qh-prev l! ( qh ) ( R: idx )
442 then
443 r> intr-tail! ( )
444;
445: insert-intr-qh ( qh speed interval -- )
446 drop ( qh speed )
447 speed-high = if h# 0020 else h# 1c01 then
448 over >hcqh-endp-cap dup le-l@ rot or swap le-l!
449 ( qh ) #framelist 0 do dup i (insert-intr-qh) intr-interval +loop drop
450 #intr 0= if enable-periodic then
451 #intr++
452;
453
454: (remove-intr-qh) ( qh idx -- )
455 >r ( qh ) ( R: idx )
456 dup >qh-prev l@ ?dup if over >qh-next l@ swap >qh-next l! then
457 dup >qh-next l@ ?dup if over >qh-prev l@ swap >qh-prev l! then
458 r@ intr-head@ over = if ( qh ) ( R: idx )
459 dup >qh-next l@ dup r@ intr-head! ( qh nqh ) ( R: idx )
460 ?dup if >qh-phys l@ TYP_QH or else TERMINATE then r@ framelist!
461 ( qh ) ( R: idx )
462 then
463 r@ intr-tail@ over = if ( qh ) ( R: idx )
464 dup >qh-prev l@ r@ intr-tail! ( qh ) ( R: idx )
465 then
466 r> 2drop
467;
468: remove-intr-qh ( qh -- )
469 #intr--
470 ( qh ) #framelist 0 do dup i (remove-intr-qh) intr-interval +loop drop
471 #intr 0= if disable-periodic then
472;
473
474\ ---------------------------------------------------------------------------
475\ Wait for a QH to be done and process any errors.
476\
477\ When done? returns no error found yet, the caller should check if errors
478\ were found in the TDs.
479\ ---------------------------------------------------------------------------
480
4810 value timeout
482
483: .qtd-error ( cc -- )
484 dup TD_STAT_HALTED and if " Stalled; " USB_ERR_STALL set-usb-error then
485 dup TD_STAT_DBUFF and if " Data Buffer Error; " USB_ERR_DBUFERR set-usb-error then
486 dup TD_STAT_BABBLE and if " Babble Detected; " USB_ERR_BABBLE set-usb-error then
487 dup TD_STAT_XERR and if " CRC/Timeout/Bad PID; " USB_ERR_CRC set-usb-error then
488 dup TD_STAT_MISS_MF and if " Missed Micro-frame; " USB_ERR_MICRO_FRAME set-usb-error then
489 TD_STAT_SPLIT_ERR and if " Periodic split-x error; " USB_ERR_SPLIT set-usb-error then
490;
491
492: qh-done? ( qh -- done? )
493 >hcqh-overlay ( olay )
494 dup >hcqtd-next le-l@ ( olay pnext )
495 swap >hcqtd-token le-l@ ( pnext token )
496 dup TD_STAT_HALTED and -rot ( halted? pnext token )
497 TD_STAT_ACTIVE and 0= swap ( halted? inactive? pnext )
498 TERMINATE = and ( halted? done? )
499 or ( done?' )
500;
501: done? ( qh -- usberr )
502 begin
503 process-hc-status
504 ( qh ) dup sync-qh
505 ( qh ) dup qh-done? ?dup 0= if
506 1 ms
507 timeout 1- dup to timeout 0=
508 then
509 until
510
511 ( qh ) qh-done? 0= if " Timeout" USB_ERR_TIMEOUT set-usb-error then
512 usb-error
513;
514
515: error? ( qh -- usberr )
516 dup >hcqh-endp-char le-l@ d# 12 >> 3 and
517 speed-high = if h# fc else h# fd then
518 swap >hcqh-overlay >hcqtd-token le-l@ and ?dup if .qtd-error then
519 usb-error
520;
521
522: get-actual ( qtd #qtd -- actual )
523 0 -rot 0 ?do ( actual qtd )
524 dup sync-qtd ( actual qtd )
525 dup >hcqtd-token le-l@ dup TD_STAT_ACTIVE and 0= if
526 over >qtd-/buf l@ ( actual qtd token len )
527 swap d# 16 >> h# 7fff and - ( actual qtd len' )
528 rot + swap ( actual' qtd )
529 else
530 drop ( actual qtd )
531 then
532 >qtd-next l@ ( actual qtd )
533 loop drop ( qtd )
534;
535
536\ ---------------------------------------------------------------------------
537\ Allocate a dummy qh to be head of the queue to get around the fact that
538\ the VIA 2.0 controller does not stop async when told to.
539\ ---------------------------------------------------------------------------
540
5410 value dummy-qh
542
543: alloc-dummy-qh ( -- )
544 dummy-qh 0= if
545 1 alloc-qhqtds ( qh qtd )
546 drop to dummy-qh
547 TERMINATE dummy-qh >hcqh-overlay >hcqtd-next le-l!
548 then
549 dummy-qh insert-qh
550;
551
552: free-dummy-qh ( -- )
553 dummy-qh ?dup if free-qhqtds 0 to dummy-qh then
554;
555
556: ?alloc-dummy-qh ( -- )
557 0 my-w@ h# 1106 ( VIA ) = if alloc-dummy-qh then
558;
559
560: (init-extra) ( -- )
561 ?alloc-dummy-qh
562 init-intr
563 init-framelist
564;
565
566' (init-extra) to init-extra
567
568headers
569
570\ LICENSE_BEGIN
571\ Copyright (c) 2006 FirmWorks
572\
573\ Permission is hereby granted, free of charge, to any person obtaining
574\ a copy of this software and associated documentation files (the
575\ "Software"), to deal in the Software without restriction, including
576\ without limitation the rights to use, copy, modify, merge, publish,
577\ distribute, sublicense, and/or sell copies of the Software, and to
578\ permit persons to whom the Software is furnished to do so, subject to
579\ the following conditions:
580\
581\ The above copyright notice and this permission notice shall be
582\ included in all copies or substantial portions of the Software.
583\
584\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
585\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
586\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
587\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
588\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
589\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
590\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
591\
592\ LICENSE_END