GemDos BIOS functions

From Atari Wiki
Jump to navigation Jump to search
      GemDos BIOS           August 26, 1985                      3
The ST BIOS, contrary to the GEMDOS specification, is  call-
able from the 68000's user mode.
The BIOS is re-entrant to three levels.  That is, there  may
be  up  to three recursive BIOS calls before the system runs
into trouble.  No level checking  is  performed;  the  first
sign  of an overflow will be mysterious system behavior, and
an eventual crash.
Applications should NOT attempt disk or  printer  I/O  (this
includes getbpb calls, and standard-output redirected to the
printer device) in critical-error, system-timer or  process-
terminate handlers.
          The BIOS modifies the function number (and  the  re-
          turn  address)  pushed  on the stack by the applica-
          tion.  The function number on the stack will be ZERO
          on  return.   [For  the  curious: this feature saved
          several cycles per BIOS call ...]
       (0) getmpb
           VOID getmpb(p_mpb)
           LONG p_mpb;
                 Upon entry, 'p_mpb'  points  to  a  'sizeof(MPB)'
                 block  to  be  filled  in with the system initial
                 Memory Parameter Block.  Upon return, the MPB  is
                 filled in.
                 Structures are:
                     #define MPB     struct mpb
                     #define MD      struct md
                     #define PD      struct pd
                     MPB {
                         MD *mp_mfl;         /* memory free list */
                         MD *mp_mal;         /* memory allocated list */
                         MD *mp_rover;       /* roving ptr */
                     MD {
                         MD *m_link;         /* next MD (or NULL) */
                         long m_start;       /* saddr of block */
                         long m_length;      /* #bytes in block */
                         PD *m_own;          /* owner's process descriptor */
                 [See  `System  Variables'  for  more  information
                 about setting up the initial TPA.]
       (1) bconstat
           WORD bconstat(dev)
           WORD dev;
                 Return character-device input status,  D0.L  will
                 be  $0000 if no characters available, or $ffff if
                 (at least one) character is available.  'dev' can
                 be one of:
                         0   PRT: (printer, the parallel port)
                         1   AUX: (aux device, the RS232 port)
                         2   CON: (console, the screen)
                         3   MIDI port (Atari extension)
                         4   Keyboard port (Atari extension)
                 Legal operations on character devices are:
                                     (0)     (1)     (2)     (3)     (4)
                     Operation       PRT     AUX     CON     MIDI    KBD
                     ---------       ----    ----    ----    ----    ----
                     bconstat()      no      yes     yes     yes     no
                     bconin()        yes     yes     yes     yes     no
                     bconout()       yes     yes     yes     yes     yes
                     bcostat()       yes     yes     yes     yes     yes
       (2) bconin
           WORD bconin(dev)
           WORD dev;
                 'dev' is the character device number described in
                 function 1.
                 Does not return until a character has been  input
                 (busy-wait).   It  returns the character value in
                        Atari Corp. Confidential
                 D0.L, with the high word zero.
                 For the console (CON:, device 2) it  returns  the
                 IBM-PC compatible scancode in the low byte of the
                 upper word, and the Ascii character  in  the  low
                 byte of the low word.
                 If bit 3 in the system variable 'conterm' is set,
                 then the high byte of the upper word will contain
                 the value of the system  variable  'kbshift'  for
                 that  keystroke.   [The  default  state for 'con-
                 term%%3' is OFF.]
       (3) bconout
           VOID bconout(dev, c)
           WORD dev, c;
                 'dev' is the character device number described in
                 function 1.
                 Output character 'c' to  the  device.   Does  not
                 return until the character has been written.
       (4) rwabs
           LONG rwabs(rwflag, buf, count, recno, dev)
           WORD rwflag;
           LONG buf;
           WORD count, recno, dev;
                 Read  or  write  logical  sectors  on  a  device.
                 'rwflag' is one of:
                         0   read
                         1   write
                         2   read, do not affect media-change
                         3   write, do not affect media-change
                 'buf' points to a buffer  to  read  or  write  to
                 (unaligned  transfers -- on odd boundaries -- are
                 permitted, but they are slow).   'count'  is  the
                 number  of  sectors  to transfer.  'recno' is the
                 logical sector number to start the  transfer  at.
                 'dev'  is the device number, and on the ST is one
                         0   Floppy drive A:
                         1   Floppy drive B: (or "logical" drive A:
                             on single-disk systems).
                         2+  Hard disks, networks, etc.
                 On return, 0L indicates a  successful  operation.
                 Any negative number indicates an error condition.
                 (It is the responsibility of the BIOS  to  detect
                        Atari Corp. Confidential
                 media  changes,  and return the appropriate error
                 Modes 2 and 3 force  a  physical  disk  operation
                 that  will NOT affect media change, nor result in
                 one (this allows the GEMDOS disk  formatter,  for
                 instance, to read and write logical sectors after
                 formatting a disk, and still allow  the  BIOS  to
                 recognize  a media change on the volume just for-
                 [explain about "insert-disk" critical error  hack
                 for single-drive systems]
       (5) setexc
           LONG setexc(vecnum, vec)
           WORD vecnum;
           LONG vec;
                 'vecnum' is the number of the vector  to  get  or
                 set.  'vec' is the address to setup in the vector
                 slot; no set  is  done  if  'vec'  is  -1L.   The
                 vector's previous value is returned.
                 Vectors $00 through  $FF  are  reserved  for  the
                 Logical vectors $100 through  $1FF  are  reserved
                 for GEMDOS.  Vectors currently implemented are:
                       $100  System timer interrupt
                       $101  Critical error handler
                       $102  Process terminate hook
                     $103..$107:  Currently unused, reserved
                 Logical vectors $200 through $FFFF  are  reserved
                 for  OEM use.  The ST BIOS makes no provision for
       (6) tickcal
           LONG tickcal()
                 Returns a system-timer calibration value, to  the
                 nearest millisecond.
                 This is a silly function,  since  the  number  of
                 elapsed  milliseconds is passed on the stack dur-
                 ing a system-timer trap.
       (7) *getbpb
           BPB *getbpb(dev)
           WORD dev;
                 'dev' is a device number (0 for  drive  A,  etc.)
                 Returns a pointer to the BIOS Parameter Block for
                 the specified drive, or 0L if (for  some  reason)
                 the BPB cannot be determined.
       (8) bcostat
           LONG bcostat(dev)
                 'dev' is a character device number, as  in  func-
                 tion 1.  Returns character output status:
                        -1   Device is ready to send (no waiting on
                             next device-output call).
                         0   Device is not ready to send.
       (9) mediach
           LONG mediach(dev)
           WORD dev;
                 'dev' is a drive number.  Returns one of:
                         0   Media definitely has not changed
                         1   Media /might/ have changed
                         2   Media definitely has changed
                 GEMDOS will respond to a return value of '1' with
                 a  read  operation.  If the BIOS detects an abso-
                 lute  media  change,  it  will  return  a  "media
                 change" error at that time.
       (10) drvmap
           LONG drvmap()
                 Returns a bit-vector that contains a '1' in a bit
                 position  (0 .. 31) when a drive is available for
                 that bit, or a 0 if there is no  drive  available
                 for the bit.
                 Installable disk drivers must correctly  maintain
                 the longword '_drvbits' [see: System Variables].
       (11) kbshift
           LONG kbshift(mode)
           WORD mode;
                 If 'mode'  is  non-negative,  sets  the  keyboard
                 shift  bits accordingly and returns the old shift
                 bits.  If 'mode' is less than zero,  returns  the
                 IBM-PC  compatible state of the shift keys on the
                 keyboard, as a bit-vector in the low byte of D0.
                 Bit assignments are:
                       0     Right shift key
                       1     Left shift key
                       2     Control key
                       3     ALT key
                       4     Caps-lock
                       5     Right mouse button (CLR/HOME)
                       6     Left mouse button (INSERT)
                       7     (reserved, currently zero)
      Extended BIOS         August 26, 1985                      9
      These functions are available through trap 14.  The  calling
      conventions  are  the  same as for trap 13.  Contrary to the
      GEMDOS specification, the caller does  NOT  have  to  be  in
      supervisor  mode.   It  is  the  caller's  responsibility to
      cleanup arguments passed to the trap (as per the  C  calling
      A typical trap handler, one that works  from  a  C  binding,
      might be:
                  move.l  (sp)+,tr14ret   ; pop ret addr
                  trap    #14             ; do BIOS func
                  move.l  tr14ret,-(sp)   ; return to
                  rts                     ;  caller
          tr14ret: ds.l                   ; saved ret. addr
      and it might be used like:
           * Stupid way to set the screen to a single value.
          WORD v;
              extern long trap14();
              register WORD *p;
              register int i;
              scrbase = (WORD *)trap14(3);
              for (i = 0x4000; i; --i)
                  *p++ = v;
           * Xor palettes in a range with a given value
          set_palette_range(start, fin, v)
          WORD start, fin, v;
              while (start <= fin)
                  trap14(7, trap14(7, -1) ^ v);
       (0) initmous
           VOID initmous(type, param, vec)
           WORD type;
           LONG param, vec;
                 Initialize mouse packet handler.  'type'  is  one
                      type   Action
                       0     disable mouse
                       1     enable mouse, in relative mode
                       2     enable mouse, in absolute mode
                       3     (unused)
                       4     enable mouse, in keycode mode
                  'param' points to a parameter block that  should
                 look like:
                     struct param {
                         BYTE topmode;
                         BYTE buttons;
                         BYTE xparam;
                         BYTE yparam;
                 'topmode' should be:
                       0     Y_position == 0 at bottom
                       1     Y_position == 0 at top
                 'buttons' is a parameter for the keyboard's  "set
                 mouse buttons" command.
                 'xparam' and 'yparam' are the X and Y  threshold,
                 scale or delta factors, depending on the mode the
                 mouse is being placed in.
                        Atari Corp. Confidential
      Extended BIOS         August 26, 1985                     11
                 For mouse absolute mode,  some  extra  parameters
                 immediately follow the parameter block:
                     struct extra {
                         WORD xmax;
                         WORD ymax;
                         WORD xinitial;
                         WORD yinitial;
                 'xmax' and 'ymax' specify the  maximum  X  and  Y
                 mouse   positions.    'xinitial'  and  'yinitial'
                 specify the initial X and Y mouse position.
                 'vec' points to a mouse  interrupt  handler;  see
                 extended  function  number  34,  'kbdvbase',  for
                 further   information   about   ikbd    subsystem
       (1) ssbrk
           LONG ssbrk(amount)
           WORD amount;
                 Reserve 'amount' bytes from the  top  of  memory.
                 Returns  a long pointing to the base of the allo-
                 cated  memory.   This  function  MUST  be  called
                 before the OS is initialized.
                 'ssbrk' is actually pretty useless.  It DOES  NOT
                 work  after GEMDOS has been brought up, since the
                 TPA has already been set up.
       (2) _physBase
           LONG _physBase()
                 Get the screen's physical base  address  (at  the
                 beginning of the next vblank).
       (3) _logBase
           LONG _logBase()
                 Get the screen's logical base, right away.   This
                 is the location that GSX uses when drawing to the
       (4) _getRez
           WORD _getRez()
                 Get the screen's current resolution (returning 0,
                 1 or 2).
       (5) _setScreen
           VOID _setScreen(logLoc, physLoc, rez)
           LONG logLoc, physLoc;
           WORD rez;
                 Set the logical  screen  location  (logLoc),  the
                 physical  screen location (physLoc), and the phy-
                 sical screen resolution.  Negative parameters are
                 ignored (making it possible, for instance, to set
                 screen  resolution  without   changing   anything
                 The logical screen location changes  immediately.
                 The physical screen location hardware register is
                 changed immediately, but the new screen  location
                 will take effect after the next vertical retrace.
                 When  resolution  is  changed,  the   screen   is
                 cleared, the cursor is homed, and the VT52 termi-
                 nal emulator state is reset.
       (6) _setPallete
           VOID _setPallete(palettePtr)
           LONG palettePtr;
                 Set the contents of the hardware palette register
                 (all  16 color entries) from the 16 words pointed
                 to by 'palettePtr'.  'paletteptr' MUST  be  on  a
                 word  boundary.   The  palette  assignment  takes
                 place at the beginning of the next vertical blank
       (7) _setColor
           WORD _setColor(colorNum, color)
           WORD colorNum, color;
                 Set the palette number 'colorNum' in the hardware
                 palette table to the given color.  Return the old
                 color in  D0.W.   If  'color'  is  negative,  the
                 hardware register is not changed.
       (8) _floprd
           WORD  _floprd(buf,  filler,  devno,  sectno,   trackno,
                 sideno, count)
           LONG buf, filler;
           WORD devno, sectno, trackno, sideno, count;
                 Read one or more  sectors  from  a  floppy  disk.
                 'filler' is an unused longword.  'buf' must point
                 to a word-aligned buffer large enough to  contain
                 the  number of sectors requested.  'devno' is the
                 floppy number (0 or 1).  'sectno' is  the  sector
                 number  to  start reading from (usually 1 through
                 9).  'trackno' is the track number  to  seek  to.
                 'sideno'  is  the side number to select.  'count'
                 is the number of sectors to read (which  must  be
                 less  than  or equal to the number of sectors per
                 On return, D0 contains a status code.  If  D0  is
                 zero, the operation succeeded.  If D0 is nonzero,
                 the operation failed (and D0  contains  an  error
                        Atari Corp. Confidential
       (9) _flopwr
           WORD  _flopwr(buf,  filler,  devno,  sectno,   trackno,
                 sideno, count)
           LONG buf, filler;
           WORD devno, sectno, trackno, sideno, count;
                 Write one or  more  sectors  to  a  floppy  disk.
                 'buf'   must  point  to  a  word-aligned  buffer.
                 'filler' is an unused longword.  'devno'  is  the
                 floppy  number  (0 or 1).  'sectno' is the sector
                 number to start writing to (usually 1 through 9).
                 'trackno'   is  the  track  number  to  seek  to.
                 'sideno' is the side number to  select.   'count'
                 is  the number of sectors to write (which must be
                 less than or equal to the number of  sectors  per
                 On return, D0 contains a status code.  If  D0  is
                 zero, the operation succeeded.  If D0 is nonzero,
                 the operation failed (and D0  contains  an  error
                 Writing to the boot sector  (sector  1,  side  0,
                 track 0) will cause the media to enter the "might
                 have changed" state.  This will be  reflected  on
                 the next rwabs() or mediach() BIOS call.
       (10) _flopfmt
           WORD _flopfmt(buf, filler, devno, spt, trackno, sideno,
                 interlv, magic, virgin)
           LONG buf, filler;
           WORD devno, spt, trackno, sideno, interlv, virgin;
           LONG magic;
                 Format a track on  a  floppy  disk.   'buf'  must
                 point  to  a  word-aligned buffer large enough to
                 hold an entire track image  (8K  for  9  sectors-
                 per-track).   'filler'  is  an  unused  longword.
                 'devno' is the floppy  drive  number  (0  or  1).
                 'spt'  is the number of sectors-per-track to for-
                 mat (usually 9).  'trackno' is the  track  number
                 to  format  (usually  0  to 79).  'sideno' is the
                 side number to format (0 or 1).  'interlv' is the
                 sector-interleave factor (usually 1).  'magic' is
                 a magic number that MUST be the value  $87654321.
                 'virgin' is a word fill value for new sectors.
                 On return, D0 contains a status code.  If  D0  is
                 zero, the operation succeeded.  If D0 is nonzero,
                 the operation failed (and D0  contains  an  error
                 number).   The format function can soft-fail when
                 it finds bad sectors during the verify pass.  The
                 caller  has the choice of attempting to re-format
                 the media, or recording the bad sectors  so  they
                 will not be included in the file system.
                 A  null-terminated  (0.W)  list  of  bad   sector
                 numbers  is returned in the buffer.  They are not
                 necessarily in numerical order.  (If  there  were
                 no bad sectors, the first word in the buffer will
                 be zero.)
                 A good value for 'virgin'  is  $E5E5.   The  high
                 nibble  of  each  byte  in the 'virgin' parameter
                 must not be equal to $F.  Resist  the  temptation
                 to  format  a  disk  with  sectors initialized to
                 Formatting a track will cause the media to  enter
                 the  "definitely  changed"  state.   This will be
                 reflected on the next rwabs() or  mediach()  BIOS
       (11) used-by-BIOS
           VOID used-by-BIOS()
                 [Obsolete function]
       (12) midiws
           VOID midiws(cnt, ptr)
           WORD cnt;
           LONG ptr;
                 Writes a string to the MIDI port.  'cnt'  is  the
                 number  of characters to write, minus one.  'ptr'
                 points to a vector of characters to write.
       (13) _mfpint
           VOID _mfpint(interno, vector)
           WORD interno;
           LONG vector;
                 Set the MFP interrupt number 'interno' (0 to  15)
                 to 'vector'.  The old vector is written over (and
                 thus unrecoverable).
       (14) iorec
           LONG iorec(devno)
           WORD devno;
                 Returns a pointer  to  a  serial  device's  input
                 buffer record.  'devno' is one of:
                     devno   Device
                     -----   --------
                       0     RS232
                       1     Keyboard
                       2     MIDI
                 The structure of the record is:
                     struct iorec
                         LONG ibuf;          /* pointer to buffer */
                         WORD ibufsiz;       /* size of buffer */
                         WORD ibufhd;        /* head index */
                         WORD ibuftl;        /* tail index */
                         WORD ibuflow;       /* low-water mark */
                         WORD ibufhi;        /* high-water mark */
                 For RS-232, an output-buffer  record  immediately
                 follows  the  input-buffer record.  The format of
                 the output-buffer record is identical.
                 'ibuf' points to the device's buffer.   'ibufsiz'
                 is  the  buffer's size.  'ibufhi' is the buffer's
                 high-water mark.  'ibuflow' is the buffer's  low-
                 water mark.
                 If flow control is  enabled  and  the  number  of
                 characters  in  the buffer reaches the high-water
                 mark, the ST requests  (according  to  the  flow-
                 control  protocol)  the  sender  to  stop sending
                 characters.  When the number of characters in the
                 buffer  drops  below  the  low-water mark, the ST
                 tells the sender to resume transmission.
                 The flow-control operation  is  similar  for  the
                 RS-232 output record.
       (15) rsconf
           VOID rsconf(speed, flowctl, ucr, rsr, tsr, scr)
           WORD speed, flowctl, ucr, rsr, tsr, scr;
                 Configure RS-232 port.  If any  parameter  is  -1
                 ($FFFF),  the  corresponding hardware register is
                 not set.  'speed' sets the port's baud  rate,  as
                     speed         Rate (bps)
                     -----         ----------
                       0             19,200
                       1             9600
                       2             4800
                       3             3600
                       4             2400
                       5             2000
                       6             1800
                       7             1200
                       8             600
                       9             300
                       10            200
                       11            150
                       12            134
                       13            110
                       14            75
                       15            50
                 'flow' sets the flow control, as per:
                     flow    Flavor
                     -----   ---------
                       0     No flow control [powerup default]
                       1     XON/XOFF (^S/^Q)
                       2     RTS/CTS
                       3     XON/XOFF and RTS/CTS [is this useful?]
                 'ucr', 'rsr', 'tsr', and 'scr' set the  appropri-
                 ate 68901 registers.
       (16) keytbl
           LONG keytbl(unshift, shift, capslock)
           LONG unshift, shift, capslock;
                 Sets pointers to the keyboard translation  tables
                 for  unshifted  keys,  shifted  keys, and keys in
                 caps-lock mode.  Returns a pointer to the  begin-
                 ning of a structure:
                     struct keytab {
                         LONG unshift;       /* -> unshift table */
                         LONG shift;         /* -> shift table */
                         LONG capslock;      /* -> capslock table */
                 Each pointer in the structure should point  to  a
                 table  128  bytes  in length.  A scancode is con-
                 verted to Ascii by indexing into  the  table  and
                 taking the byte there.
       (17) _random
           LONG _random()
                 Returns a 24-bit psuedo-random  number  in  D0.L.
                 Bits  24..31 will be zero.  The sequence /should/
                 be different each time the system is  turned  on.
                 [The algorithm is from vol. 2 of Knuth:
                                  S = [S * C] + K
                 where K = 1, C = 3141592621, and S is  the  seed.
                 S  >>  8  is returned.  The initial value of S is
                 taken from the frame-counter '_frclock'.]
                 The function's  behavior  is  surprisingly  good,
                 except  that bit 0 has an /exact/ distribution of
                 50%.  Therefore it is probably not a good idea to
                 test  individual  bits and expect them to be well
       (18) _protobt
           VOID _protobt(buf, serialno, disktype, execflag)
           LONG buf, serialno;
           WORD disktype, execflag;
                 Prototype an image of a boot  sector.   Once  the
                 boot  sector image has been constructed with this
                 function, write it to the volume's boot sector.
                 'buf' points to a 512-byte buffer (which may con-
                 tain  garbage,  or  already contain a boot sector
                 'serialno' is a serial number to stamp  into  the
                 boot  sector.   If  'serialno'  is  -1,  the boot
                 sector's serial number is not changed.  If 'seri-
                 alno'  is  greater  than or equal to $01000000, a
                 random serial number is generated and  placed  in
                 the boot sector.
                 'disktype' is either -1 (to leave the  disk  type
                 information alone) or one of the following:
                     0: 40 tracks, single sided (180K)
                     1: 40 tracks, double sided (360K)
                     2: 80 tracks, single sided (360K)
                     3: 80 tracks, double sided (720K)
                 If 'execflag' is 1, the boot sector is made  exe-
                 cutable.   If 'execflag' is 0, the boot sector is
                 made non-executable.  If 'execflag'  is  -1,  the
                 boot  sector remains executable or non-executable
                 depending on the way it was originally.
       (19) _flopver
           WORD  _flopver(buf,  filler,  devno,  sectno,  trackno,
                 sideno, count)
           LONG buf, filler;
           WORD devno, sectno, trackno, sideno, count;
                 Verify (by simply reading) one  or  more  sectors
                 from  a floppy disk.  'buf' must point to a word-
                 aligned 1024-byte buffer.  'filler' is an  unused
                 longword.  'devno' is the floppy number (0 or 1).
                 'sectno' is the sector number  to  start  reading
                 from  (usually  1  through  9).  'trackno' is the
                 track number to seek to.  'sideno'  is  the  side
                 number  to  select.   'count'  is  the  number of
                 sectors to verify (which must  be  less  than  or
                 equal to the number of sectors per track).
                 On return, D0 contains a status code.  If  D0  is
                 zero, the operation succeeded.  If D0 is nonzero,
                 the operation failed (and D0  contains  an  error
                 A  null-terminated  (0.W)  list  of  bad   sector
                 numbers  is returned in the buffer.  They are not
                 necessarily in numerical order.  (If  there  were
                 no bad sectors, the first word in the buffer will
                 be zero.)
       (20) scrdmp
           VOID scrdmp()
                 Dump screen to printer.  [Currently this  is  the
                 monochrome-only  version from CES.  Will be fixed
       (21) cursconf
           WORD cursconf(function, operand)
           WORD function, operand;
                 Configure  the  "glass  terminal"  cursor.    The
                 'function' code is one of the following:
                       0     Hide cursor
                       1     Show cursor
                       2     Cursor set to blink
                       3     Cursor set not to blink
                       4     Set cursor blink timer to 'operand'
                       5     Return cursor blink timer value
                 The cursor blink rate is based on the video  scan
                 rate  (60hz  for color, 70hz for monochrome, 50hz
                 for PAL).  The 'rate' parameter is equal to  one-
                 half the cycle time.
       (22) settime
           VOID settime(datetime)
           LONG datetime;
                 Sets the intelligent keyboard's idea of the  time
                 and date.  'datetime' is a 32-bit DOS-format date
                 and time (time in the low word, date in the  high
       (23) gettime
           LONG gettime()
                 Interrogates the intelligent keyboard's  idea  of
                 the time and date, and returns that value (in DOS
                 format) as a 32-bit word.  (Time in the low word,
                 date in the high word).
       (24) bioskeys
           VOID bioskeys()
                 Restores the powerup  settings  of  the  keyboard
                 translation tables.
       (25) ikbdws
           VOID ikbdws(cnt, ptr)
           WORD cnt;
           LONG ptr;
                 Writes a  string  to  the  intelligent  keyboard.
                 'cnt' is the number of characters to write, minus
                 one.  'ptr' points to a vector of  characters  to
       (26) jdisint
           VOID jdisint(intno)
           WORD intno;
                 Disable interrupt number 'intno' on the 68901.
       (27) jenabint
           VOID jenabint(intno)
           WORD intno;
                 Enable interrupt number 'intno' on the 68901.
       (28) giaccess
           BYTE giaccess(data, regno)
           BYTE data;
           WORD regno;
                 Read or write  a  register  on  the  sound  chip.
                 'regno'  is  the  register number, logically ORed
                     $00 to read [well, ok, you don't
                         /really/ OR with this...]
                     $80 to write
                 'data' is a byte to write to the register.
                 Sound chip  registers  are  not  shadowed.   Pro-
                 cedures  that change register values by reading a
                 register, modifying a local copy of it, and writ-
                 ing  the  result  back to the register, should be
                 critical sections.  In particular, the BIOS (fre-
                 quently)  updates  the  PORT  A register, and any
                 code  that  read-modify-writes  PORT  A  must  be
       (29) offgibit
           VOID offgibit(bitno)
           WORD bitno;
                 Atomically set a bit in the PORT  A  register  to
       (30) ongibit
           VOID ongibit(bitno)
           WORD bitno;
                 Atomically set a bit in the PORT  A  register  to
       (31) xbtimer
           VOID xbtimer(timer, control, data, vec)
           WORD timer, control, data;
           LONG vec;
                 'timer'  is  the  timer  number  (0,  1,   2,   3
                 corresponding  to  68901  timers  A, B, C and D).
                 'control' is the  timer's  control-register  set-
                 ting.   'data'  is a byte shoved into the timer's
                 data register.  'vec' is a pointer to  an  inter-
                 rupt handler.
                 Timers are allocated:
                     Timer   Usage
                       A     Reserved for end-users and applications
                       B     Reserved for graphics (hblank sync, etc.)
                       C     System timer (200hz)
                       D     RS-232 baud-rate control (this timer's
                             interrupt vector is available to anyone).
       (32) dosound
           VOID dosound(ptr)
           LONG ptr;
                 Set sound daemon's "program  counter"  to  'ptr'.
                 'ptr'  points  to  a set of commands organized as
                 Command numbers $00 through $0F take a  one  byte
                 argument to be shoved into a sound chip register.
                 (Command $00 shoves the  byte  into  register  0,
                 command  1  shoves  the byte into register 1, and
                 you get the idea...)
                 Command $80 takes a one byte  argument  which  is
                 shoved into a temporary register.
                 Command $81 takes three one-byte arguments.   The
                 first  argument  is  a  register  number to load,
                 using the temp register.  The second argument  is
                 a  2's  complement  value to be added to the temp
                 register.  The third argument is the  termination
                 value.  The instruction is executed (once on each
                 update) until the temp register equals the termi-
                 nation value.
                 Commands  $82  through  $FF   take   a   one-byte
                 argument.   If the argument is zero, the sound is
                 terminated.  Otherwise the argument reflects  the
                 number  of system-timer ticks (at 50hz) until the
                 next update.
       (33) setprt
           WORD setprt(config)
           WORD config;
                 Set/get printer configuration byte.  If  'config'
                 is  -1  ($FFFF) return the current printer confi-
                 guration byte.  Otherwise set the byte and return
                 it's old value.
                 Bits currently defined are:
                      Bit#   When 0          When 1
                      ----   -------------   ---------------
                       0     Dot matrix      Daisy wheel
                       1     Color device    Monochrome device
                       2     Atari printer   "Epson" printer
                       3     Draft mode      Final mode
                       4     Parallel port   RS232 port
                       5     Form-feed       Single sheet
                       6             reserved
                       7             reserved
                       8             reserved
                       9             reserved
                       10            reserved
                       11            reserved
                       12            reserved
                       13            reserved
                       14            reserved
                       15    Must be zero
       (34) kbdvbase
           LONG kbdvbase()
                 Returns a pointer to the base of a structure:
                     struct kbdvecs {
                         LONG midivec;       /* MIDI-input */
                         LONG vkbderr;       /* keyboard error */
                         LONG vmiderr;       /* MIDI error */
                         LONG statvec;       /* ikbd status packet */
                         LONG mousevec;      /* mouse packet */
                         LONG clockvec;      /* clock packet */
                         LONG joyvec;        /* joystick packet */
                         LONG midisys;       /* system MIDI vector */
                         LONG ikbdsys;       /* system IKBD vector */
                 'midivec' is initialized to point to a  buffering
                 routine in the BIOS.  D0.B will contain a charac-
                 ter read from the MIDI port.
                 'vkbderr' and 'vmiderr' are  called  whenever  an
                 overrun  condition is detected on the keyboard or
                 MIDI 6850s.  [Probably not  a  useful  vector  to
                 'statvec', 'mousevec', 'clockvec',  and  'joyvec'
                 point to ikbd status, mouse, real-time clock, and
                 joystick packet handlers.   The  packet  handlers
                 are  passed  a  pointer to the packet received in
                 A0, and on the stack as a LONG.  GEM/GSX uses the
                 mouse  vector.   Handlers  should  return with an
                 RTS, and should not spend more than 1ms  handling
                 the interrupt.
                 The 'midisys' and 'ikbdsys'  vectors  are  called
                 when  characters are available on the appropriate
                 6850.  Initially they point to  default  routines
                 (the  MIDI  handler  indirects through 'midivec',
                 and the ikbd handler parses-out ikbd packets  and
                 calls the appropriate subsystem vectors).
       (35) kbrate
           WORD kbrate(initial, repeat)
           WORD initial, repeat;
                 Get/set the keyboard's  repeat  rate.   'initial'
                 governs  the  initial  delay  (before  key-repeat
                 starts).  'repeat'  governs  the  rate  at  which
                 key-repeats  are generated.  If a parameter is -1
                 ($FFFF) it is not changed.  Times  are  based  on
                 system ticks (50hz).
                 Returns the old key-repeat values, with 'initial'
                 in  the high byte of the low word and 'repeat' in
                 the low byte of the low word.
       (36) _prtblk
           VOID _prtblk()
                 Prtblk() primitive [see manual pages on PRTBLK].
       (37) vsync
           VOID vsync()
                 Waits until the next vertical-blank interrupt and
                 returns.    Useful   for  synchronizing  graphics
                 operations with vblank.
       (38) supexec
           VOID supexec(codeptr)
           LONG codeptr;
                 'codeptr' points to a piece of code, ending in an
                 RTS,  that  is  executed in supervisor mode.  The
                 code cannot perform BIOS or GEMDOS  calls.   This
                 function  is  meant  to  allow  programs  to hack
                 hardware and protected locations  without  having
                 to  fiddle  with  GEMDOS  get/set supervisor mode
       (39) puntaes
           VOID puntaes()
                 Throws away the AES, freeing  up  any  memory  it
                 used.   If  the AES is still resident, it will be
                 discarded and the system will reboot.  If the AES
                 is not resident (if it was discarded earlier) the
                 function will return.
                 There is NO way to throw away the AES and  return
                 --  the  reboot MUST be performed.  [Ok, ok -- we
                 know this is a lose.]
      Terminal Escapes      August 26, 1985                     24
                        CONOUT Escape Sequences
      These are the escape  functions  interpreted  by  the  BIOS'
      conout()  function.   For the most part they emulate a VT-52
      terminal [that's the easy one to do].  There are  extensions
      to  hack screen colors, control screen wrap, and a few other
      simple functions.
      ESC A
      Cursor Up
           This sequence moves the cursor up  one  line.   If  the
           cursor  is  already on the top line of the screen, this
           sequence has no effect.
      ESC B
      Cursor Down
           This moves the cursor down one line.  If the cursor  is
           already  on  the  last  line of the screen, this escape
           sequence has no effect.
      ESC C
      Cursor Forward
           This moves the cursor one position to  the  right.   If
           this  function  would  move  the cursor off the screen,
           this sequence has no effect.
      ESC D
      Cursor Backward
           This move the cursor one position to the left.  This is
           a  non-  destructive  move  because  the character over
           which the cursor now rests is not replaced by a  blank.
           If  the  cursor  is  already  in  column O, this escape
           sequence has no effect.
      ESC E
      Clear Screen (and Home Cursor)
           This moves the cursor to  column  O,  row  I  (the  top
           left-hand corner of the screen), and clears all charac-
           ters from the screen.
      ESC H
      Home Cursor
           This move the cursor to column O, row O.  The screen is
           NOT cleared.
      ESC I
      Reverse Index
           Moves the cursor to the same horizontal position on the
                        Atari Corp. Confidential
      Terminal Escapes      August 26, 1985                     25
           preceding  lines.   If the cursor is on the top line, a
           scroll down is performed.
      ESC J
      Erase to End of Page
           Erases all the information from cursor (including  cur-
           sor position) to the end of the page.
      ESC K
      Clear to End of Line
           This sequence clears the line from the  current  cursor
           position to the end of the line.
      ESC L
      Insert Line
           Inserts a new blank line by moving the line that cursor
           is  on,  end all following lines, down one line.  Then,
           the cursor is moved to the beginning of the  new  blank
      ESC M
      Delete Line
           Deletes the contents of the line that the cursor is on,
           places  the  cursor at the beginning of the line, moves
           all the following lines up one line, and adds  a  blank
           line at the bottom.
      ESC Y
      Position Cursor
           The two characters that follow the "Y" specify the  row
           and  column  to  which  the cursor is to be moved.  The
           first character specifies the row, the second specifies
           the colum.  Rows and columns number from 1 up.
      ESC b
      Set Foreground Color
           The Foreground Color is the color in which the  charac-
           ter is displayed.
           Escape-b must be followed by a color selection  charac-
           ter.  Only the four least significant bits of the color
           character are used:
           Bit Pattern of Control Byte:
                  7     6     5     4     3     2     1     0
               |     |     |     |     |                       |
               |  X  |  X  |  X  |  X  |    color index        |
               |     |     |     |     |                       |
               (X = "don't care")
      ESC c
      Set Background Color
           This function selects Background Color,  the  color  of
           the cell that contains the characters.
           Escape-c must be followed by a color selection  charac-
           ter.  Only the four least significant bits of the color
           character are used.  (See diagram for ESC-b function)
      ESC d
      Erase Beginning of Display
           This sequence erases from beginning of the  display  to
           the  cursor  position.   The  cursor position is erased
      ESC e
      Enable Cursor
           This sequence causes the cursor to be  invisible.   The
           cursor  may  still be moved about on the display, using
           escape sequence defined in this appendix.
      ESC f
      Disable Cursor
           This sequence causes the cursor to be  invisible.   The
           cursor  may  still be moved about on the display, using
           escape sequences defined in this appendix.
      ESC j
      Save Cursor Position
           This sequence preserves the  current  cursor  position.
           You  can  restore  the  cursor  to the previously saved
           position with ESC-k.
      ESC k
      Restore Cursor Position
           This sequence restores the cursor to a previously saved
           position.  If you use this sequence without having pre-
           viously saved the cursor position, then the  cursor  is
           moved to the home position, the top left-hand corner of
           the screen.
      ESC l
      Erase Entire Line
           This sequence erases an entire line and moves the  cur-
           sor to the leftmost column.
      ESC o
      Erase Beginning of Line
           Erases from the beginning of the line to the cursor and
           includes the cursor position.
      ESC p
      Enter Reverse Video Mode
           Enters the reverse video mode so  that  characters  are
           displayed  as  background  color  characters on a fore-
           ground colored cell.
      ESC q
      Exit Reverse Video Mode
           Exits the reverse video mode.
      ESC v
      Wrap at End of Line
           This sequence causes the first character past the  last
           displayable  position  on  a  line  to be automatically
           placed in the first  character  position  on  the  next
           line.  The page scrolls up if necessary.
      ESC w
      Discard at End of Line
           Following invocation of this sequence, after  the  last
           displayable  character  on a line has been reached, the
           characters overprint.  Therefore, only the last charac-
           ter received is displayed in the last column position.
* interrupts
                Traps, Interrupts and Interrupt Vectors
      The ST makes use of four of the sixteen  TRAP  vectors  pro-
      vided  by  the  68000.   All  other  traps are available for
           Trap   Use
           ----   ----
            0     (none)
            1     GEMDOS interface
            2     DOS extensions (GEM, GSX)
            3     (none)
            4     (none)
            5     (none)
            6     (none)
            7     (none)
            8     (none)
            9     (none)
            10    (none)
            11    (none)
            12    (none)
            13    BIOS
            14    Atari BIOS extensions
            15    (none)
      68901 interrupts are based at $100.  The  sixteen  longwords
      at this location are bound by the hardware to:
           Vector    Function
            $100     (disabled) Parallel port int.
            $104     (disabled) RS232 Carrier Detect
            $108     (disabled) RS232 Clear-To-Send
            $10c     (disabled)
            $110     (disabled)
            $114     200hz System clock
            $118     Keyboard/MIDI [6850]
            $11c     (disabled) Polled FDC/HDC
            $120     HSync (initially disabled)
            $124     RS232 transmit error
            $128     RS232 transmit buffer emtpy
            $12c     RS232 receive error
            $130     RS232 receive buffer full
            $134     (disabled)
            $138     (disabled) RS232 ring indicator
            $13c     (disabled) Polled monitor type
      The divide-by-zero vector is pointed at an RTE.
      All other traps (Bus Error, et al) are pointed at a  handler
      that dumps the processor state and attempts to terminate the
      current process.  [See: System Initialization]
      The Line 1010 ("Line Aye") vector is used as a short-circuit
      around  the  VDI  to  the ST's graphics primitives.  It is a
      powerful and useful interface; see the `Line A' document for
      further information.
      The Line 1111 ("Line Eff")  trap  is  currently  being  used
      internally  to  the  system.  If you fiddle with this vector
      the AES will break.
      The FDC/HDC interrupt may be enabled by a hard  disk  device
      driver.   The floppy disk code, however, assumes this inter-
      rupt is disabled (it busy-waits on the input  bit's  state).
      It  is  the responsibility of other drivers in the system to
      ensure that, when the  floppy  disk  read/write/format  code
      gets control, the FDC/HDC interrupt is disabled.
      The processor's normal interrupt priority level is 3.   This
      is  to  prevent  HBLANK (autovector level 2) interrupts from
      occurring on every scanline.  [It would eat about 10%  of  a
      system  running  in a color graphics mode, or about 22% of a
      system running in monochrome.   Yuck.]  The  default  HBLANK
      interrupt handler modifies the interrupted process' IPL to 3
      and performs an RTE.  This is to  discourage  programs  from
      using IPL 0 -- to use HBLANK, use an IPL of 1.
      To prevent "jittering" in programs that change screen colors
      on  the  fly,  using the HBLANK and HSYNC interrupt vectors,
      the following hack will keep the  system  intact  and  still
      yield a solid display:
         [1] Re-vector the keyboard/MIDI interrupt  to  a  routine
             that  lowers  the IPL to 5 and then jumps through the
             original vector.
         [2] During the "critical"  section  of  the  screen,  re-
             vector  the  200hz  system  clock interrupt vector to
             point to a routine  that  increments  a  counter  and
             RTEs.   The counter keeps track of the number of sys-
             tem ticks that occur during the critical section.
         [3] After the critical section, block interrupts (at  IPL
             6)  and call the sytem clock handler (JMP through the
             interrupt vector, with a fake SR and  return  address
             on  the  stack)  the number of times indicated by the
                             System Variables
         This is a list of variables in the ST BIOS that have been
         "cast  in  concrete".   Their  locations  and meanings in
         future revisions of the ST BIOS  are  guarenteed  not  to
         Any other variables in RAM, routines in the ROM, or  vec-
         tors  below  $400 that are not documented here are almost
         certain to change.  It is  important  not  to  depend  on
         undocumented variables or ROM locations.
         etv_timer (long) $400
             Timer handoff vector (logical vector $100).  See GEM-
             DOS documentation.
         etv_critic (long) $404
             Critical error handoff vector (logical vector  $101).
             See GEMDOS documentation.
         etv_term (long) $408
             Process-terminate  handoff  vector  (logical   vector
             $102).  See GEMDOS documentation.
         etv_xtra (longs) $40c
             Space for logical vectors $103 through $107).
         memvalid (long) $420
             Contains the magic number $752019F3, which  (together
             with  'memval2') validates 'memcntlr' and indicates a
             successful coldstart.
         memcntlr (byte) $424
             Contains memory controller configuration nibble  (the
             low  nibble).   For  the full story, see the hardware
             manual.  Some popular values are:
                 Memory size     Value
                 128K            0
                 512K            4
                 256K (2 banks)  0
                 1MB (2 banks)   5
         resvalid (long) $426
             If 'resvalid' is the magic number $31415926 on system
             RESET, the system will jump though 'resvector'.
         resvector (long) $42a
             System-RESET bailout vector, valid if 'resvalid' is a
             magic  number.  Called early-on in system initializa-
             tion (before /any/ hardware registers, including  the
             memory  controller  configuration register, have been
             touched).  A return address will be loaded  into  A6.
             Both stack pointers will contain garbage.
         phystop (long) $42e
             Physical top of RAM.  Contains a pointer to the first
             unusable byte (i.e. $80000 on a 512K machine).
         _membot (long) $432
             Bottom of available memory.  The 'getmpb' BIOS  func-
             tion uses this value as the start of the GEMDOS TPA.
         _memtop (long) $436
             Top of available memory.  The 'getmpb' BIOS  function
             uses this value as the end of the GEMDOS TPA.
         memval2 (long) $43a
             Contains the magic number $237698AA  which  (together
             with 'memvalid') validates 'memcntlr' and indicates a
             successful coldstart.
         flock (word) $43e
             Used to lock  usage  of  the  DMA  chip.   Should  be
             nonzero  to ensure that the OS does not touch the DMA
             chip registers during vertical blank.   Device-driver
             writers  TAKE  NOTE: this variable MUST be nonzero in
             order to make use of the DMA bus.
         seekrate (word) $440
             Default floppy seek rate.  Bits zero and one  contain
             the default floppy disk seek rate for both drives:
                 00      6ms
                 01      12ms
                 10      2ms
                 11      3ms [default]
         _timr_ms (word) $442
             System timer calibration (in ms).  Should be $14  (20
             decimal), since the timer handoff vector is called at
             50hz.  Returned  by  BIOS  function  '_tickcal',  and
             passed on the stack to the timer handoff vector.
         _fverify (word) $444
             Floppy verify flag.   When  nonzero,  all  writes  to
             floppies  are  read-verified.   When  zero, no write-
             verifies  take  place.   The  default  state   (after
             system-reset) is to verify.
         _bootdev (word) $446
             Contains the device  number  the  system  was  booted
             from.   The BIOS constructs an enviroment string from
             this variable before bringing up the desktop.
         palmode (word) $448
             When nonzero, indicates the system is  in  PAL  (50hz
             video)  mode.   When zero, indicates the system is in
             NTSC (60hz video) mode.
         defshiftmd (byte) $44a
             Default video resolution.  If the system is forced to
             change  from  monochrome  mode to a color resolution,
             'defshiftmd' contains the resolution the system  will
             switch to.
         sshiftmd (word) $44c
             Contains shadow for 'shiftmd' hardware register:
                 0       320x200x4 (low resolution)
                 1       640x200x2 (medium rez)
                 2       640x400x1 (high rez / "monochrome")
         _v_bas_ad (long) $44e
             Pointer to base of screen memory.  Always on  a  512-
             byte  boundary.   Always  points to 32K of contiguous
         vblsem (word) $452
             Semaphore to enforce mutual  exclusion  in  vertical-
             blank  interrupt  handler.   Should  be '1' to enable
             vblank processing,
         nvbls (word) $454
             Number of longwords that '_vblqueue' points to.   (On
             RESET, defaults to 8).
         _vblqueue (long) $456
             Pointer to a vector of pointers to vblank handlers.
         colorptr (long) $45a
             Pointer to a vector of 16  words  to  load  into  the
             hardware  palette  registers  on the next vblank.  If
             NULL, the palettes are  not  loaded.   'colorptr'  is
             zeroed after the palettes are loaded.
         screenpt (long) $45e
             Pointer to the base of screen memory, to be setup  on
             the  next  vblank.   If  NULL, the screen base is not
         _vbclock (long) $462
             Count of vertical-blank interrupts.
         _frclock (long) $466
             Count of vertical-blank  interrupts  that  were  pro-
             cessed (not blocked by 'vblsem').
         hdv_init (long) $46a
             Vector to hard disk initialization.  NULL if unused.
         swv_vec (long) $46e
             The system follows this  vector  when  it  detects  a
             transition  on  the "monochrome monitor detect" input
             (from low to high  rez,  or  visa-versa).   'swv_vec'
             initially  points to the system reset handler; there-
             fore the system will reset if the user changes  moni-
         hdv_bpb (long) $472
             Vector to routine to return a hard disk's Bios Param-
             eter  Block  (BPB).   Same calling conventions as the
             BIOS function for GETBPB.  NULL if unused.
         hdv_rw (long) $476
             Vector to routine to read or write on  a  hard  disk.
             Same  calling  conventions  as  the BIOS function for
             RWABS.  NULL if unused.
         hdv_boot (long) $47a
             Vector to routine to boot from hard  disk.   NULL  if
         hdv_mediach (long) $47e
             Vector to routine  to  return  a  hard  disk's  media
             change  mode.   Same  as  BIOS  binding for floppies.
             NULL if unused.
         _cmdload (word) $482
             When nonzero an attempt is made to load  and  execute
             COMMAND.PRG  from  the boot device.  (Load a shell or
             an application in place of the desktop).  Can be  set
             to nonzero by a boot sector.
         conterm (byte) $484
             Contains attribute bits for the console system:
                 Bit     Function
                 0       nonzero: enable bell when ^G is written to CON:
                 1       nonzero: enable key-repeat
                 2       nonzero: enable key-click
                 3       nonzero: on BIOS conin() function, return the
                                  current value of 'kbshift' in bits
                                  24..31 of D0.L.
                         zero:    leave bits 24..31 alone...
         themd (long) $48e
             Filled in by the BIOS on a 'getmpb'  call;  indicates
             to GEMDOS the limits of the TPA.  The structure is:
                 struct MD
                         MD      *m_link;        /* ->next MD [NULL] */
                         long    m_start;        /* start of TPA */
                         long    m_length;       /* size of TPA (bytes) */
                         PD      *m_own;         /* ->MD's owner [NULL] */
                 } ;
             The structure may NOT be changed once GEMDOS has been
             initialized.   In  addition, there may be only ONE of
             these suckers (you can't use the  'm_link'  field  in
             the  first MD).  Someday these (with a better GEMDOS)
             these limitations may be lifted.
         savptr (long) $4a2
             Pointer to register save area for BIOS functions.
         _nflops (word) $4a6
             Number of floppy disks actually attached to the  sys-
             tem (0, 1, or 2).
         sav_context (long) $4ae
             Pointer to saved  processor  context  (more  on  this
         _bufl (long) $4b4
             Two (GEMDOS) buffer-list  headers.   The  first  list
             buffers data sectors, the second list buffers FAT and
             directory sectors.  Each of these pointers points  to
             a BCB (Buffer Control Block), that looks like:
                 struct BCB
                         BCB     *b_link;        /* next BCB */
                         int     b_bufdrv;       /* drive#, or -1 */
                         int     b_buftyp;       /* buffer type */
                         int     b_bufrec;       /* record# cached here */
                         int     b_dirty;        /* dirty flag */
                         DMD     *b_dm;          /* -> Drive Media Descriptor */
                         char    *b_bufr;        /* -> buffer itself */
                 } ;
         _hz_200 (long) $4bc
             Raw 200hz system timer tick.  Used to  divide-by-four
             for a 50hz system timer.
         the_env (byte[4]) $4be
             The default enviroment string.  Four bytes of $00....
         _drvbits (long) $4c4
             32-bit vector, returned by the "DRIVEMAP" BIOS  func-
             tion (#10), of "live" block devices.  If any floppies
             are attached, this value is 3.
         _dskbufp (long) $4c6
             Points to a 1024-byte disk buffer  somewhere  in  the
             system's  BSS.   The buffer is ALSO used for some GSX
             graphics operations, and should not be used by inter-
             rupt routines.
         _prt_cnt (word) $4ee
             Initialized to -1.  Pressing the ALT-HELP key  incre-
             ments this.  The screen dump code checks for $0000 to
             start imaging the screen to the printer,  and  checks
             for nonzero to abort the screen print.
         _sysbase (long) $4f2
             Points to the base of the OS (in ROM or RAM).
         _shell_p (long) $4f6
             Points to shell-specific context.
         end_os (long) $4fa
             Points just past the last byte of low RAM used by the
             operating  system.   This is used as the start of the
             TPA (end_os is copied into _membot).
         exec_os (long) $4fe
             This points to the shell that gets exec'd by the BIOS
             after  system  initialization  is complete.  Normally
             this points to the first byte of the AES'  text  seg-
                          POST MORTEM INFORMATION
         If a diagnostic cartridge is not inserted,  all  "unused"
         interrupt  vectors  are  pointed to a handler in the BIOS
         that saves the  processor's  state  in  low  memory  (see
         below)  and  displays  a number of icons in the middle of
         the screen.  The handler attempts to restart  the  system
         after  the  crash -- it is not always (honestly: it isn't
         very often) successful.
         The exact number of icons represents the  exception  that
         occurred (2 for bus error, 3 for address error, and so on
         -- see the `Exception Processing' section in the Motorola
         68000 manual).
         The processor state is saved in an area of memory that is
         NOT  touched by a system reset.  Therefore it is possible
         to examine a post-mortem dump after resetting the  system
         to reboot.
             *  Post-mortem dump area;
             *  processor state saved here on uncaught exception:
             proc_lives      equ     $380    ; $12345678 iff valid
             proc_dregs      equ     $384    ; saved D0-D7
             proc_aregs      equ     $3a4    ; saved A0-A6, supervisor A7 (SSP)
             proc_enum       equ     $3c4    ; first byte is exception #
             proc_usp        equ     $3c8    ; saved user A7
             proc_stk        equ     $3cc    ; sixteen words popped from SSP
         If the longword at $380 is the  magic  number  $12345678,
         then the following information is valid (unless it's been
         stepped on by another crash).
         D0-D7, A0-A6, and the supervisor A7 are copied  to  loca-
         tions  $384  to  $3c0.   The  exception number (2 for bus
         error, etc.) is recorded in the byte at $3c4.   The  user
         A7  is  copied  to  $3c8.  The first sixteen words at the
         supervisor A7 are copied to the sixteen words starting at
         The function is Trap 1, number 32 (hex  $20).   It  wears
         three hats:
             LONG _super(stack)
             LONG stack;
         If 'stack' is -1 ($FFFFFFFF), then the  function  returns
         (in D0.L) either a 0 (indicating that the processor is in
         user mode) or a 1 (indicating that the  processor  is  in
         supervisor mode).
         If the function is called when the processor is  in  user
         mode, GEMDOS will return with the processor in supervisor
         mode.  The old value of  the  supervisor  stack  will  be
         returned  in D0.L.  If 'stack' was NULL ($00000000), then
         the supervisor stack will be the same as the  user  stack
         before  the call.  Otherwise the supervisor stack will be
         set to 'stack'.
         If the function is called when the processor is in super-
         visor mode, GEMDOS will return with the processor in user
         mode.  'stack' should be  the  value  of  the  supervisor
         stack  that  was  returned by the first call to the func-
         The old value  of  the  supervisor  stack  MUST  restored
         before  the  process  terminates.   (Failure to do so may
         result in a crash).
         And from assembly:
             *  superstuff - play around in supervisor mode
                     .  do user stuff
                     clr.l   -(sp)                   ; we want our own stack
                     move.w  #$20,-(sp)              ; get/set supervisor mode
                     trap    #1                      ; (do it)
                     addq    #6,sp                   ; (clean up)
                     move.l  d0,save_ssp             ; save old SSP
                     .  do supervisor stuff
                     move.l  save_ssp,-(sp)          ; push old SSP
                     move.w  #$20,-(sp)              ; get/set supervisor mode
                     trap    #1                      ; (do it)
                     addq    #6,sp                   ; (clean up)
                     .  do user stuff
                         GEMDOS Relocation Format
                     (Clarification to GEMDOS manual)
         This is the  REAL  GEMDOS  fixup  bytestream  format,  as
         implemented  by  the  function  xpgmld()  in  GEMDOS  (as
         opposed to what is documented in the GEMDOS manual):
             $00             no more relocation information
             $01             add $FE to the dot
             $02..$FF        add N to the dot, and fixup the longword there
         So, to fixup a longword $100 bytes from the  current  one
         (the dot), RELMOD would generate:
                     $01 $02
         [note that only longwords can be fixed up, and that  they
         must be on word boundaries.]
      Error Numbers         August 26, 1985                     42
                              Error Handling
         Error numbers are returned by certain BIOS and most  GEM-
         DOS  functions.   Note  that some GEMDOS functions return
         WORD error numbers instead of LONG ones  (that  is,  bits
         16..31 of D0.L are garbage).  Someday DRI will get around
         to fixing these ....
         [Describe  critical-error  handler  calling  conventions,
         whenever DRI gets around to defining them so they're use-
         0 (OK)
             Successful action (the anti-error).
         -1 (ERROR)
             All-purpose error.
         -2 (DRIVE_NOT_READY)
             Device was not ready, or was  not  attached,  or  has
             been busy for a long time.
         -3 (UNKNOWN_CMD)
             Device didn't know about a command.
         -4 (CRC_ERROR)
             Soft error while reading a sector.
         -5 (BAD_REQUEST)
             Device couldn't handle a command (the  command  might
             be  valid in other contexts).  Command parameters may
             be bad.
         -6 (SEEK_ERROR)
             Drive couldn't seek.
         -7 (UNKNOWN_MEDIA)
             Attempt to read foriegn media (usually means  a  cor-
             rupted or zero boot sector).
         -8 (SECTOR_NOT_FOUND)
             Sector could not be located.
         -9 (NO_PAPER)
             Printer is out of paper (this cannot happen on disks,
         -10 (WRITE_FAULT)
             Failure on a write operation.
         -11 (READ_FAULT)
             Failure on a read operation.
         -12 (GENERAL_MISHAP)
             Reserved for future catastrophes.  [This seems to  be
             a useless error right now.]
         -13 (WRITE_PROTECT)
             Attempt to write  on  write-protected  or  write-only
         -14 (MEDIA_CHANGE)
             Media changed since last write -- the operation (read
             or  write)  did NOT take place.  (This is more a mes-
             sage to the file system than a real error).
         -15 (UNKNOWN_DEVICE)
             Operation specified a device the  BIOS  doesn't  know
             anything about.
         -16 (BAD_SECTORS)
             Format operation succeeded (for the  most  part)  but
             yielded bad sectors.
         -17 (INSERT_DISK)
             Ask user to insert a disk (this is more a message  to
             the  shell  --  GEM  or  COMMAND.PRG  --  to  start a
             dialouge with the user).
                             Cartridge Support
         There are two kinds of  cartridges.   'Application'  car-
         tridges are recognized by GEM and the desktop.  'Diagnos-
         tic' cartridges are  executed  almost  immediately  after
         system  reset (before the 68000 touches any RAM), and may
         take over the entire system.
         The ST hardware maps cartridge space  to  a  128K  region
         starting  at $FA0000, extending to $FBFFFF.  The longword
         at $FA0000 has special meaning to the OS.  It  should  be
         one of the following:
                 $FA52255F indicates that a  diagnostic  cartridge
                     is inserted.
                 $ABCDEF42 indicates that an application cartridge
                     is inserted.
                 anything else is ignored.
         On system RESET, if a diagnostic  cartridge  is  inserted
         the   OS  will  (almost  immediately)  jump  to  location
         $FA0004.  A6 will contain a return  address  (should  the
         cartridge  ever  wish to continue with system initializa-
         tion).  The stack pointer will be garbage.  Most  of  the
         ST's  hardware registers will not have been touched.  The
         most significant of these registers is  the  memory  con-
         troller  --  the  diagnostic cartridge is responsible for
         sizing memory and initializing the memory controller.
         Application  cartridges   should   provide   'application
         header'  at  location  $FA0004 (immediately following the
         magic longword).  An application header contains informa-
         tion  about  an  application  in  ROM.   There may be any
         number of applications in a cartridge.
                     |       CA_NEXT         | 0   ->next header
                     |                       |
                     |       CA_INIT         | 4   ->init code
                     |                       |
                     |       CA_RUN          | 8   ->run code
                     |                       |
                     |       CA_TIME         | $c  DOS time
                     |       CA_DATE         | $e  DOS date
                     |       CA_SIZE         | $10 "size" of appl.
                     |                       |
                     |       CA_NAME         | $14 asciz name
                     |                       |     (NNNNNNNN.EEE\0)
                     |                       |
                     |                       |
         CA_NEXT is a pointer to the next application header.   If
         CA_NEXT  is  $00000000, then there are no more headers in
         the list.
         CA_INIT is a pointer to the application's  initialization
         code.   If  CA_INIT  is  NULL, there is no initialization
         code.  The initialization  vector  is  called  at  system
         startup  time,  as  controlled  by magic bits in the high
         byte of this longword (see below).
         CA_RUN is a  pointer  to  the  application's  main  entry
         CA_TIME and CA_DATE are DOS-format time and date  stamps.
         [They  are  kind  of  useful for keeping track of version
         numbers and things like that, but are  otherwise  useless
         CA_SIZE is a silly field that is the "size" of the appli-
         cation.   [This  field  is  pointless, but DRI wanted it,
         sooo ....]
         CA_NAME is the NULL-terminate name  of  the  application.
         It  should  be  in  the  same  format as a DOS acceptable
         filename, without a path (i.e. up to eight leading  char-
         acters,  optionally  followed  by  a  dot and up to three
         characters of extension, and a final NUL ($00)).
         The high 8 bits (24..31) of CA_INIT have special meaning:
             0 - Set to execute application (through CA_INIT  vec-
                 tor)  before  interrupt  vectors,  display memory
                 (etc.) have been initialized.
             1 - Set to execute application (through CA_INIT  vec-
                 tor) just before GEMDOS is initialized.
             2 - (unused)
             3 - Set to execute application (through CA_INIT  vec-
                 tor)  immediately  before  a  disk-boot.  [***FOR
                 NOW*** Applicable to boot ROM only.]
             4 - (unused)
             5 - Set if the application is a desk accessory.
             6 - Set if the application is NOT a GEM  application.
                 That is, it runs under DOS and doesn't do any AES
             7 - Set if non-GEM application (see bit  6)  requires
                 commandline parameters before execution.
                         Vertical Blank Interrupts
         This section describes the OS's Vertical Blank  Interrupt
         (VBI) handler, entered through the VBI vector at $70.
         The VBI handler increments the "frame counter"  'frclock'
         and then checks for mutual exclusion by testing 'vblsem'.
         If 'vblsem' is less than or equal to zero, no  other  VBI
         code  is executed.  Otherwise, all registers are saved on
         the stack and the "vblank counter"  'vbclock'  is  incre-
         If  the  system  is  currently  in  high-resolution  mode
         (SHIFTMD  >= 2) and a low-resolution monitor is attached,
         the resolution is set  to  'defshiftmd'.   (or  zero,  if
         'defshiftmd'  is  >=  2).  This test is necessary because
         some low-resolution monitors may "burn up" when driven by
         the ST's high-resolution video signal.
         The handler calls the cursor-blink routine.
         If 'colorptr' is nonzero, then the 16 color palettes  are
         loaded  from  the  16  words  that  'colorptr' points to.
         'colorptr' is then zeroed.
         If 'screenpt' is nonzero, then the screen's physical base
         address set to 'screenpt'.  'screenpt' is then zeroed.
         There may be any number of "deferred" VBI vectors.  These
         are  executed  just  before the VBI handler returns.  The
         variable 'nvbls' contains the current number of  deferred
         vector  slots.   'vblqueue'  points  to  an array of NVBL
         pointer slots that in turn point to deferred VBI code  or
         NULL (in the case of an empty slot):
                                 |vblqueue o|----+
                                 +----------+    |
                      |   ........... 'NVBL' entries ..................
                      |  /                                               (
                      |  +-------+-------+-------+-------+-------+-------+
                      +->|   o   |       |       |   o   |       |       |
                             |                       |
                             +---> handler...        +---> handler...
         The OS initially allocates 8 VBI slots.  The  first  slot
         is  reserved for GEM's VBI code.  To add another deferred
         handler, place a pointer in a free (NULL) slot.  If there
         are no more free slots, then allocate a larger VBI array,
         copy the current vectors to the new array  (clearing  any
         new, unused entries), and update 'vblqueue' and 'nvbls'.
         Deferred VBI handlers should return with  RTS,  _�n_�o_�t  RTE.
         They may use any registers except the user stack-pointer.
         Applications are responsible for cleaning up  vbl-vectors
         they have installed prior to process termination.
      System Startup        August 26, 1985                     49
                         ROM System Initialization
         [1]  Initial PC set from  location  $FC0000,  initial  SP
              (trash, really) set from location $FC0004.
              Catch system RESET.  Raise processor IPL to 7,  exe-
              cute RESET instruction to reset hardware registers.
              If a diagnostic cartridge is inserted, load a return
              address into A6 and jump to the cartridge.
         [2]  If memory was setup (i.e. this is a  warmstart)  the
              initialize the memory controller.
         [3]  If the RESET-bailout vector is valid, load a  return
              address into A6 and jump to the reset handler.
         [4]  Initialize the PSG (deselect  floppies),  setup  the
              scan  rate (50 or 60hz), write default values to the
              color palettes,  and  set  the  display  pointer  to
          If memory was sized on a previous reset, go to step 8.
         [5]  Size both banks of memory.
         [6]  [This used to perform a memory test.]
         [7]  Once memory has been sized and  zeroed,  record  the
              fact by setting two magic longwords in low memory.
         [8]  Clear the low 64K  of  memory,  from  'endosbss'  to
              0xffff.   Initialize  all  kinds  of  OS  variables.
              Setup interrupt vectors.  Call the serial BIOS' ini-
              tialization entry-point.
         [9]  Execute %%2 cartridge applications.
         Initialize the screen resolution.
         [11] Execute %%0 cartridge applications.
         [12] Enable interrupts (all but HBLANK) by  bringing  the
              IPL to 3.
         [13] Execute %%1 cartridge applications.
         [14] Call GEMDOS' initialization routine.
         [15] Attempt to boot from  floppy  disk,  if  the  system
              variable  'bootdev' is less than 2.  If there are no
              floppies, no attempt is made to boot from floppy.
              Attempt to load a boot sector from the DMA bus.  For
              each  of the eight DMA bus devices, a read operation
              is attempted on logical sector 0.  If  the  read  is
              successful,  and the sector checksums to $1234, then
              the sector is executed.  [See the section  "DMA  Bus
              ALL devices are checked.  The boot sector  code  may
              return,  in which case the BIOS will attempt to load
              boot sectors from the rest of the devices.
         [16] Turn on the cursor.  Do autoexec.  Attempt  to  exec
         [17] Do autoexec.  Kludge up an enviroment string.   Exec
              the AES (in ROM).
         If [16] or [17] ever  complete,  restart  the  system  by
              going back to [1].
                 |       Diagnostic      | (1)
                 |    Cartridge check    |
                 |    Memory Controller  | (2)
                 |      (fast init)      |
                 |    RESET bailout      | (3)
                 |       vector          |
                 |    init PSG           | (4)
                 |    init 50hz/60hz     |
                 |    init palettes      |
                 |    display at $10000  |
                  ~                     ~
            YES  ~   Has memory been     ~
              /-<    sized?  [is this     ~
              |  ~   a warmstart?]       ~
              |   ~                     ~
              |    ~~~~~~~~~~~~~~~~~~~~~
              |             |
              |          NO |
              |             |
              |             V
              |  +-----------------------+
              |  |    size memory        |
              |  |    and clear it       |
              |  +-----------------------+
              |             |
              |             V
              |  +-----------------------+
              |  |   indicate successful | (7)
              |  |       warmstart       |
              |  +-----------------------+
              |             |
              |             |
                 |    Clear bottom 64K   | (8)
                 |    Init variables     |
                 |    Init interrupts    |
                 |    Init serial BIOS   |
                 | Execute %%2 cartridge | (9)
                 |      applications     |
                 |    Init screen        | (10)
                 |     resolution        |
                 | Execute %%0 cartridge | (11)
                 |      applications     |
                 |   Bring IPL to 3      | (12)
                 |                       |
                 | Execute %%1 cartridge | (13)
                 |      applications     |
                 |   Initialize GEMDOS   | (14)
                 |                       |
                 +-----------------------+ (15)
                 |   Attempt to boot     |>------\
                 |    from floppy        |<--\   | execute
                 +-----------------------+   |   | boot
                            |                |   | sector
                            |                \---/
                 +-----------------------+ (15a)
                 |   Poll devices on     |>------\
                 |   DMA bus, requesting |       |
                 |     boot sectors      |<--\   | execute
                 +-----------------------+   |   | boot
                            |                |   | sector
                            V                \---/
                  ~                     ~
            YES  ~                       ~
              /-<    _cmdload == 0 ?      ~
              |  ~                       ~
              |   ~                     ~
              |    ~~~~~~~~~~~~~~~~~~~~~
              |             |
              |          NO |
              |             V
              |  +-----------------------+
              |  |   Turn on cursor      | (16)
              |  |   Exec \AUTO\*.PRG    |
              |  |   Exec COMMAND.PRG    |
              |  +-----------------------+
              |             |
              |             \--------------------\
              |                                  |
              \-------------\                    |
                            |                    |
                            V                    |
                 +-----------------------+       |
                 |   Exec \AUTO\*.PRG    | (17)  |
                 |   Kludge up enviro.   |       |
                 |       string          |       |
                 |   Exec AES (in ROM)   |       |
                 +-----------------------+       |
                            |                    |
                      Reset system,
                    start over again
      Boot Sectors          August 26, 1985                     54
         The boot sector contains
             o  A volume serial number
             o  A BIOS parameter block
             o  Optional boot code and boot parameters
         An executable boot sector must word-checksum to the magic
         number $1234.  During system initialization the boot sec-
         tor from a disk drive is loaded into a  buffer.   If  the
         checksum  is  correct,  the system JSRs the first byte of
         the  buffer.   [Since  the  location  of  the  buffer  is
         indeterminant, any code contained in the boot sector must
         be position-independent.] See the section on system  ini-
         tialization  for  further  details  on  writing  bootable
         When a "Get BPB" call is made, the BIOS  reads  the  boot
         sector  and  examines  the prototype BIOS parameter block
         (BPB).  A BPB is constructed from the prototype.  If  the
         prototype looks strange (for instance, if critical fields
         in it are zero) the BIOS returns NULL (as an error  indi-
         A BPB is normally computed and written when the volume is
         The 24-bit serial number is used to determine if the user
         has  changed disks.  (see the [still nonexistant] section
         on "Disk Changes").  The serial number  is  computed  and
         written by the FORMAT utility, and is (hopefully) unique.
                         |       BRA.S           | $0  branch to boot code
                         |       (wherever)      |
                         |       filler          | $2  reserved for OEMs
                         |                       |
                         |       (OEM            |
                         |        cruft)         |
                         |                       |
                         |                       |
                         |       SERIAL          | $8  volume serial number
                         |       24-bit volume   |     written by FORMAT
                         |       serial number   |
                         |l      BPS             | $b  #bytes/sector
                         |h                      |
                         |       SPC             | $d  #sectors/cluster
                         |l      RES             | $e  #reserved sectors
                         |h                      |
                         |       NFATS           | $10 #FATs
                         |l      NDIRS           | $11 #directory entries
                         |h                      |
                         |l      NSECTS          | $13 #sectors on media
                         |h                      |
                         |       MEDIA           | $15 media descriptor
                         |l      SPF             | $16 #sectors/FAT
                         |h                      |
                         |l      SPT             | $18 #sectors/track
                         |h                      |
                         |l      NSIDES          | $1a #sides on media
                         |h                      |
                         |l      NHID            | $1c #hidden sectors
                         |h                      |
                         |       boot code       | $1e
                         .       (if any)        .
                         |                       |
         The prototype BPB is software compatible with  an  MS-DOS
         version  2.x  BPB.   (This  does not mean the ST can read
         sectors written by, or write sectors readable by, a  disk
         controller other than the WDC 1770/1772).
         The low byte of a 16-bit field in the BPB (such as 'BPS')
         occupies the lower address [as on the 8086.]
         BPS is the number of bytes per sector  (for  floppies  on
         the ST, it will be 512).
         SPC is the number of sectors per  cluster  (on  floppies,
         usually 2 for a cluster size of 1K).
         RES is the number of reserved sectors at the beginning of
         the  media,  including the boot sector.  RES is usually 1
         on floppies.
         NFATS is the number of  File  Allocation  Tables  on  the
         NDIRS is the number of directory entries.
         NSECTS is the  total  number  of  sectors  on  the  media
         (including the reserved sectors).
         MEDIA is a media descriptor byte.  The ST BIOS  does  not
         use this byte, but other file-systems might.
         SPF is the number of sectors in each FAT.
         SPT is the number of sectors per track.
         NSIDES is the number of sides  on  the  media.   (Single-
         sided  media  can be read on double-sided drives, but not
         NHID is the number of "hidden"  sectors.   (The  ST  BIOS
         currently ignores this value for floppies).
         The last word in the boot  sector  (at  offset  $1FE)  is
         reserved for "evening out" checksums.  In particular, the
         "_protobpb" extended BIOS function modifies this word.
                         Formatting a Floppy Disk
         [1] Use the 'flopfmt()' (#10.) extended BIOS call to for-
             mat  all tracks on the floppy disk.  If tracks 0 or 1
             have any bad sectors then the media is unusable.
             The ST standard format is
                 1 or 2 sides;
                 80 tracks;
                 9 sectors per track;
                 no interleave (sequential sectors).
             Zero the first two tracks (this will zero the FAT and
             directory sectors).
         [2] Use the 'protobt()'  (#18.)  extended  BIOS  call  to
             create  a  boot  sector.   The  'disktype'  parameter
             should be 2 or 3 for 1  or  2  sided  80-track  media
             respectively.   The  'serialno' parameter should be a
             random number (or $1000000).
             The 'execflag' parameter should be  zero  unless  the
             prototyping  buffer  contains code (such as a copy of
             the Loader) that you want executed when the  disk  is
         [3] Write the boot sector, (prototyped in the  buffer  in
             step  [2])  to  track  0, side 0, sector 1 of the new
             disk.  Do NOT use the 'rwabs' call; use the  extended
             BIOS function 'flopwr'.
         It is possible to create disks in wierd formats by  vary-
         ing  the  number  of  sectors per track, formatting a few
         extra tracks, or specifying strange interleave factors.
         The 1772 "write track" codes used to format a track are:
             COUNT   BYTE    what
             -----   ----    ----------------
             60      $4e     (start of track)
             For each sector:
              12      $00
              3       $f5    (writes $a1)
              1       $fe    (ID address mark)
              1       track# (0..$4f)
              1       side#  (0..1)
              1       sector# (1..9)
              1       $02    (512 bytes/sector)
              1       $f7    (2 CRCs written)
              22      $4e
              12      $00
              3       $f5    (writes $a1)
              1       $fb    (data address mark)
              512     xx     (virgin data)
              1       $f7    (2 CRCs written)
              40      $4e
             End of track:
             1401    $4e     (filler at end of track)
                             DMA Bus Boot Code
         This code, extracted from the ST's BIOS, attempts to load
         boot  sectors  from devices on the DMA bus.  The code can
         be used:
             o As an example of how to use the DMA bus (useful
               for boot-sector and device-driver writers);
             o To provide information about  the  timeout  and
               command  characteristics expected from bootable
               DMA bus devices;
         gpip            equ     $fffffa01       ; (B) 68901 input register
     diskctl         equ     $ffff8604       ; (W) disk controller data access
         fifo            equ     $ffff8606       ; (W) DMA mode control
         dmahigh         equ     $ffff8609       ; (B) DMA base high
         dmamid          equ     $ffff860b       ; (B) DMA base medium
         dmalow          equ     $ffff860d       ; (B) DMA base low
         flock           equ     $43e            ; (W) DMA chip lock variable
         _dskbufp        equ     $4c6            ; (L) -> 1K disk buffer
         _hz_200         equ     $4ba            ; (L) 200hz counter
   *  dmaboot - attempt to boot from a device on the DMA bus
   *    Passed:    nothing
   *    Returns:   maybe-never (although it depends ...)
   *    Uses:      everything
   *    Discussion:
   *               Attempts to read boot sectors from eight devices connected
   *               to the DMA bus.  If a sector is read, and it is executable
   *               (word checksum is $1234), then it is executed.
   *               This code should take about 0.5 sec to execute if nothing
   *               is connected to the DMA bus.  Of course, if something IS
   *               hooked up, it should provide us with a boot sector, right?
                 moveq   #0,d7           ; start with dev #0
         dmb_1:  bsr     dmaread         ; attempt to read boot sector
                 bne     dmb_2           ; (failed -- try next dev)
                 move.l  _dskbufp,a0     ; a0 -> disk buffer
                 move.w  #$00ff,d1       ; checksum $100 words
                 moveq   #0,d0           ; checksum = 0
         dmb_3:  add.w   (a0)+,d0        ; add (next) word
                 dbra    d1,dmb_3
                 cmp.w   #bootmagic,d0   ; is the sector executable?
                 bne     dmb_2           ; (nope)
                 move.l  _dskbufp,a0     ; a0 -> disk buffer
                 jsr     (a0)
         dmb_2:  add.b   #$20,d7         ; next devno
                 bne     dmb_1           ; (do all eight devs)
         *  dmaread - attempt to read boot sector from DMA bus device
         *    Passed:    d7.b = ddd00000
         *               ('ddd' is the ACSI device number, 0..7)
         *    Returns:   NE: read failed;
         *               EQ: successful read,
         *                   sector data in (*_dskbufp)[];
         *    Preserves: d7.w
         *    Uses:      everything else
                 lea     fifo,a6         ; a6 -> DMA control register
                 lea     diskctl,a5      ; a5 -> DMA data register
                 st      flock           ; lock up DMA against vblank
                 move.l  _dskbufp,-(sp)  ; setup DMA pointer
                 move.b  3(sp),dmalow
                 move.b  2(sp),dmamid
                 move.b  1(sp),dmahigh
                 addq    #4,sp
                 move.w  #$098,(a6)      ; toggle R/W, leave in Read state
                 move.w  #$198,(a6)
                 move.w  #$098,(a6)
                 move.w  #1,(a5)         ; write sector count register (= 1)
                 move.w  #$088,(a6)      ; select dma bus (not SCR)
                 move.b  d7,d0           ; setup d0.L with devno+command
         or.b    #$08,d0         ; d0.b = devno<<5 .OR. "READ" command bits
                 swap    d0
                 move.w  #$088,d0
           bsr     wcbyte          ; d0.L = xxxxxxxxDDD01000xxxxxxx010001010
           bne     dmr_q           ; (punt on timeout)
           moveq   #3,d6           ; (count = 4)
           move.l  #$0000008a,d0   ; d0.L = generic command ($0000)
   dmr_lp: bsr     wcbyte          ; write bytes 2, 3, 4 and 5
           bne     dmr_q           ; (punt on timeout)
           dbra    d6,dmr_lp       ; (loop for more bytes)
           move.l  #$0000000a,(a5) ; write byte 6 (final byte)
           move.w  #400,d1         ; timeout = 2.0 sec
           bsr     wwait           ; wait for completion
           bne     dmr_q           ; (punt on timeout)
           move.w  #$08a,(a6)      ; select status reg
           move.w  (a5),d0         ; get return code from DMA device
           and.w   #$00ff,d0       ; strip crufty bits
           beq     dmr_r           ; (return if OK)
   *--- reset DMA, return NE
           moveq   #-1,d0          ; return -1 (error)
   dmr_r:  move.w  #$080,(a6)      ; cleanup DMA chip for floppy driver
           tst.b   d0              ; (test for NE on return)
           sf      flock           ; unlock DMA chip
           rts                     ; return
   *  wcbyte - write ACSI command byte, wait for IRQ
   *    Passed:    D0.L = command byte and FIFO control
   *                       bits 16..23 = command byte,
   *                       bits 0..7 = FIFO control bits
   *               a5 -> $ff8604
   *    Returns:   NE on failure (timeout)
   *               EQ on successful ACK
   *    Uses:      d1
           move.l  d0,(a5)         ; write WDC, WDL [due to jwt]
           moveq   #10,d1          ; wait 1/20th second
   wwait:  add.l   _hz_200,d1      ; d1 = time to quit at...
   ww_1:   btst.b  #5,gpip         ; disk done?
           beq     ww_w            ; (yes, return)
           cmp.l   _hz_200,d1      ; timeout?
           bne     ww_1            ; (not yet -- wait some more...)
           moveq   #-1,d1          ; ensure NE (timeout error) return
   ww_w:   rts
                          Hard Disk Partitioning
         The first sector (logical sector #0) on a hard disk  con-
         tains partition information.
                     |       hd_siz          | $1c2
                     |                       |
                     |       p0_flg          | $1c6
                     |       p0_id           | $1c7
                     |       p0_st           | $1ca
                     |                       |
                     |       p0_siz          | $1ce
                     |                       |
                     |       p1_flg          | $1d2
                     |       p1_id           | $1d3
                     |       p1_st           | $1d6
                     |                       |
                     |       p1_siz          | $1da
                     |                       |
                     |       p2_flg          | $1de
                     |       p2_id           | $1df
                     |       p2_st           | $1e2
                     |                       |
                     |       p2_siz          | $1e6
                     |                       |
                     |       p3_flg          | $1ea
                     |       p3_id           | $1eb
                     |       p3_st           | $1ee
                     |                       |
                     |       p3_siz          | $1f2
                     |                       |
                     |       bsl_st          | $1f6
                     |                       |
                     |       bsl_cnt         | $1fa
                     |                       |
                     |       (reserved)      | $200
         'hd_siz' is the total size of the disk, in  logical  sec-
         'bsl_st' specifies the starting sector# of the bad sector
         list.   [Typically the bad sector list will be located at
         the end of the device.]
         'bsl_cnt' specifies the /number/ of  bad  sectors.   Each
         bad  sector  is  specified  by  a longword containing the
         sector's number.  The total number of sectors used up  by
         the  bad  sector  list  is  therefore  'bsl_siz' / 4.  If
         'bsl_cnt' is zero, there are no bad sectors.
         A disk may contain up to four partitions.  The first sec-
         tor  in  a  partition is a boot sector (which, on the ST,
         will contain a BPB).
                     |       root boot       |
                     |       partition 0     |
                     |                       |
                     |       partition 1     |
                     |       (optional)      |
                     |       partition 2     |
                     |       (optional)      |
                     |       partition 3     |
                     |       (optional)      |
                     |       optional        |
                     |       bad sector      |
                     |       list            |
         Each partition is described by a 12-byte structure:
                     |       p*_flg          | (+0)
                     |       p*_id           | (+1)
                     |                       |
                     |                       |
                     |       p*_st           | (+4)
                     |                       |
                     |                       |
                     |                       |
                     |       p*_siz          | (+8)
                     |                       |
                     |                       |
                     |                       |
         'p*_flg' should be nonzero to indicate that the partition
         exists.   The BIOS will boot the first partition that has
         bit 7 set in this byte.
         'p*_id' is a three-byte field that identifies the  parti-
         tion.  For GEMDOS partitions, the field contain the three
         ascii characters "GEM".
         'p*_st' specifies the logical sector number of the begin-
         ning of the partition.
         'p*_siz' specifies the size of the partition, in  logical
      Boot Loader           August 26, 1985                     65
         The Loader is a generic system-loader.  It lives on  boot
         sectors, and is brought into RAM and executed during sys-
         tem initialization.  The Loader  has  the  capability  to
         load  an "image" file or a set of contiguous sectors from
         The six reserved bytes starting at offset 2 in  the  boot
         sector must be:
         for some tools to be able to manipulate Loader boot  sec-
         An image file contains no header or  relocation  informa-
         tion.   It  is  an  exact image of the program to be exe-
         cuted.  The loader is capable of loading  any  file  from
         disk,  regardless of where it appears in the directory or
         whether the file is contiguous or not.
         Loader information immediately follows  the  BPB  in  the
         boot sector:
                     |       EXECFLG         | $1e
                     |                       | _cmdload
                     |       LDMODE          | $20
                     |                       | load mode
                     |       SSECT           | $22
                     |                       | sector start
                     |       SECTCNT         | $24
                     |                       | #sectors
                     |       LDADDR          | $26
                     |                       | load-address
                     |                       |
                     |                       |
                     |       FATBUF          | $2a
                     |                       | FAT address
                     |                       |
                     |                       |
                     |       FNAME   n       | $2e
                     |               n       |
                     |               n       |
                     |               n       |
                     |               n       |
                     |               n       |
                     |               n       |
                     |               n       |
                     |               e       |
                     |               e       |
                     |               e       |
                     |       (reserved)      | $39
                     |       BOOTIT          | $3a
                     |       code            |
                     .                       .
         EXECFLG is a word that is copied to '_cmdload'.
         LDMODE governs the loading mode.  If LDMODE  is  zero,  a
         file  is  searched for and loaded.  If LDMODE is nonzero,
         then 'SECTCNT'  sectors,  starting  with  logical  sector
         number 'SSECT', are loaded from the disk.
         SSECT is the logical sector number to start loading  from
         (valid iff LDMODE is nonzero).
         SECTCNT is the number  of  sectors  to  load  (valid  iff
         LDMODE is nonzero).
         LDADDR is the load-address of the file (or the sectors).
         FATBUF points to a place to put  the  FAT  and  directory
         FNAME is a filename to load (valid iff LDMODE  is  zero).
         It consists of eight character name and a three character
         [See also: documentation on the BOOTGEN utility.]
                               Boot Sequence
            [1] The boot sector is loaded.  The Loader takes  con-
                trol of the system.
            [2] The boot device's directory and 2nd FAT buffer are
                read into memory, starting at _membot.  The Loader
                searches for a file (usually) called TOS.IMG.   If
                it  is not found, it returns with an error code in
            [3] TOS.IMG is read into memory, starting at $40000.
            [4] Control is passed to the first byte of TOS.IMG.
         TOS.IMG consists of three parts:
            [1] A relocator (RELOCRL) that moves TOS.IMG to  where
                it  expects  to  be  executed  in memory.  RELOCRL
                takes control of the  system,  fades  the  screen,
                performs  a fast block-copy, and passes control to
                the first byte in the operating system.
            [2] An image of the operating system ('prox 90K).
            [3] An image of the desktop and GEM ('prox 110K).
         System initialization  proceeds  as  normal  (except  for
         clearing memory) once the OS has control.
                                 Boot ROM
         The ST boot ROM (AKA "Das Boot") contains a subset of the
         BIOS.   The  only  functions  available relate to reading
         floppy disks.
         System initialization is identical to the normal OS  pro-
         cedure.  However, the locations and intepretations of the
         system variables may have changed.  See the end  of  this
         section for a list of "safe" system variables.
         The normal course of events is:
             The boot ROM catches RESET  and  initializes  the
             system.    It   puts  up  some  pretty  graphics.
             Kids'll love it.
             An attempt is made to boot  from  both  floppies.
             '_bootdev'  will  contain  the device number on a
             successful boot sector load.  [Someday there  may
             be  a  version  of  the boot ROM that understands
             about hard disks.]
             The boot sector is executed.  [See-also: Loader]
         Das Boot's version number (the second word in the ROM, at
         $FC0002) is $0000.
         BIOS functions on trap 13:
              func   Name [see: GEMDOS spec]
              ----   --------
                0:   [unused]
                1:   [unused]
                2:   [unused]
                3:   [unused]
                4:   rwabs (read only)
                5:   [unused]
                6:   [unused]
                7:   getbpb
         Extended functions on trap 14:
              func   Name [see: Extended BIOS Functions]
              ----   --------
                0:   [unused]
                1:   ssbrk
                2:   [unused]
                3:   [unused]
                4:   [unused]
                5:   [unused]
                6:   [unused]
                7:   [unused]
                8:   _floprd (read sectors)
         DAS BOOT uses memory from $10000  to  $20000  for  screen
         buffers.  Avoid loading stuff into this region (until you
         take over  the  system)  when  writing  directly-bootable
         Between the time when DAS BOOT was released and the  time
         the  first  RAM-loaded  systems  were  shipped  (will  be
         shipped?) the variables in low memory were added  to  and
         <<<give list of "safe" variables here>>>
                                GEMDOS CALL
                         (QUICKER) REFERENCE GUIDE
         Functions are  available  through  trap  #1.   The  first
         number  is  the trap number (first word on the stack when
         the trap is made).  The  function's  name  (as  given  in
         OSBIND.H)  is  next, along with the named arguments.  The
         number in brackets is the number of bytes  that  must  be
         cleaned  up  off  the  stack  after the call is made (for
         those of us doing traps  from  assembly).   The  argument
         declarations  (if  any)  follow  the  first line.  Then a
         short description of the function is given.
         In general, GEMDOS calls return LONGs  in  D0.   However,
         there  /are/ exceptions.  When testing for error returns,
         it is best to examine D0.W only.  In addition, GEMDOS may
         occasionally  return BIOS error numbers (that is, between
         -1 and -31).
         $00 Pterm0() [2]
                   Terminate process (with return code of $0).
         $01 Cconin() [2]
                   Return cooked character from stdin.
         $02 Cconout(chr) [4]
             char chr;
                   Write character to stdout.
         $03 Cauxin() [2]
                   Return character from AUX:.
         $04 Cauxout(chr) [4]
             char chr;
                   Write character to AUX:.
         $05 Cprnout(chr) [4]
             char chr;
                   Write character to PRN:.
         $06 Crawio(wrd) [4]
             WORD wrd;
                   If (wrd == 0x00ff) return char from stdin
                   If (wrd != 0x00ff) print it on stdout;
         $07 Crawcin() [2]
                   Return raw character from stdin (without echo).
         $08 Cnecin() [2]
                   Read char from  stdin  without  echo.   Control
                   characters  (^S,  ^Q,  ^C)  are interpreted and
                   have effect.
         $09 Cconws(str) [6]
             char *str;
                   Write null-terminated string to stdout.
         $0a Cconrs(buf) [6]
             char *buf;
                   Read  edited  string  from  stdin.   On  entry,
                   buf[0] contains size of data part of buf[].  On
                   exit, buf[1] contains number of  characters  in
                   data  part  of  buf[].   The data part of buf[]
                   starts at buf[2].
         $0b Cconis() [2]
                   Return -1 [nonzero] if character  is  available
                   on stdin, 0 otherwise.
         $0e Dsetdrv(drv) [4]
             WORD drv;
                   Select  current  drive  (0=A:,   1=B:,   etc.).
                   Returns a bitmap of drives in the system (bit 0
                   = A, ....)
         $10 Cconos() [2]
                   Returns -1 [nonzero] if  console  is  ready  to
                   receive a character, 0 if it is "unavailable."
         $11 Cprnos() [2]
                   Returns  -1  [nonzero]  if  PRN:  is  ready  to
                   receive a character, 0 if it is "unavailable."
         $12 Cauxis() [2]
                   Returns -1 [nonzero] if char  is  available  on
                   AUX:, 0 otherwise.
         $13 Cauxos() [2]
                   Returns  -1  [nonzero]  if  AUX:  is  ready  to
                   receive a character, 0 if it is "unavailable."
         $19 Dgetdrv() [2]
                   Returns number of current drive (0=A:, etc.)
         $1a Fsetdta(ptr) [6]
             LONG ptr;
                   Set disk transfer address (used by Fsfirst()).
         $20 Super(stack) [6]
             LONG stack;
                   Hack processor privelege mode.  If  'stack'  is
                   -1L,  return  0  or  1 (processor is in user or
                   supervisor mode).  If in user mode,  switch  to
                   supervisor mode and use 'stack' as the supervi-
                   sor stack (or the value from USP if 'stack'  is
                   NULL).   If  in supervisor mode, switch to user
                   mode and use 'stack' as the  supervisor  stack.
                   Return the old supervisor stack value.
         $2a Tgetdate() [2]
                   Returns date:
                       0..4    day 1..31
                       5..8    month 1..12
                       9..15   year 0..119 since 1980
         $2b Tsetdate(date) [4]
             WORD date;
                   Set date in the format described above.
         $2c Tgettime() [2]
                   Return time in the format:
                       0..4    second 0..59 (2-second resolution)
                       5..10   minute 0..59
                       11..15  hour 0..23
         $2d Tsettime(time) [4]
             WORD time;
                   Set time in the format described above.
         $2f Fgetdta() [2]
                   Return current DTA.
         $30 Sversion() [2]
                   Return current version number.
         $31 Ptermres(keep, ret) [8]
             LONG keep;
             WORD ret;
                   Terminate and stay resident.  'keep' has number
                   of  bytes  to  keep  in the process descriptor.
                   'ret' is the process' return code.
         $36 Dfree(buf, drv) []
             LONG buf;
             WORD drv;
                   Return information about  allocation  on  drive
                   'drv'  (0=current,  1=A:,  2=B:,  etc.).  'buf'
                   points to  a  structure  where  stuff  will  be
                       LONG b_free;    #free clusters on drive
                       LONG b_total;   total #clusters on drive
                       LONG b_secsiz;  #bytes in a sector
                       LONG b_clsiz;   #sectors in a cluster
         $39 Dcreate(path) [6]
             char *path;
                   Create a directory.
         $3a Ddelete(path) [6]
             char *path;
                   Delete a directory.
         $3b Dsetpath(path) [6]
             char *path;
                   Set current directory.
         $3c Fcreate(name, attr) [8]
             char *name;
             WORD attr;
                   Create a file with the given pathname.  Returns
                   a  handle  or a (negative) error#.  Bits in the
                   attribute word are:
                       $01     set to readOnly
                       $02     hidden from directory search
                       $04     system file, hidden from dir search
                       $08     volume label (first 11 bytes of name)
         $3d Fopen(name, mode) [8]
             char *name;;
             WORD mode;
                   Open a file.  Mode is  0,  1  or  2  for  read,
                   write,  and  read/write.  Returns a handle or a
                   (negative) error#.
         $3e Fclose(handle) [4]
             WORD handle;
                   Close the handle.
         $3f Fread(handle, count, buf) [12]
             WORD handle;
             LONG count;
             char *buf;
                   Read bytes from a file.  Return count read,  or
                   a negative error#.
         $40 Fwrite(handle, count, buf) [12]
             WORD handle;
             LONG count;
             char *buf;
                   Write bytes to a file.  Return  count  written,
                   or a negative error#.
         $41 Fdelete(name) [6]
             char *name;
                   Delete the file.
         $42 Fseek(offset, handle, mode) [10]
             LONG offset;
             WORD handle;
             WORD mode;
                   Seek within the file (handle).  'offset' is the
                   (signed)  number  of bytes to seek by.  Mode is
                   one of:
                       0       from beginning of file
                       1       from current position
                       2       from end of file
         $43 Fattrib(path, mode, mode) [10]
                   Get file attributes if 'mode' is 0, set them if
                   'mode' is 1.  Bits are:
                       $01     readOnly
                       $02     hidden
                       $04     system (hidden hidden)
                       $08     volume label
                       $10     subdirectory
                       $20     written to and closed
         $45 Fdup(stdhandle) [4]
             WORD stdhandle;
                   Returns non-standard handle that refers to  the
                   same file.
         $46 Fforce(stdhandle, nonstdhandle) [6]
             WORD stdhandle;
             WORD nonstdhandle;
                   Force standard handle to point to same file  or
                   dev as the nonstandard handle.
         $47 Dgetpath(pathbuf, drv) [8]
             char *pathbuf;
             WORD drv;
                   Return  current  directory  for   drive   'drv'
                   (0=default,  1=A:, etc.) in the buffer.  Buffer
                   must be at least 64 bytes long.
         $48 Malloc(amount) [6]
             LONG amount;
                   'amount' contains # bytes to allocate  (or  -1,
                   which   returns   maximum   available  memory).
                   Return pointer to block (on word  boundary)  of
                   'amount' bytes, or zero on allocation failure.
         $49 Mfree(addr) [6]
             char *addr;
                   Free a block  of  memory.   Nonzero  return  on
         $4a Mshrink(zero, mem, size) [12]
             WORD zero;
             LONG mem;
             LONG size;
                   'zero' must be a word containing 0.  'mem' con-
                   tains beginning of memory block.  'size' is the
                   the amount of memory to RETAIN  in  the  block.
                   Nonzero return on failure.
         $4b Pexec(mode, path, commandline, enviroment) [16]
             WORD mode;
             char *path;
             char *commandline;
             char *enviroment;
                   'mode' is one of:
                       0       load and go
                       3       just load
                       4       create basepage
                       5       just go
                   'commandline' is the  command  tail,  which  is
                   copied  into the basepage.  'enviroment' is the
                   enviroment string; if NULL, the parent process'
                   enviroment string is inheirited.
                   For mode 0, the  return  code  is  the  child's
                   return  code, or a negative (OS) error.  If the
                   load or create-basepage fails, a negative error
                   number is returned.
         $4c Pterm(code) [4]
             WORD code;
                   Terminate current process, returning 'code'  to
                   the parent.
         $4e Fsfirst(spec, attr) [8]
             char *spec;
             WORD attr;
                   'attr' is a set of  attributes  to  match  (see
                   function  #43 for details).  'spec' may contain
                   wildcard characters in the filename, but not in
                   the  pathname.   Returns  0 if a file is found,
                   EFILNF if no file was found.  Dumps stuff  into
                   the DTA:
                       0..20   junk
                       21      file attributes
                       22-23   file time stamp
                       24-25   file date stamp
                       26-29   file size (longword)
                       30-43   name+extension of found file
         $4f Fsnext() [2]
                   Continue with with Fsfirst().
         $56 Frename(zero, old, new) [12]
             WORD zero;
             char *old;
             char *new;
                   Change the name of a file from 'old' to  'new'.
                   'zero' is reserved, and must be 0.
         $57 Fdatime(handle, buf, set) [10]
             WORD handle;
             char *buf;
             WORD set;
                   'buf' points to buffer containing file date and
                   time  information.  'handle' is a handle to the
                   file.  If 'set' is zero, get the time and date.
                   If 'set' is 1, set the file time and date.    

Back to Programming