6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu May 09, 2024 5:00 am

All times are UTC




Post new topic Reply to topic  [ 18 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Thu Aug 25, 2022 9:18 am 
Offline
User avatar

Joined: Sat Jul 24, 2021 1:37 pm
Posts: 282
BigDumbDinosaur wrote:
[color=#000000]
floobydust wrote:
I've been the same basic string out routine for decades...

My "print string" sub in the POC firmware is similar, except I don’t use a lookup table and the string address is pushed to the stack before the call. Within the sub, direct page is pointed to the stack, which means bank-agnostic, long addressing can be used to access the string. The actual call is through the BIOS API, which is responsible for setting the environment, as well as cleaning up the stack before returning to the caller.


Nice documentation! Can I ask about the error codes? How do you do error handling above this function?

_________________
BB816 Computer YouTube series


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 25, 2022 5:17 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8177
Location: Midwestern USA
akohlbecker wrote:
BigDumbDinosaur wrote:
My "print string" sub in the POC firmware is similar...

Nice documentation!

Thanks!

I do that for my own sanity. The system firmware runs to about 13,500 lines of code, with many subroutines. It’s impossible to remember what they all do, so I'm careful to document everything with as much detail as necessary. It’s even more important in some “user-land” programs, one of which runs to nearly 30,000 lines.

Quote:
Can I ask about the error codes? How do you do error handling above this function?

Any user-land program that calls a firmware API and gets an error return has to decide what to do about it. In the user-land programs I have written, there is an error-handling library function that gets INCLUDEd to decode the error and return a pointer to a terse message. It’s up to the caller to process and/or display the message as needed, and to determine what to do afterward. Here’s the decoding function:

Code:
08740  ;libgerr: GLOBAL ERROR MESSAGE DECODER
08741  ;
08742  ;   ———————————————————————————————————————————————————————————————————————
08743  ;   Synopsis: This function returns a 32-bit pointer to the error message
08744  ;             corresponding to the error code passed in the accumulator.
08745  ;
08746  ;             § The message pointer's LSW will be returned in .X & the MSW
08747  ;               in .Y.  The MSW will be set to the current execution bank.
08748  ;
08749  ;             § Error messages are null-terminated character strings & may
08750  ;               be copied, processed and/or printed using other library
08751  ;               functions, such as libstrng & libterm.
08752  ;
08753  ;             § If the error code passed to this function has not been def-
08754  ;               ined, a pointer to “unknown error” will be returned & carry
08755  ;               will be set upon exit from this function.
08756  ;
08757  ;             § This function must be in the same bank as the process that
08758  ;               is using it.
08759  ;
08760  ;             § The following files must be INCLUDEd in your program in or-
08761  ;               der to use this function:
08762  ;
08763  ;               ~/include/sys/gerc.asm
08764  ;
08765  ;                 gerc.asm is a system file that defines error codes.  It
08766  ;                 should be INCLUDEd in the definitions section of your
08767  ;                 program.
08768  ;
08769  ;               ~/lib/libgerm.asm
08770  ;
08771  ;                 libgerm.asm contains the text strings & other data to
08772  ;                 which this function makes reference.  libgerm.asm should
08773  ;                 be INCLUDEd in the static data section of your program.
08774  ;                 It must be in the same bank as this function.
08775  ;   ———————————————————————————————————————————————————————————————————————
08776  ;   Invocation example: LDA #ERRCODE           ;error code
08777  ;                       JSR libgerr
08778  ;                       BCS UNKNOWN_CODE
08779  ;
08780  ;   Exit registers: .A: entry value
08781  ;                   .B: entry value
08782  ;                   .X: text string pointer LSW
08783  ;                   .Y: text string pointer MSW
08784  ;                   DB: entry value
08785  ;                   DP: entry value
08786  ;                   PB: entry value
08787  ;                   SR: nvmxdizc
08788  ;                       ||||||||
08789  ;                       |||||||+———> 0: okay
08790  ;                       |||||||      1: unknown error code
08791  ;                       ||||+++————> entry value
08792  ;                       |||+———————> 0
08793  ;                       +++————————> entry value
08794  ;
08795  ;   ———————————————————————————————————————————————————————————————————————
08796  ;
08797  0014B0  C2 11         libgerr  rep #m_setx|sr_car    ;clear c & x
08798  0014B2  08                     php
08799  0014B3  C2 30                  rep #m_setr
08800  0014B5  5A                     phy
08801  0014B6  DA                     phx
08802  0014B7  48                     pha
08803  ;
08804  ;—————————————————————————————————————————————————————————
08805  ;
08806  ;LOCAL STACK DEFINITIONS
08807  ;
08808    0001              .sfbase   .= 1                  ;base stack index
08809    0001              .sfidx   .= .sfbase            ;workspace index
08810  ;
08811  ;—————————> register stack frame start <—————————
08812  ;
08813    0001              .reg_c   =.sfidx               ;.C
08814    0003              .sfidx   .= .sfidx+s_word
08815    0003              .reg_x   =.sfidx               ;.X
08816    0005              .sfidx   .= .sfidx+s_word
08817    0005              .reg_y   =.sfidx               ;.Y
08818    0007              .sfidx   .= .sfidx+s_word
08819    0007              .reg_sr   =.sfidx               ;SR
08820    0008              .sfidx   .= .sfidx+s_mpusrx
08821    0008              .reg_pc   =.sfidx               ;PC
08822    000A              .sfidx   .= .sfidx+s_mpupcx
08823  ;
08824  ;—————————> register stack frame end <—————————
08825  ;
08826    0009              .s_rsf   =.sfidx-.sfbase       ;register frame size
08827    000A              .sfbase   .= .sfidx
08828  ;—————————————————————————————————————————————————————————
08829  ;
08830  0014B8  E2 20                  sep #m_seta
08831  0014BA  A2 26 00               ldx !#n_glerc-1
08832  ;
08833  0014BD  DD 25 4A      .main    cmp libgelut,x        ;look up error code
08834  0014C0  F0 09                  beq .main010          ;found it
08835  ;
08836  0014C2  CA                     dex
08837  0014C3  D0 F8                  bne .main             ;keep looking
08838  ;
08839  0014C5  A3 07                  lda .reg_sr,s         ;entry SR
08840  0014C7  09 01                  ora #sr_car           ;set carry to indicate...
08841  0014C9  83 07                  sta .reg_sr,s         ;code not found
08842  ;
08843  0014CB  C2 20         .main010 rep #m_seta
08844  0014CD  8A                     txa                   ;code table index
08845  0014CE  0A                     asl
08846  0014CF  AA                     tax                   ;message table index
08847  0014D0  BD 4C 4A               lda libgmlut,x        ;message pointer
08848  0014D3  83 03                  sta .reg_x,s
08849  0014D5  E2 20                  sep #m_seta
08850  0014D7  4B                     phk                   ;execution bank is...
08851  0014D8  68                     pla                   ;MSW of string address
08852  0014D9  C2 30                  rep #m_setr
08853  0014DB  29 FF 00               and !#%11111111       ;mask noise in .B
08854  0014DE  83 05                  sta .reg_y,s          ;set MSW
08855  0014E0  68                     pla
08856  0014E1  FA                     plx
08857  0014E2  7A                     ply
08858  0014E3  28                     plp
08859  0014E4  60                     rts

In my applications, after a call is made to the above and the error text has been displayed, the program either prompts the user to repeat input (assuming faulty input is what triggered the error) or a “long jump” is made to a point where the program can gracefully terminate.

The data needed by the above decoding function is as follows:

Code:
27660  ;libgerm: GLOBAL ERROR MESSAGES
27661  ;
27662  ;   ———————————————————————————————————————————————————————————————————————
27663  ;   Synopsis: This file defines the error messages known to the global er-
27664  ;             ror-handling functions.  It consists of three parts: an error
27665  ;             code lookup table, a message pointer table, & message text.
27666  ;             Entries in the error code LUT are BYTE-sized & entries in the
27667  ;             vector table are DWORD-sized.  Messages are null-terminated
27668  ;             character strings.
27669  ;
27670  ;             There is a one-for-one correspondence between entries in the
27671  ;             error code lookup table & entries in the message pointer
27672  ;             table.  Getting one or both tables out of order will cause
27673  ;             incorrect error text to be returned by the libgerr function.
27674  ;             The message text strings may be in any order.
27675  ;
27676  ;             If a new error code is to be created, proceed as follows:
27677  ;
27678  ;             1) Define the new error code in ~/include/sys/gerc.asm.  The
27679  ;                new error code should be a numeric value that is higher
27680  ;                than that of the highest existing code.  DO NOT change any
27681  ;                existing codes!
27682  ;
27683  ;             2) Add the new error code to the end of the LIBGELUT lookup
27684  ;                table (below).  Note that entries in this table must be
27685  ;                defined with the .BYTE assembler pseudo-op.
27686  ;
27687  ;             3) Add the corresponding message text to the end of the text
27688  ;                section (below).  It is recommended that message text be
27689  ;                succint, not wordy.  Note the general form of existing
27690  ;                messages.  Also note that message text strings are defined
27691  ;                with local (.LABEL) labels, not global ones (LABEL).
27692  ;
27693  ;             4) Add a message text pointer to the end of LIBGMLUT (below).
27694  ;                Note that entries in this table must be defined as WORDS
27695  ;                (16-bit pointers).  Also note that entries are local lab-
27696  ;                els as explained in 3) above.
27697  ;   ———————————————————————————————————————————————————————————————————————
27698  ;
27699  ;—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
27700  ;
27701  ;ERROR CODES
27702  ;
27703    4A25              libgelut   =*                    ;error codes...
27704           .byte e_okay          ;  no error
27705           .byte e_apiidx        ;  API index out-of-range
27706           .byte e_memf          ;  memory fault
27707           .byte e_rtcf          ;  RTC fault
27708           .byte e_nvrf          ;  NVRAM fault
27709           .byte e_sscf          ;  SCSI HBA general fault
27710           .byte e_sscfe         ;  SCSI HBA FIFO fault
27711           .byte e_sioss         ;  SIO subsystem not ready
27712           .byte e_sioch         ;  invalid channel
27713           .byte e_sioror        ;  receiver data overrun
27714           .byte e_sssnr         ;  SCSI subsystem not ready
27715           .byte e_sstid         ;  target ID out of range
27716           .byte e_ssdne         ;  device not enumerated
27717           .byte e_ssdnp         ;  device not present
27718           .byte e_sscmd         ;  illegal controller command
27719           .byte e_ssudf         ;  unsupported driver function
27720           .byte e_ssudt         ;  unsupported device type
27721           .byte e_ssubr         ;  unexpected bus reset
27722           .byte e_ssubp         ;  unsupported bus phase
27723           .byte e_ssucg         ;  unsupported command group
27724           .byte e_ssabt         ;  aborted transaction
27725           .byte e_sschk         ;  check condition
27726           .byte e_ssblk         ;  too many blocks
27727           .byte e_parm          ;  parameter invalid
27728           .byte e_ptrnul        ;  null pointer
27729           .byte e_strnul        ;  null string
27730           .byte e_strlen        ;  string too long
27731           .byte e_elmct         ;  too many elements in list
27732           .byte e_huge          ;  number too big
27733           .byte e_inon          ;  not a number
27734           .byte e_idivz         ;  division by zero
27735           .byte e_iover         ;  over-/underflow
27736           .byte e_isizw         ;  invalid integer size
27737           .byte e_notdsk        ;  device not a disk
27738           .byte e_devcap        ;  device capacity
27739           .byte e_mbr           ;  invalid master boot record
27740           .byte e_dupfsn        ;  duplicate filesystem name
27741           .byte e_dupvol        ;  duplicate volume name
27742           .byte e_fsnf          ;  filesystem not found
27743  ;
27744  ;   ———————————————————————————————————
27745  ;   Do not change the below definition!
27746  ;   ———————————————————————————————————
27747  ;
27748    0027              n_glerc  =*-libgelut           ;number of error codes in table
27749  ;
27750  ;—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
27751  ;
27752  ;MESSAGE POINTERS
27753  ;
27754    4A4C              libgmlut   =*                    ;message pointers...
27755           .word .okay           ;  no/unknown error
27756           .word .apiidx         ;  API index out-of-range
27757           .word .memf           ;  memory fault
27758           .word .rtcf           ;  RTC fault
27759           .word .nvrf           ;  NVRAM fault
27760           .word .sscf           ;  SCSI HBA general fault
27761           .word .sscfe          ;  SCSI HBA FIFO fault
27762           .word .sioss          ;  SIO subsystem not ready
27763           .word .sioch          ;  invalid channel
27764           .word .sioror         ;  receiver data overrun
27765           .word .sssnr          ;  SCSI subsystem not ready
27766           .word .sstid          ;  target ID out of range
27767           .word .ssdne          ;  device not enumerated
27768           .word .ssdnp          ;  device not present
27769           .word .sscmd          ;  illegal controller command
27770           .word .ssudf          ;  unsupported driver function
27771           .word .ssudt          ;  unsupported device type
27772           .word .ssubr          ;  unexpected bus reset
27773           .word .ssubp          ;  unsupported bus phase
27774           .word .ssucg          ;  unsupported command group
27775           .word .ssabt          ;  aborted transaction
27776           .word .sschk          ;  check condition
27777           .word .ssblk          ;  too many disk blocks
27778           .word .parmiv         ;  parameter invalid
27779           .word .ptrnul         ;  null pointer
27780           .word .strnul         ;  null string
27781           .word .strsiz         ;  string too long
27782           .word .elmct          ;  too many elements in list
27783           .word .hugenum        ;  number too big
27784           .word .inon           ;  not a number
27785           .word .idivz          ;  division by zero
27786           .word .iover          ;  integer computation over-/underflow
27787           .word .isizw          ;  invalid integer size
27788           .word .notdsk         ;  device not a disk
27789           .word .devcap         ;  device capacity
27790           .word .mbriv          ;  invalid master boot record
27791           .word .dupfsn         ;  duplicate filesystem name
27792           .word .dupvol         ;  duplicate volume name
27793           .word .fsnf           ;  filesystem not found
27794  ;
27795     .if {{*-libgmlut}/s_word} != n_glerc
27796  ;                                                         
27797  ;—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—-—
27798  ;
27799  ;MESSAGE TEXT
27800  ;
27801  .ssabt   .byte "Aborted SCSI transaction",0
27802  .sschk   .byte "Check condition",0
27803  .iover   .byte "Computation out-of-range",0
27804  .devcap  .byte "Device capacity exceeded",0
27805  .sstid   .byte "Device ID out-of-range",0
27806  .notdsk  .byte "Device not a disk",0
27807  .ssdne   .byte "Device not enumerated",0
27808  .ssdnp   .byte "Device not responding",0
27809  .idivz   .byte "Division by zero",0
27810  .dupfsn  .byte "Duplicate filesystem name",0
27811  .dupvol  .byte "Duplicate volume name",0
27812  .fsnf    .byte "Filesystem not found",0
27813  .memf    .byte "Hardware: core fault",0
27814  .nvrf    .byte "Hardware: NVRAM fault",0
27815  .rtcf    .byte "Hardware: RTC fault",0
27816  .sscfe   .byte "HBA FIFO fault",0
27817  .sscf    .byte "HBA general fault",0
27818  .sscmd   .byte "Illegal SCSI controller command",0
27819  .isizw   .byte "Illegal integer type",0
27820  .apiidx  .byte "Invalid API index",0
27821  .mbriv   .byte "Invalid master boot record",0
27822  .parmiv  .byte "Invalid parameter",0
27823  .sioch   .byte "Invalid SIO channel",0
27824  .inon    .byte "Not a number",0
27825  .hugenum .byte "Number magnitude",0
27826  .ptrnul  .byte "Null pointer",0
27827  .strnul  .byte "Null string",0
27828  .sssnr   .byte "SCSI subsystem not ready",0
27829  .sioror  .byte "SIO receiver data overrun",0
27830  .sioss   .byte "SIO subsystem not ready",0
27831  .strsiz  .byte "String too long",0
27832  .ssblk   .byte "Too many disk blocks",0
27833  .elmct   .byte "Too many elements",0
27834  .okay    .byte "Unknown error",0
27835  .ssubr   .byte "Unexpected SCSI bus reset",0
27836  .ssubp   .byte "Unsupported SCSI bus phase",0
27837  .ssucg   .byte "Unsupported SCSI command group",0
27838  .ssudt   .byte "Unsupported SCSI device type",0
27839  .ssudf   .byte "Unsupported SCSI driver function",0

