Finding The SmartPort Dispatcher - FujiNetWIFI/fujinet-firmware GitHub Wiki
Before using the SmartPort, you have to find it. More specifically, you have to find the dispatcher.
Finding the Slot
The first part, finding the slot, is accomplished by scanning the I/O space for each slot ($C000, $C100, ...), for the following four bytes at offsets 1, 3, 5, and 7:
Offset | Byte |
---|---|
1 | $20 |
3 | $00 |
5 | $03 |
7 | $00 |
C implementation
/**
* Check for SmartPort presence
* @return slot #, or 0xFF if not present.
*/
uint8_t sp_find_slot(void)
{
uint8_t s=0;
for (s=7; s-- > 0;)
{
uint16_t a = 0xc000 + (s * 0x100);
if ((PEEK(a+1) == 0x20) &&
(PEEK(a+3) == 0x00) &&
(PEEK(a+5) == 0x03) &&
(PEEK(a+7) == 0x00))
return s;
}
// Did not find.
return 0;
}
6502 Assembly Example
SRC_ADDR = $ED
SRC_ADDR_LO = $ED
SRC_ADDR_HI = $EE
;*******************************
; FIND_SMARTPORT_SLOT
; INPUT:
; NONE
;***
; RETURN
; A = $FF - NO SMARTPORT FOUND
; A = $CX - WHERE X IS THE SLOT
;**********************************
FIND_SMARTPORT_SLOT:
LDA #$C7 ; START AT SLOT 7 ($C700)
STA SLOT_ADDR_HI
LDA #$00
STA SLOT_ADDR_LO
SCAN:
LDY #$01 ; LOOK AT BYTES 1,3,5,AND 7
LDX #$00
NEXT_MATCH:
LDA (SLOT_ADDR),Y ; COMPARE TO THE MAGIC NUMBERS
CMP FIJINET_ID,X ;
BNE NEXT_SLOT ; NOT THE SAME, SO GO TO NEXT SLOT
INY ; PREPARE TO CHECK THE NEXT NUMBER
INY
INX ; POINTER TO NEXT NUMBER TO CHECK
CPX #$04 ; HAVE WE COMPARED ALL 4 NUMBERS?
BEQ FOUND ; YES, WE'VE FOUND IT
BNE NEXT_MATCH ; MORE TO MATCH
NEXT_SLOT:
LDX SLOT_ADDR_HI ; MOVE TO THE NEXT LOWER SLOT
DEX ; $C700 -> $C600
STX SLOT_ADDR_HI
CPX #$C0 ; HAVE WE GONE BELOW SLOT 1?
BEQ NOT_FOUND ; WE'RE DONE
BNE SCAN ; CONTINUE SCANNING
FOUND:
LDA SLOT_ADDR_HI
RTS ; WE FOUND IT! A = SLOT ADDRESS
NOT_FOUND:
LDA #$FF ; WE DIDN'T FIND IT
RTS
FIJINET_ID: .BYTE $20, $00, $03, $00
Finding the dispatch address
Once the slot has been found, the dispatcher address can be found by reading offset $FF at the found slot, then taking the value found, adding 3 to it, and adding that to the slot address.
C implementation
/**
* Return dispatch address for Smartport slot.
* @param s Slot # (1-7)
* @return smartport dispatch address
*/
uint16_t sp_dispatch_address(uint8_t slot)
{
uint16_t a = (slot * 0x100) + 0xC000;
uint8_t j = PEEK(a+0xFF);
return a + j + 3;
}
6502 Assembly Example
;*******************************
; GET_SMARTPORT_DISPATCH_ADDRESS
; INPUT:
; NONE
;***
; RETURN
; -A DISPATCHER ADDRESS HIGH
; -X DISPATCHER ADDRESS LOW
; OR A AND X WILL BE SET TO $FF
; IF DISPATCHER NOT FOUND
;**********************************
DISPATCHER = $EB
DISPATCHER_ADDR_LO = $EB
DISPATCHER_ADDR_HI = $EC
GET_SMARTPORT_DISPATCH_ADDRESS:
JSR FIND_SMARTPORT_SLOT
CMP #$FF ; IF A == $FF THEN NOT FOUND
BEQ NO_DISPATCHER
STA DISPATCHER_ADDR_HI ; A = $CX WHERE X IS THE SLOT
LDA #$00
STA DISPATCHER_ADDR_LO ; COMPLETE ADDRESS IS $CX00
LDY #$FF
LDA (SLOT_ADDR),Y ; j= peek(a+0xFF)
CLC
ADC DISPATCHER_ADDR_LO ; DISPATCHER_ADDR += J
STA DISPATCHER_ADDR_LO
LDA DISPATCHER_ADDR_HI
ADC #$00
STA DISPATCHER_ADDR_HI
CLC ; DISPATCHER_ADDR += 3
LDA DISPATCHER_ADDR_LO
ADC #$03
STA DISPATCHER_ADDR_LO
LDA DISPATCHER_ADDR_HI
ADC #$00
STA DISPATCHER_ADDR_HI
LDA DISPATCHER_ADDR_HI ; PUT ADDRESS IN A AND X
LDX DISPATCHER_ADDR_LO
CLC
BCC DONE
NO_DISPATCHER:
LDA #$FF ; NO ADDRESS FOUND
LDX #$FF
DONE:
RTS
Once this is found, you can start Issuing SmartPort Commands.