<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Mon, 24 May 2004 10:03:27 +0100
From   : Angus Duggan <angus.duggan@...>
Subject: Re: Tube / Master Coprocessor question

Sprow writes:
>In article <40B120C0.6010807@...>,
>   Richard Gellman <splodge@...> wrote:
>
>> Note that contrary to the expected behavior, the data is not 
>> signalled by interrupts.
>
>I'd have to disagree there. A cursory disassembly of the IRQ handler shows
>that messaging from the IO processor to the 2nd processor is done
>exclusively with interrupts, and the high speed block data transfers with
>NMIs.
>
>Maybe you were talking about the host not the parasite?
>Sprow.

Sorry about the length of this. The tube has both interrupting and
non-interrupting registers. The interrupting registers are used to signal
commands, parameters are then passed by polling.

Full details below.

a.

The Tube hardware provides 4 independent bi-directional comminication paths.
Each consists of a one byte control register and a one byte data register
(which may have multibyte buffering). The characterstics of each register set
are decribed below, in the descriptions RnSTAT refers to status register n
and RnDATA refers to its corresponding data register.

Register Set 1
                                Host address      Parasite address
R1DATA
  write                         FEE1                FEF9
  read (reading clears irq)
R1STAT
  bit 7 data available/irq      FEE0                FEF8
  bit 6 not full

In the parasite to host direction this register set is used for the OSWRCH
call. The data register is a FIFO big enough to enable the longest VDU
command (10 bytes) to reside within it. In the host to parasite direction the
data register provides a 1 byte buffer. When the host writes to it an IRQ is
generated to the parasite. It is used to pass on event interrupts and the
escape operation.

Register Set 2
                                Host address      Parasite address
R2DATA
  write                         FEE3               FEFB
  read
R2STAT
  bit 7 data available          FEE2               FEFA
  bit 6 not full

This register set is used to implement long (in machine time used) OS calls,
or those which (RDCH) cannot interrupt the WRCH host background task. The
parasite passes a byte to describe the required action. The two machines then
co-operate in passing data across R2DATA until the job is done.

Register Set 3
                                Host address      Parasite address
R3DATA
  write
  read                          FEE5               FEFD
R3STAT
  bit 7 data available/nmi      FEE4               FEFC
  bit 6 not full

R3DATA is programmeable (from the host) to be either a 1 or 2 byte FIFO. This
register set is used for the background task of block data transfer between
the two machines (cf register set 4). For higher performance applications
this register may actually interface to a DMA controller.

Register Set 4
                                Host address      Parasite address
R4DATA
  write (writing sets irq)      FEE7               FEFF
  read (reading clears irq)
R4STAT
  bit 7 data available/irq      FEE6               FEFE
  bit 6 not full/irq

This register set is used as a control channel for block transfers carried
out across R3. The host interrupts the parasite by writing a byte describing
the required action into R4DATA. The two machines then co-operate in passing
data across register 4 [? sic - ed] until the job is done.

The register set is also used to initiate the passing of an error string from
host to parasite. The host interrupts the parasite by writing an error code
into R4DATA, the two machines then cooperate in passing the error string
across R2DATA.

Notes:

(i) The BBC machine operates by polling the tube registers for work.
(ii) In all the transactions which may generate errors it is important to
realise that if the error is reported by the BBC machine under interrupt
(i.e. it was generated by a 6502 BRK sequence), the protocol which generated
the error is abandoned.

Non Interrupt protocols (parasite-side)

OSWRCH

Wait until R1DATA not full, write character into R1DATA.

OSRDCH

Wait until R2DATA not full, write RDCHNO (&00) to R2DATA
Wait for data in R2DATA, top bit of R2DATA is 6502 C bit
Wait for data in R2DATA, this is 6502 A register

OSCLI

Wait until R2DATA not full, write CLINO (&02) to R2DATA
FOR all characters in the command string (including terminating CR)
DO [
   Wait until R2DATA not full, write character to R2DATA
]
Wait for data in R2DATA and read it
IF this byte =&80
THEN [
   code has been loaded into the parasite by an interrupt protocol and it
   should be entered at the address given by the last R4 protocol type 4
   address.
]

OSBYTE

IF osbyte < &80
THEN [
   Wait until R2DATA not full, write SBYTNO (&04) to R2DATA
   Wait until R2DATA not full, write parameter for 6502 X register to R2DATA
   Wait until R2DATA not full, write osbyteno to R2DATA
   Wait for data in R2DATA, read R2DATA which is 6502 X register
]
ELSEIF osbyteno = &82 THEN [ resultis machine high order address ]
ELSEIF osbyteno = &83 THEN [ resultis low memory value ]
ELSEIF osbyteno = &84 THEN [ resultis high memory value ]
ELSE [
   Wait until R2DATA not full, write SBYTNO (&04) to R2DATA
   Wait until R2DATA not full, write parameter for 6502 X register to R2DATA
   Wait until R2DATA not full, write parameter for 6502 Y register to R2DATA
   Wait until R2DATA not full, write osbyteno to R2DATA
   IF osbyteno = &9D THEN RETURN from protocol (no reply)
   Wait for data in R2DATA, bit 7 is 6502 C flag
   Wait for data in R2DATA, byte read is 6502 Y register
   Wait for data in R2DATA, byte read is 6502 X register
]

OSWORD

IF oswordno = &00
THEN [
   Wait until R2DATA not full, write RDLNNO (&0A) to R2DATA
   Wait until R2DATA not full, write upper bound char to R2DATA
   Wait until R2DATA not full, write lower bound char to R2DATA
   Wait until R2DATA not full, write length allowed to R2DATA
   Wait until R2DATA not full, write &07 allowed to R2DATA
   Wait until R2DATA not full, write &00 allowed to R2DATA
   Wait for data in R2DATA
   IF this data > &7F THEN [ RETURN from protocol, escape was pressed ]
   Read a CR terminated string from R2DATA
]
ELSE [
   Wait until R2DATA not full, write WORDNO (&08) to R2DATA
   Wait until R2DATA not full, write oswordno to R2DATA
   Wait until R2DATA not full, write #params to send to R2DATA
   Wait parameter block to R2DATA, last byte first
   Wait until R2DATA not full, write #params to receive to R2DATA
   Read bytes back from R2DATA into parameter block, last byte first
]

The number of parameters to send/receive is determined by:
IF oswordno < &14
THEN [
     oswordno   parameters to send      parameters to receive
     1          0                       5
     2          5                       0
     3          0                       5
     4          5                       0
     5          2                       5
     6          5                       0
     7          8                       0
     8          14                      0
     9          4                       5
     10         1                       9
     11         1                       5
     12         5                       0
     13         0                       8
     14         16                      16
     15         16                      16
     16         16                      13
     17         13                      1
     18         0                       128
     19         8                       8
     20         128                     128
]
ELSEIF oswordno < &80
THEN [
     #params to send = 16
     #params to receive = 16
]
ELSE [
     byte 0 of transfer block = #params to send
     byte 1 of transfer block = #params to receive
]

OSBPUT

Wait until R2DATA not full, write BPUTNO (&10) to R2DATA
Wait until R2DATA not full, write file handle to R2DATA
Wait until R2DATA not full, write 6502 A to R2DATA (byte to write)
Wait for data in R2DATA, discard it

OSBGET

Wait until R2DATA not full, write BGETNO (&0E) to R2DATA
Wait until R2DATA not full, write file handle to R2DATA
Wait for data in R2DATA, top bit of byte is 6502 C flag
Wait for data in R2DATA, this is byte read from file

OSFIND

Wait until R2DATA not full, write FINDNO (&12) to R2DATA
Wait until R2DATA not full, write type of open to R2DATA
IF type = 0
THEN [
   Wait until R2DATA not full, write file handle to R2DATA
   Wait for data in R2DATA, read result
]
ELSE [
   Wait until R2DATA not full, write file name string to R2DATA including CR
   Wait for data in R2DATA, read handle from R2DATA
]

OSARGS

Wait until R2DATA not full, write ARGSNO (&0C) to R2DATA
Wait until R2DATA not full, write file handle to R2DATA
Wait until R2DATA not full, write 4 bytes osarg_data to R2DATA (most
   significant byte first)
Wait until R2DATA not full, write operation code to R2DATA
Wait for data in R2DATA, read fs type from R2DATA
Wait for data in R2DATA, read 4 bytes osarg_fs type from R2DATA (most
   significant byte first)

Note: osarg_data is file sequential pointer or length depending on the type
of OSARGS call.

OSFILE

Wait until R2DATA not full, write FILENO (&14) to R2DATA
Wait until R2DATA not full, write 16 byte OSFILE control block to R2DATA
   (last byte written first)
Wait until R2DATA not full, write filename to R2DATA including CR
Wait until R2DATA not full, write type of transfer to R2DATA (transfer is
   completed under interrupt using R3, R4)
Wait for data in R2DATA, low 7 bits is filing system type
Wait for data in R2DATA, read 16 byte OSFILE control block (last byte first)

OSGBPB

Wait until R2DATA not full, write GBPBNO (&16) to R2DATA
Wait until R2DATA not full, write 13 byte OSGBPB control block to R2DATA
   (last byte written first)
Wait until R2DATA not full, write type of transfer to R2DATA (transfer is
   completed under interrupt using R3, R4)
Wait for data in R2DATA, read 13 byte OSGBPB control block (last byte first)
Wait for data in R2DATA, bit 7 is 6502 C flag
Wait for data in R2DATA, read 6502 A register

Interrupt driven operations

In addition to thes parasite initiated activities the parasite is also
required to respond to interrupts from registers 1, 3 and 4.

The determine the source of an interrupt it is important to follow the order:

1. Check for register 4 interrupt
2. Check for register 1 interrupt

Register 1 interrupts

These occur only in the host to parasite direction. The interrupt sequence
is:

Read type byte from R1DATA
IF type < 0
THEN [ ; Escape flag update
  Replace the escape flag with bit 6 of type
  RETURN from servicing interrupt
]
ELSE [ ; Event signal
  Interrupt_R1_read 6502_Y event parameter
  Interrupt_R1_read 6502_X event parameter
  Interrupt_R1_read 6502_A event parameter
  ; BBC machine will now continue processing
  ; actions to service event can now be taken
]

Where Interrupt_R1_read is:

UNTIL data ready in R1
DO [
   IF data ready in R4 THEN CALL R4_interrupt_service
]
RETURN read R1DATA

Register 5 interrupts

Read type byte from R4DATA
IF type < 0
THEN [ ; BBC machine is reporting an error
   Wait for data in R2DATA, read and discard it
   Wait for data in R2DATA, read error number from R2DATA
   Read a zero byte terminated string from R2DATA
]
ELSE [ ; type is a command to initiate a register 3 block transfer
   Wait for data in register 4, read claimer identity from R4DATA
   CASE type OF
   [
      0 : ; Single byte transfer parasite to host
          Read 4 byte base address for transfer from R4DATA, msb first
          Set NMI routine for this transfer type
          Wait for and remove synchronising byte from R4DATA
      1 : ; Single byte transfer host to parasite
          Read 4 byte base address for transfer from R4DATA, msb first
          Set NMI routine for this transfer type
          Wait for and remove synchronising byte from R4DATA
      2 : ; Double byte transfer parasite to host
          Read 4 byte base address for transfer from R4DATA, msb first
          Set NMI routine for this transfer type
          Wait for and remove synchronising byte from R4DATA
      3 : ; Double byte transfer host to parasite
          Read 4 byte base address for transfer from R4DATA, msb first
          Set NMI routine for this transfer type
          Wait for and remove synchronising byte from R4DATA
      4 : ; No transfer (pass address host to parasite only)
          Read 4 byte base address for transfer from R4DATA, msb first
          Wait for data in R4DATA, discard it
      5 : ; No transfer (filing system release)
      6 : ; 256 byte transfer parasite to host without interrupt
          Read 4 byte base address for transfer from R4DATA, msb first
          Wait for data in R4DATA, discard it
          Transfer 256 bytes to host via R3DATA
          Write a byte into R4DATA to stop unwanted interrupts on host
      7 : ; 256 byte transfer host to parasite without interrupt
          Read 4 byte base address for transfer from R4DATA, msb first
          Wait for data in R4DATA, discard it
          Transfer 256 bytes from host via R3DATA
   ]
   RETURN from interrupt
]

Notes:

(i)   For type 0-3: As soon as the synchronising byte is removed register 3
      transfer requests (NMIs) will start to occur. When the interrupt occurs
      1 or 2 bytes are transferred (depending on the current mode).
(ii)  A release (type 5) is a guarantee that no more register 3 NMIs will
      occur for the current transfer.
(iii) The transfers must take place within the following times:

      Type      Max Service Time        Delay between sync and transfer start
      0         24uS per byte           24uS
      1         24uS per byte           24uS
      2         26uS per byte           24uS
      3         26uS per byte           24uS
      6         10uS per byte           19uS
      7         10uS per byte           19uS

END
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>