  cbm4linux Users Guide
  Michael Klein, nip@c64.org
  2001/22/01

  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 Examples
     2.2 cbmformat
        2.2.1 cbmformat invocation
     2.3 d64copy
        2.3.1 d64copy invocation

  3. cbm4linux API

     3.1 Preprocessor macros
     3.2 Variables
     3.3 Functions


  ______________________________________________________________________

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

  The popular Commodore 8-bit homecomputers 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.



  22..11..22..  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 8 0xc000 0xc000 > 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.


  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 disk- 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 Quiet output, don't output track map


     --ss _s_t_a_r_t _t_r_a_c_k
        Set start track (defaults to 1)


     --ee _e_n_d _t_r_a_c_k
        Set end track (defaults to 35). _d_6_4_c_o_p_y is able to access tracks
        1-35 in original transfer mode and 1-40 with serial1, serial2
        and parallel.


     --tt _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_n_t_e_r_l_e_a_v_e
        Set interleave value. This is ignored when reading in warp mode.
        Default is 16 for transer 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 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 reliefes the drive's
        CPU. However, although read errors are recognized and displayed,
        warp mode doesn't try very hard to re-read those sectors (yet).
        If you encounter tracks containing read errors it is often a
        good idea to copy those tracks via the -s and -e options once
        again in turbo mode to the same .d64 image. _d_6_4_c_o_p_y won't touch
        the other tracks in this case.


     --bb BAM-only copy. Only blocks marked as allocated are copied. For
        extended tracks (36-40), SpeedDOS BAM format is assumed. Use
        with caution.


     --BB Save BAM-only copy. this is like the -b option but always copies
        the entire directory track (18).


     --dd 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).



  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
  libcbm4linux.a. The Prototypes can be found in cbm4linux.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 _d_6_4_c_o_p_y source for more information.


  33..22..  VVaarriiaabblleess



     ccoonnsstt cchhaarr ccbbmm__ddeevv[[]];;
        This is the name of the cbm4linux character device. Normally
        /dev/cbm.  This file needs to be opened to access any cbm4linux
        functionality.


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


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


     iinntt ccbbmm__lliisstteenn((iinntt 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 0 on success, < 0 means error.


     iinntt ccbbmm__ttaallkk((iinntt 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 0 on success, < 0 means error.


     iinntt ccbbmm__ooppeenn((iinntt 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((iinntt 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 secondard 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((iinntt 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((iinntt 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((iinntt ff));;
        Get EOI flag after bus read, return velue 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((iinntt ff));;
        Do a hardware reset on all connected devices. Control is
        returned after a 5 second delay.
     ____uu__cchhaarr ccbbmm__pppp__rreeaadd((iinntt ff));;
        Read byte from XP1541/XP1571 bus. No hardshaking or such
        involved.


     vvooiidd ccbbmm__pppp__wwrriittee((iinntt ff,, ____uu__cchhaarr cc));;
        Write byte to XP1541/XP1571 bus. No hardshaking or such
        involved.


     iinntt ccbbmm__iieecc__ppoollll((iinntt ff));;
        Read status of all bus lines. Return value if 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((iinntt 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((iinntt 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((iinntt 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((iinntt ff,, iinntt lliinnee,, iinntt ssttaattee));;
        Experimental.


     iinntt ccbbmm__uuppllooaadd((iinntt ff,, ____uu__cchhaarr ddeevv,, iinntt aaddrr,, ____uu__cchhaarr **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((iinntt ff,, iinntt ddrrvv,, cchhaarr **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((iinntt ff,, iinntt ddrrvv,, cchhaarr **ccmmdd,, iinntt lleenn));;
        Execute command _c_m_d. Returns number of bytes actually written.






