In the firmware, the situation is a little different. With a few exceptions, internal firmware functions do not call APIs, the above SCPRINT being one of those exceptions (it calls the KSCPUT API to actually write to the console). Therefore, error handling is simplified compared to what would be required if a user-land program calls an API.¹ For example, in the above SCPRINT function, E_STRLEN (string is too long) could only occur when SCPRINT is called from user-land—none of the character strings in the firmware code are too long. Therefore, the possibility of E_STRLEN occurring is ignored in any firmware functions that need to write on the console.

E_SIOCH would occur if the serial I/O (SIO) primitive (KSCPUT) aborted because the selected SIO channel is not present in the system. In practice, such an error will never be returned when reading from or writing to the console. As the console is driven from SIO port A, any SIO setup failure during first-stage POST would halt the system. On the latest POC renditions, the MCE (machine check exception) LED would be illuminated to indicate POST terminated with a fatal error.

————————————————————
¹Although the machine language monitor, Supermon 816, is part of the firmware, it is actually a user-land program that only accesses the firmware through the documented APIs. Supermon 816’s error-handling is stark, consisting of the text *ERR being printed, followed by a return to the user input loop.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 25, 2022 9:49 pm 
Offline
User avatar

Joined: Sat Jul 24, 2021 1:37 pm
Posts: 282
That's very informative, thanks.

_________________
BB816 Computer YouTube series


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: