duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 69724f7f5bbd9534829354cfd00fd0084aeff0b4
parent 52d7037d9bfbbefa08fac1575affe07232ae7e78
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Sat,  6 Aug 2022 12:24:29 -0400

drv/pc/pci: refactor to allow more fields

The previous approach lead to quite inelegant code when adding more fields.

Diffstat:
Mfs/drv/pc/pci.fs | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mfs/lib/nfmt.fs | 3+++
Mfs/lib/str.fs | 12++++++++----
Mfs/tests/kernel.fs | 6++++++
Mfs/xcomp/bootlo.fs | 9+++++++--
5 files changed, 101 insertions(+), 27 deletions(-)

diff --git a/fs/drv/pc/pci.fs b/fs/drv/pc/pci.fs @@ -1,17 +1,66 @@ \ PCI driver +?f<< /lib/str.fs $cf8 const CFGADDR $cfc const CFGDATA +$100 const META_FIELDDESC \ data: a string + 0 value pcibus 0 value pcislot 0 value pcifunc -0 value pcidevice -0 value pcivendor -0 value pciclass -0 value pcisubclass -0 value pciprogif -0 value pcitype +0 value _readcnt \ how many registers are read in current buffer +create _buf $50 allot +0 value _currentlist +: _ + current _currentlist ! 4 to+ _currentlist + '"' expectchar current 'emeta lladd drop + META_FIELDDESC , [compile] S" drop ; +: pcifield ( off -- ) _buf + &@ _ ; +: pcifieldw ( off -- ) _buf + &w@ _ ; +: pcifieldc ( off -- ) _buf + &c@ _ ; + +\ Common header +12 const COMMONFIELDCNT +create commonfieldlist COMMONFIELDCNT 4 * allot +commonfieldlist to _currentlist + +$00 pcifieldw pci.vendor "Vendor ID" +$02 pcifieldw pci.device "Device ID" +$04 pcifieldw pci.command "Command" +$06 pcifieldw pci.status "Status" +$08 pcifieldc pci.revision "Revision ID" +$09 pcifieldc pci.progIF "progIF" +$0a pcifieldc pci.subclass "Subclass" +$0b pcifieldc pci.class "Class" +$0c pcifieldc pci.cachelinesz "Cache Line Size" +$0d pcifieldc pci.lattimer "Latency Timer" +$0e pcifieldc pci.hdrtype "Type" +$0f pcifieldc pci.bist "BIST" + +create summaryfields + ' pci.vendor , ' pci.device , ' pci.class , ' pci.subclass , ' pci.hdrtype , + +\ Type 0 header +15 const TYPE0FIELDCNT +create type0fieldlist TYPE0FIELDCNT 4 * allot +type0fieldlist to _currentlist + +$10 pcifield pci0.bar0 "BAR0" +$14 pcifield pci0.bar1 "BAR1" +$18 pcifield pci0.bar2 "BAR2" +$1c pcifield pci0.bar3 "BAR3" +$20 pcifield pci0.bar4 "BAR4" +$24 pcifield pci0.bar5 "BAR5" +$28 pcifield pci0.cisptr "Cardbus CIS ptr" +$2c pcifieldw pci0.subsystemvendor "Subsystem Vendor" +$2e pcifieldw pci0.subsystem "Subsystem ID" +$30 pcifield pci0.expansionaddr "Expansion Addr" +$34 pcifieldc pci0.capabiliesptr "Capabilities ptr" +$3c pcifieldc pci0.interruptline "Interrupt Line" +$3d pcifieldc pci0.interruptpin "Interrupt PIN" +$3e pcifieldc pci0.mingrant "Min grant" +$3f pcifieldc pci0.maxlatency "Max latency" : pciaddr ( off -- n ) $fc and pcifunc 8 lshift or pcislot 11 lshift or pcibus 16 lshift or @@ -19,37 +68,44 @@ $cfc const CFGDATA : _pci@ ( pciaddr -- n ) CFGADDR p! CFGDATA p@ ; -: pci@ ( bus slot func -- f ) \ returns whether the read yields a valid device +\\ Read the first register of pci address and return whether it's a valid device +: pci@ ( bus slot func -- f ) to pcifunc to pcislot to pcibus - 0 pciaddr _pci@ dup $ffff and to pcivendor 16 rshift to pcidevice - pcivendor $ffff = if 0 exit then - 8 pciaddr _pci@ dup 24 rshift $ff and to pciclass - dup 16 rshift $ff and to pcisubclass 8 rshift $ff and to pciprogif - $0c pciaddr _pci@ 16 rshift $ff and to pcitype 1 ; + 0 to _readcnt 0 pciaddr _pci@ dup -1 = not if ( n ) + _buf ! 1 to _readcnt 1 else 1+ ( 0 ) then ; -: pcinextfunc ( -- f ) +\ Ensure that at least "n" registers are read in _buf +: _ensureread ( n ) + begin _readcnt over < while + _readcnt 4 * dup pciaddr _pci@ ( off n ) + swap _buf + ! 1 to+ _readcnt repeat ( n ) drop ; + +: _nextfunc ( -- f ) begin 1 to+ pcifunc pcifunc 8 < while pcibus pcislot pcifunc pci@ not while repeat 1 else 0 then ; -: pcinextslot ( -- f ) +: _nextslot ( -- f ) begin 1 to+ pcislot pcislot $20 < while pcibus pcislot 0 pci@ not while repeat 1 else 0 then ; -: .pci ( -- ) +: _getdesc ( 'field -- str ) + emeta META_FIELDDESC swap findemeta ?dup if 'emetadata else S" ???" then ; + +\\ Print current PCI device in a one line summary +: .pciln ( -- ) pcibus .x1 ':' emit pcislot .x1 '.' emit pcifunc . spc> - ." Vendor ID " pcivendor .x2 ." Device ID " pcidevice .x2 - ." Class " pciclass .x1 ':' emit pcisubclass .x1 - ." ProgIF " pciprogif .x1 ." Type " pcitype .x1 nl> ; + 5 dup _ensureread >r summaryfields begin ( a ) + @+ dup _getdesc stype spc> execute .x? spc> next drop nl> ; : .pcislot ( bus slot -- ) 0 pci@ if - .pci pcitype $80 and if \ multi-function - begin pcinextfunc while .pci repeat then then ; + .pciln pci.hdrtype $80 and if \ multi-function + begin _nextfunc while .pciln repeat then then ; : .pcibus ( bus -- ) 0 0 pci@ if pcibus pcislot .pcislot then - begin pcinextslot while pcibus pcislot .pcislot repeat ; + begin _nextslot while pcibus pcislot .pcislot repeat ; diff --git a/fs/lib/nfmt.fs b/fs/lib/nfmt.fs @@ -6,6 +6,9 @@ create _ ," 0123456789abcdef" : .x2 dup 8 rshift .x1 .x1 ; \\ print top of stack in hexadecimal : .x ( n -- ) dup 16 rshift .x2 .x2 ; +\\ print in hexadecimal with a width that depends on the value +: .x? dup $ffff > if .x else dup $ff > if .x2 else .x1 then then ; + \ decimal : _ 10 /mod ( r q ) ?dup if _ then '0' + emit ; : . ( n -- ) diff --git a/fs/lib/str.fs b/fs/lib/str.fs @@ -54,11 +54,15 @@ create _ 4 c, ," AZaz" create _ 6 c, ," AZaz09" : alnum? ( c -- f ) _ rmatch ; +\\ Read in< until next non WS and yield it +: toword ( -- c ) begin in< dup ws? while drop repeat ( c ) ; + +\\ Read in<, discarding whitespaces and expect the next char to be "c" +: expectchar ( c -- ) + toword over = not if emit abort" expected" else drop then ; + \ Create a list of strings (same format as sfind above) with the specified \ number of elements. Each element must be "quoted" with no space (unless you \ want them in the string) in the quotes. \ Example: 3 stringlist mylist "foo" "bar" "hello world!" -: stringlist create >r begin - begin in< dup ws? while drop repeat ( c ) - '"' = not if '"' emit abort" expected" then - [compile] S" drop next 0 c, ; +: stringlist create >r begin '"' expectchar [compile] S" drop next 0 c, ; diff --git a/fs/tests/kernel.fs b/fs/tests/kernel.fs @@ -66,6 +66,12 @@ current .x : baz ; ' baz preventry ' bar #eq +\ metadata and linked lists +' bar emeta 0 #eq +42 ' bar emeta findemeta 0 #eq +' bar 'emeta lladd 42 , ( ll ) +42 ' bar emeta findemeta ( ll ) #eq + \ autoloading floaded # diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs @@ -45,6 +45,7 @@ \ Memory : c@+ ( a -- a+1 c ) dup 1+ swap c@ ; +: @+ ( a -- a+4 n ) dup 4 + swap @ ; : c!+ ( c a -- a+1 ) tuck c! 1+ ; : Ac@+ Ac@ A+ ; : Ac!+ Ac! A+ ; @@ -64,6 +65,9 @@ : doer code compile (does) CELLSZ allot ; : does> r> ( exit current definition ) current 5 + ! ; : &+ ( n -- ) doer , does> @ + ; +: &@ ( n -- ) doer , does> @ @ ; +: &w@ ( n -- ) doer , does> @ w@ ; +: &c@ ( n -- ) doer , does> @ c@ ; : &+@ ( n -- ) doer , does> @ + @ ; : &+! ( n -- ) doer , does> @ + ! ; : field ( off -- ) doer , does> ( a 'w ) @ + to? ?dup if execute else @ then ; @@ -115,6 +119,7 @@ alias noop [then] \ Dictionary -5 &+@ preventry -9 &+@ emeta +-9 &+ 'emeta : wordlen ( w -- len ) 1- c@ $3f and ; : wordname[] ( w -- sa sl ) dup wordlen swap 9 - over - ( sl sa ) swap ; @@ -123,7 +128,7 @@ alias noop [then] \ Entry metadata 4 &+@ emetatype -8 &+ 'emeta +8 &+ 'emetadata : findemeta ( typeid ll -- ll-or-0 ) begin ( typeid ll ) dup while 2dup emetatype = not while llnext repeat ( success ) then ( typeid ll-or-0 ) nip ; @@ -134,7 +139,7 @@ alias noop [then] : \\ nextmeta lladd drop EMETA_DOCLINE , begin in< dup c, LF = until ; : .doc ( w -- ) emeta begin ( ll ) EMETA_DOCLINE swap findemeta ?dup while ( ll ) - dup 'emeta begin c@+ dup emit LF = until drop llnext repeat ; + dup 'emetadata begin c@+ dup emit LF = until drop llnext repeat ; \ Alias chaining. See doc/usage. : _ ( 'target 'alias -- )