  cbm4linux 0.3.0 Users Guide
  Michael Klein, nip@c64.org
  2002/04/05

  This document describes the cbm4linux package, a linux kernel module
  and a few user space support programs to control and use serial
  devices as used by most Commodore (CBM) 8-bit machines.
  ______________________________________________________________________

  Table of Contents


  1. Overview

  2. Utilities

     2.1 cbmctrl
        2.1.1 Actions
        2.1.2 cbmctrl Examples
     2.2 cbmformat
        2.2.1 cbmformat invocation
        2.2.2 cbmformat Examples
     2.3 d64copy
        2.3.1 d64copy invocation
     2.4 cbmcopy
        2.4.1 cbmcopy invocation

  3. cbm4linux API

     3.1 Preprocessor macros
     3.2 Enumeration types
     3.3 Functions
        3.3.1 Basic I/O
        3.3.2 Low-level port access
        3.3.3 Helper functions
        3.3.4 libd64copy
        3.3.5 libcbmcopy


  ______________________________________________________________________

  11..  OOvveerrvviieeww

  The popular Commodore 8-bit home-computers like the C-64 and the
  VIC-20 are using a custom serial bus to talk to attached devices (disk
  drive, printer).  The cbm4linux kernel module provides an interface to
  this bus at TALK/LISTEN level, similar to the one provided by the
  Commodore kernel routines, but low level bus control is available as
  well. The serial devices are connected to the PC's parallel port via a
  XM1541 or XA1541 and, optionally, a XP1541 or XP1571 add-on.


  22..  UUttiilliittiieess

  cbm4linux comes with the following utilities:


  22..11..  ccbbmmccttrrll

  Synopsis: cbmctrl ACTION ...


  _c_b_m_c_t_r_l is used to send commands to external devices.



  22..11..11..  AAccttiioonnss

  Here's a list of all valid actions for _c_b_m_c_t_r_l:



     lliisstteenn _d_e_v_i_c_e _s_e_c_a_d_r
        Tell device _d_e_v_i_c_e to listen on secondary address _s_e_c_a_d_r. Until
        the next _u_n_l_i_s_t_e_n command, everything written to the special
        device _/_d_e_v_/_c_b_m will be received by this device.


        This command corresponds to the following 6502 assembly code on
        a C64:

        ________________________________________________________________
        lda #device
        jsr $ffb1
        lda #secadr
        ora #$60
        jsr $ff93
        ________________________________________________________________




     ttaallkk _d_e_v_i_c_e _s_e_c_a_d_r
        Tell device _d_e_v_i_c_e to talk on secondary address _s_e_c_a_d_r. Until
        the next _u_n_t_a_l_k command, data from this device can be received
        device by reading from the special device _/_d_e_v_/_c_b_m.


        This command corresponds to the following 6502 assembly code on
        a C64:

        ________________________________________________________________
        lda #device
        jsr $ffb4
        lda #secadr
        ora #$60
        jsr $ff96
        ________________________________________________________________




     uunnlliisstteenn
        Ends communication with listening devices after a _l_i_s_t_e_n
        command. This corresponds to the C64 kernel routine $ffae.


     uunnttaallkk
        Ends communication with talking devices after a _t_a_l_k command.
        This corresponds to the C64 kernel routine $ffab.


     ooppeenn _d_e_v_i_c_e _s_e_c_a_d_r _f_i_l_e_n_a_m_e
        Open file _f_i_l_e_n_a_m_e on device _d_e_v_i_c_e. After opening, data can be
        read/written by sending a _t_a_l_k resp. _l_i_s_t_e_n command with the
        secondary address _s_e_c_a_d_r.

        If _s_e_c_a_d_r is greater than 1, the file type and access mode must
        also be specified by appending ,type,mode to _f_i_l_e_n_a_m_e. Valid
        types are D, P, S, U, R (DEL, PRG, SEQ, USR, REL), valid modes
        are R for reading and W for writing.

     cclloossee _d_e_v_i_c_e _s_e_c_a_d_r
        Close the file associated with secondary address _s_e_c_a_d_r on
        device _d_e_v_i_c_e.


     ssttaattuuss _d_e_v_i_c_e
        Copies input from device _d_e_v_i_c_e, secondary address 15
        (command/status channel), to the standard output stream. Note
        that all upper case characters are changed to lower case.
        Carriage return (0x0d) is also changed to linefeed (0x0a).

        This command is similar to (in this case, no character
        conversions would be made)

        ________________________________________________________________
        cbmctrl talk device 15
        cat /dev/cbm
        cbmctrl untalk
        ________________________________________________________________




     ccoommmmaanndd _d_e_v_i_c_e _c_m_d_s_t_r
        Sends _c_m_d_s_t_r to device _d_e_v_i_c_e, secondary address 15
        (command/status channel). Since there is no PetSCII->ASCII
        conversion, commands must be sent in _u_p_p_e_r _c_a_s_e (kind of poor
        man's PetSCII conversion). This is because charset conversion
        would break the M-W and M-E commands.

        This command is identical to

        ________________________________________________________________
        cbmctrl listen device 15
        echo -n cmdstr > /dev/cbm
        cbmctrl unlisten
        ________________________________________________________________




     ddiirr _d_e_v_i_c_e
        Read directory from disk in device _d_e_v_i_c_e, print on standard
        out.


     ddoowwnnllooaadd _d_e_v_i_c_e _a_d_d_r_e_s_s _c_o_u_n_t
        Read _c_o_u_n_t bytes from drive memory, starting at _a_d_d_r_e_s_s via one
        or more M-R commands. Memory contents are written to standard
        out.


     uuppllooaadd _d_e_v_i_c_e _a_d_d_r_e_s_s _f_i_l_e
        Send _f_i_l_e to drive memory, starting at _a_d_d_r_e_s_s via one or more
        M-W commands. If _a_d_d_r_e_s_s is -1, the first to bytes from _f_i_l_e are
        considered as start address.


     rreesseett
        Triggers hardware reset on all attached devices. Control is
        returned after a five second delay to make sure all devices are
        ready.


     ddeetteecctt
        Identify connected devices (considers devices 8-15)
  22..11..22..  ccbbmmccttrrll EExxaammpplleess

  Send file contents to printer 4:

  ______________________________________________________________________
  cbmctrl listen 4 0
  cat file > /dev/cbm
  cbmctrl unlisten
  ______________________________________________________________________




  Copy file to disk drive 8:

  ______________________________________________________________________
  cbmctrl open 8 2 FILENAME,P,W
  cbmctrl listen 8 2
  cat file > /dev/cbm
  cbmctrl unlisten
  cbmctrl close 8 2
  ______________________________________________________________________




  Copy file from disk drive 8:

  ______________________________________________________________________
  cbmctrl open 8 2 FILENAME,P,R
  cbmctrl talk 8 2
  cat /dev/cbm > file
  cbmctrl untalk
  cbmctrl close 8 2
  ______________________________________________________________________




  Dump 1541 ROM:

  ______________________________________________________________________
  cbmctrl download 8 0xc000 0x4000 > 1541.rom
  ______________________________________________________________________




  22..22..  ccbbmmffoorrmmaatt

  Synopsis: cbmformat [OPTION]... DRIVE NAME,ID


  _c_b_m_f_o_r_m_a_t is a fast low-level disk formatter for the 1541 and
  compatible devices (1570, 1571, third-party clones). The drive routine
  was taken from the Star Commander ((C) Joe Forster/STA).


  22..22..11..  ccbbmmffoorrmmaatt iinnvvooccaattiioonn

  Here's a complete list of known options:


     --hh Display help and exit.


     --nn Do not bump drive head at the beginning. Don't use this on
        eventually misaligned drives.


     --xx Format 40 track disk. BAM format is SpeedDOS compatible.


     --oo Fill sectors with the original pattern (0x4b, 0x01, 0x01...)
        instead of zeroes.  The original pattern is probably due to a
        bug in the drive ROM, apart from this, zeroing out unused
        sectors should give (slightly) better results for compressed
        disk images.


     --ss Display drive status after formatting. Normally, _c_b_m_f_o_r_m_a_t exits
        after executing the drive code. With this option turned on,
        _c_b_m_f_o_r_m_a_t waits until the drive has finished formatting and
        prints the drive status after initializing the BAM on standard
        out.


     --pp Display a hash mark ('#') for each formatted track. Slows
        formatting down a bit.


  22..22..22..  ccbbmmffoorrmmaatt EExxaammpplleess

  Format standard disk (35 tracks) in drive 8, use (buggy) 1541 sector
  pattern, show drive status when done:

  ______________________________________________________________________
  cbmformat -os 8 GAMES,42
  ______________________________________________________________________




  SpeedDOS disk (40 tracks), show progress indicator, all sectors zeroed
  out, no head banging:

  ______________________________________________________________________
  cbmformat -npx 8 "40 TRACKS,OK"
  ______________________________________________________________________




  22..33..  dd6644ccooppyy

  Synopsis: d64copy [OPTION]... SOURCE TARGET


  _d_6_4_c_o_p_y is a fast disk image transfer (both read and write) program
  for the 1541 and compatible devices (1570, 1571, third-party clones).
  Maximum transfer speed is achieved by custom drive- and transfer-
  routines based on the Star Commander ((C) Joe Forster/STA) routines.


  22..33..11..  dd6644ccooppyy iinnvvooccaattiioonn

  Either SOURCE or TARGET must be an external drive, valid names are 8,
  9, 10 and 11.  The other parameter specifies the file name of the .d64
  image.

  Here's a complete list of known options:

     --hh Display help and exit


     --qq,, ----qquuiieett
        Quiet output, fewer messages (also suppresses warnings, should
        not be used)


     --vv,, ----vveerrbboossee
        Verbose output, more messages (can be repeated)


     --nn,, ----nnoo--pprrooggrreessss
        Omit progress display


     --ss,, ----ssttaarrtt--ttrraacckk==_s_t_a_r_t _t_r_a_c_k
        Set start track (defaults to 1)


     --ee,, ----eenndd--ttrraacckk==_e_n_d _t_r_a_c_k
        Set end track (default is 35 for .d64 images, 70 for .d71
        images). _d_6_4_c_o_p_y is able to access tracks 1-35 in original
        transfer mode and 1-42 with serial1, serial2 and parallel. The
        1571 supports tracks 1-70 in double sided (.d71) mode.


     --tt,, ----ttrraannssffeerr==_t_r_a_n_s_f_e_r _m_o_d_e
        Set transfermode. Valid modes are:

     +o  original (slowest)

     +o  serial1

     +o  serial2

     +o  parallel (fastest)

        original and serial1 should work in any case.  serial2 won't
        work with more than one device is connected to the IEC bus,
        parallel requires a XP1541/XP1571 cable


     --ii,, ----iinntteerrlleeaavvee==_i_n_t_e_r_l_e_a_v_e
        Set interleave value. This is ignored when reading in warp mode.
        Default is 16 for transfer mode original, for turbo and warp
        write as follows:



                    turbo (r/w)    warp (write only)
          serial1       3                 5
          serial2      12                11
          parallel      6                 3




     Lower values might slightly reduce transfer times, but if set a bit
     to low, transfer times will dramatically increase.


     --ww,, ----wwaarrpp
        Enable warp mode. this is not possible when _t_r_a_n_s_f_e_r _m_o_d_e is set
        to original. Warp mode is usually a good idea for transferring
        disk images unless you have a very slow CPU and/or bad disk
        material. Warp mode sends raw GCR data over the bus, which
        assures data integrity on the PC side and relieves the drive's
        CPU.


     --bb,, ----bbaamm--oonnllyy
        BAM-only copy. Only blocks marked as allocated are copied. For
        extended tracks (36-40), SpeedDOS BAM format is assumed. Use
        with caution, at least one wide-spread directory editor tends to
        forget to allocate some directory blocks.


     --BB,, ----bbaamm--ssaavvee
        Save BAM-only copy. this is like the -b option but always copies
        the entire directory track (18, 18 and 53 in double-sided mode).


     --dd,, ----ddrriivvee--ttyyppee==type
        Skip drive type detection. 0 or 1541 specifies 1541 mode (1 MHz,
        parallel cable at VIA $1800), 1 or 1571 forces 1571 mode (2 MHz,
        parallel cable at CIA $4000).


     --22,, ----ttwwoo--ssiiddeedd
        Double-sided mode for copying .d71 images to/from a 1571 drive.
        Warp mode is not supported (yet).


     --rr,, ----rreettrryy--ccoouunntt==count
        Number of retries.


     --EE,, ----eerrrroorr--mmooddee==mode
        Controls whether error is appended to the disk image (15x1->PC
        only).  Allowed values for mode are (abbreviations allowed):

     +o  always

     +o  on_error  (default)

     +o  never



  22..44..  ccbbmmccooppyy

  Synopsis: cbmcopy [OPTION]... DEVICE# FILE...


  _c_b_m_c_o_p_y is a fast file transfer program for various disk drives, in
  particular the 1541, 1570, 1571 and 1581 devices.  Maximum transfer
  speed is achieved by custom drive- and transfer-routines based on the
  Star Commander ((C) Joe Forster/STA) routines.


  22..44..11..  ccbbmmccooppyy iinnvvooccaattiioonn

  DEVICE# specifies the drive number for file copy.  The remaining
  arguments specify the files to be sent to/read from the disk drive.
  This version supports Raw, PC64 (P00) and T64 files are recognized
  when sending files to the disk drive, files read from external devices
  are always stored as raw binary data.

  Here's a complete list of known options:


     --hh Display help and exit


     --qq,, ----qquuiieett
        Quiet output, fewer messages (also suppresses warnings, should
        not be used)


     --vv,, ----vveerrbboossee
        Verbose output, more messages (can be repeated)


     --nn,, ----nnoo--pprrooggrreessss
        Omit progress display


     --rr,, ----rreeaadd
        Operate in read-mode, i.e. read data from an external device.
        Starting _c_b_m_c_o_p_y as _c_b_m_r_e_a_d has the same effect.


     --ww,, ----wwrriittee
        Operate in write-mode, i.e. send files to an external device.
        Starting _c_b_m_c_o_p_y as _c_b_m_w_r_i_t_e has the same effect.


     --tt,, ----ttrraannssffeerr==_t_r_a_n_s_f_e_r _m_o_d_e
        Set transfermode. Valid modes are:

     +o  serial1  (slowest)

     +o  serial2

     +o  parallel (fastest, not with 1581)

        serial1 should work in any case.  serial2 won't work with more
        than one device is connected to the IEC bus, parallel requires a
        XP1541/XP1571 cable


     --dd,, ----ddrriivvee--ttyyppee==type
        Skip drive type detection.  Valid types are 1541, 1570, 1571 and
        1581.


     --oo,, ----oouuttppuutt==name
        Specifies target name. ASCII/PetSCII conversion is performed
        when in write-mode.


     --aa,, ----aaddddrreessss==address
        Overrides the file's first two bytes with _a_d_d_r_e_s_s.


     --RR,, ----rraaww
        Skip file type detection. File data is sent as is.  This option
        is only valid in write-mode.


     --ff,, ----ffiillee--ttyyppee==type
        Specifies/overrides file type. Supported types are P, S, D, U.
        Raw files default to P, whereas the T64 format contains meta
        data which includes the file type. For PC64 files, _c_b_m_w_r_i_t_e
        tries to guess the file type from the file extension.  This
        option is only valid in write-mode.

  33..  ccbbmm44lliinnuuxx AAPPII

  All communication between the user space applications and the kernel
  module is done with ioctl's. Since ioctl's are quite unportable and
  hardly provide any type-safety, there are a number of wrapper-
  functions along with a couple of convenience functions implemented in
  libopencbm.a. The prototypes can be found in the header file
  opencbm.h.


  33..11..  PPrreepprroocceessssoorr mmaaccrrooss



  +o  #define IEC_DATA 0x01

  +o  #define IEC_CLOCK 0x02

  +o  #define IEC_ATN 0x04

  These defines are used by the _c_b_m___i_e_c___*_(_) functions. You will
  definitely need this if you intend to implement your own custom
  transfer routines. See the libd64copy/libcbmcopy source for more
  information.


  33..22..  EEnnuummeerraattiioonn ttyyppeess



  +o  enum cbm_device_type_e

  +o  cbm_dt_unknown

  +o  cbm_dt_1541

  +o  cbm_dt_1570

  +o  cbm_dt_1571

  +o  cbm_dt_1581


  33..33..  FFuunnccttiioonnss


  (All functions except cbm_driver_open(): _f must be a valid file
  descriptor)


  33..33..11..  BBaassiicc II//OO


     iinntt ccbbmm__ddrriivveerr__ooppeenn((CCBBMM__FFIILLEE **ff,, iinntt ppoorrtt));;
        Opens the driver. port isn't used by now and should be 0.  After
        successful completition, 0 is returned along with a valid
        CBM_FILE descriptor in f.


     vvooiidd ccbbmm__ddrriivveerr__cclloossee((CCBBMM__FFIILLEE ff));;
        Closes the driver.


     iinntt ccbbmm__rraaww__rreeaadd((CCBBMM__FFIILLEE ff,, vvooiidd **bbuuff,, ssiizzee__tt ssiizzee));;
        Retrive data after cbm_talk();. At most size bytes are read.
        Return value is the actual number of bytes read. < indicates an
        error.


     iinntt ccbbmm__rraaww__wwrriittee((CCBBMM__FFIILLEE ff,, ccoonnsstt vvooiidd **bbuuff,, ssiizzee__tt ssiizzee));;
        Send data after cbm_listen();. At most size bytes are written,
        Return value is the actual number of bytes written. < indicates
        an error.


     iinntt ccbbmm__lliisstteenn((CCBBMM__FFIILLEE ff,, ____uu__cchhaarr ddeevv,, ____uu__cchhaarr sseeccaaddrr));;
        Tell device _d_e_v to listen on secondary channel _s_e_c_a_d_r.  Return
        value is 0 on success, < 0 means error.


     iinntt ccbbmm__ttaallkk((CCBBMM__FFIILLEE ff,, ____uu__cchhaarr ddeevv,, ____uu__cchhaarr sseeccaaddrr));;
        Tell device _d_e_v to talk on secondary channel _s_e_c_a_d_r.  Return
        value is 0 on success, < 0 means error.


     iinntt ccbbmm__ooppeenn((CCBBMM__FFIILLEE ff,, ____uu__cchhaarr ddeevv,, ____uu__cchhaarr sseeccaaddrr));;
        Prepare device _d_e_v for opening a file. This device listens for
        the file name after this call which is normally sent by a call
        to the _w_r_i_t_e_(_)-function followed by an _u_n_l_i_s_t_e_n_(_) call.  Return
        value 0 on success, < 0 means error.


     iinntt ccbbmm__cclloossee((CCBBMM__FFIILLEE ff,, ____uu__cchhaarr ddeevv,, ____uu__cchhaarr sseeccaaddrr));;
        Close file associated with secondary address _s_e_c_a_d_r on device
        _d_e_v.  Return value 0 on success, < 0 means error.


     iinntt ccbbmm__uunnlliisstteenn((CCBBMM__FFIILLEE ff));;
        Send unlisten on bus.  Return value 0 on success, < 0 means
        error.


     iinntt ccbbmm__uunnttaallkk((CCBBMM__FFIILLEE ff));;
        Send untalk on bus.  Return value 0 on success, < 0 means error.
        descriptor.


     iinntt ccbbmm__ggeett__eeooii((CCBBMM__FFIILLEE ff));;
        Get EOI flag after bus read, return value is 0 with no EOI,
        otherwise 1.  When EOI is set to 1, the active talker has
        nothing more to send.


     iinntt ccbbmm__rreesseett((CCBBMM__FFIILLEE ff));;
        Do a hardware reset on all connected devices. Control is
        returned after a 5 second delay.


  33..33..22..  LLooww--lleevveell ppoorrtt aacccceessss


     ____uu__cchhaarr ccbbmm__pppp__rreeaadd((CCBBMM__FFIILLEE ff));;
        Read byte from XP1541/XP1571 bus. No handshaking or such
        involved.


     vvooiidd ccbbmm__pppp__wwrriittee((CCBBMM__FFIILLEE ff,, ____uu__cchhaarr cc));;
        Write byte to XP1541/XP1571 bus. No handshaking or such
        involved.



     iinntt ccbbmm__iieecc__ppoollll((CCBBMM__FFIILLEE ff));;
        Read status of all bus lines. Return value is a combination of
        IEC_ATN, IEC_CLOCK and IEC_DATA.


     iinntt ccbbmm__iieecc__ggeett((CCBBMM__FFIILLEE ff,, iinntt lliinnee));;
        Get (logical) status of line _l_i_n_e.


     vvooiidd ccbbmm__iieecc__sseett((CCBBMM__FFIILLEE ff,, iinntt lliinnee));;
        Activate line _l_i_n_e (set to 0V).


     vvooiidd ccbbmm__iieecc__rreelleeaassee((CCBBMM__FFIILLEE ff,, iinntt lliinnee));;
        Release line _l_i_n_e (set to 5V).


     iinntt ccbbmm__iieecc__wwaaiitt((CCBBMM__FFIILLEE ff,, iinntt lliinnee,, iinntt ssttaattee));;
        Experimental.


  33..33..33..  HHeellppeerr ffuunnccttiioonnss


     iinntt ccbbmm__uuppllooaadd((CCBBMM__FFIILLEE ff,, ____uu__cchhaarr ddeevv,, iinntt aaddrr,, vvooiidd **pprroogg,, iinntt
        ssiizzee));;
        Write _p_r_o_g into device _d_e_v's memory space via a series of "M-W"
        commands.


     iinntt ccbbmm__ddeevviiccee__ssttaattuuss((CCBBMM__FFIILLEE ff,, iinntt ddrrvv,, vvooiidd **bbuuff,, iinntt bbuuffssiizzee));;
        Read device status info _b_u_f, at most _b_u_f_s_i_z_e bytes are read.
        Returns _a_t_o_i_(_b_u_f_).


     iinntt ccbbmm__eexxeecc__ccoommmmaanndd((CCBBMM__FFIILLEE ff,, iinntt ddrrvv,, vvooiidd **ccmmdd,, iinntt lleenn));;
        Execute command _c_m_d. Returns number of bytes actually written.


     iinntt ccbbmm__iiddeennttiiffyy((CCBBMM__FFIILLEE ff,, iinntt ddrrvv,, eennuumm ccbbmm__ddeevviiccee__ttyyppee__ee **tt,,
        ccoonnsstt cchhaarr ****ttyyppee__ssttrr));;
        Tries to identify the device _d_r_v. The hardware type is returned
        in _t, _t_y_p_e___s_t_r contains a descriptive string which also includes
        the drives' operating system. Both _t and _t_y_p_e___s_t_r may be NULL in
        case the caller is not interrested in any of both values.

        The return value is 0 if the device responded to the "M-R"
        command, even if it could not be identified, < 0 indicates
        error.


  33..33..44..  lliibbdd6644ccooppyy TTOODDOO

  Not documented yet. See _l_i_b_d_6_4_c_o_p_y and _d_6_4_c_o_p_y source.

  Types and prototypes are defined in d64copy.h.


  33..33..55..  lliibbccbbmmccooppyy TTOODDOO

  Not documented yet. See _l_i_b_c_b_m_c_o_p_y and _c_b_m_c_o_p_y source.

  Types and prototypes are defined in cbmcopy.h.



