changeset 3032:3afecdae6f53

Low level CoCo SDC driver updtate from Darren Atkinson
author tlindner
date Mon, 22 Dec 2014 21:06:37 -0800
parents 75bf8852c390
children 7028ce216ccf
files defs/cocosdc.d level1/modules/llcocosdc.asm
diffstat 2 files changed, 483 insertions(+), 174 deletions(-) [+]
line wrap: on
line diff
--- a/defs/cocosdc.d	Sat Dec 20 12:52:07 2014 -0600
+++ b/defs/cocosdc.d	Mon Dec 22 21:06:37 2014 -0800
@@ -1,6 +1,3 @@
-          IFNE      COCOSDC.D-1
-COCOSDC.D SET       1
-
 ********************************************************************
 * cocosdc.d - CoCo SDC definitions
 *
@@ -11,8 +8,38 @@
 * ------------------------------------------------------------------
 *          2014/05/02  Boisy G. Pitre
 * Created
+*          2014/12/22  Darren Atkinson
+* Additional hardware symbols
+
+               IFNE      COCOSDC.D-1
+COCOSDC.D      SET       1
 
 
+* Main Port Address (V.PORT)
 SDAddr         SET       $FF4A
 
+* Hardware Addressing - CoCo Scheme
+CTRLATCH       equ       $FF40              controller latch (write)
+CMDREG         equ       $FF48              command register (write)
+STATREG        equ       $FF48              status register (read)
+PREG1          equ       $FF49              param register 1
+PREG2          equ       $FF4A              param register 2
+PREG3          equ       $FF4B              param register 3
+DATREGA        equ       PREG2              first data register
+DATREGB        equ       PREG3              second data register
+FLSHDAT        equ       $FF42              flash data register
+
+* Status Register Masks
+BUSY           equ       %00000001          set while a command is executing
+READY          equ       %00000010          set when ready for a data transfer
+FAILED         equ       %10000000          set on command failure
+
+* Command and Mode Values
+CMDMODE        equ       $43                control latch value to enable command mode
+CMDREAD        equ       $80                read logical sector
+CMDWRITE       equ       $A0                write logical sector
+CMDEX          equ       $C0                extended command
+CMDEXD         equ       $E0                extended command with data block
+
+
                ENDC      
--- a/level1/modules/llcocosdc.asm	Sat Dec 20 12:52:07 2014 -0600
+++ b/level1/modules/llcocosdc.asm	Mon Dec 22 21:06:37 2014 -0800
@@ -1,21 +1,34 @@
 ********************************************************************
-* llcocosdc - CoCo SD Low-level driver
+* llcocosdc - CoCo SDC Low-level driver
 *
 * $Id$
 *
 * Edt/Rev  YYYY/MM/DD  Modified by
 * Comment
 * ------------------------------------------------------------------
-*          2004/??/??  Boisy G. Pitre
+*          2013/05/??  Boisy G. Pitre
 * Created.
 *          2014/11/27  tim lindner
-* Changed read and write routines to enter and leave command mode
+* Changed read and write routines to enter and leave command mode.
+*
+*          2014/12/22  Darren Atkinson
+* Total re-write. Provides MPI slot selection to permit co-existence
+* with a real floppy controller.  Sends command to controller during
+* Init which locks out the floppy emulation capability. Adds GetStat
+* functions for extended commands.  Uses TFM to retrieve data blocks
+* when a 6309 CPU is present. Supports the SS.DSize GetStat function
+* to query controller for the disk size.
+*
 
                NAM       llcocosdc
                TTL       CoCo SDC Low-level driver
 
                USE       defsfile
                USE       rbsuper.d
+               USE       cocosdc.d
+
+MPIREG         equ       $FF7F
+
 
 tylg           SET       Sbrtn+Objct
 atrv           SET       ReEnt+rev
@@ -24,52 +37,28 @@
 
                MOD       eom,name,tylg,atrv,start,0
 
+* Low-level driver static memory area inside that of rbsuper
                ORG       V.LLMem
-* Low-level driver static memory area
+V.SDCMPI       rmb       1                  MPI slot containing CoCo SDC
+V.MaskIRQs     rmb       1                  contains $50 if IRQ/FIRQ should be masked
 
 name           FCS       /llcocosdc/
 
-start          bra       ll_init
-               nop       
-               lbra      ll_read
-               lbra      ll_write
+start          lbra      ll_init
+               bra       ll_read
+               nop
+               bra       ll_write
+               nop
                bra       ll_getstat
-               nop       
-               lbra      ll_setstat
-*         lbra  ll_term   
-
-* ll_term
-*
-* Entry:
-*    Y  = address of device descriptor
-*    U  = address of device memory area
-*
-* Exit:
-*    CC = carry set on error
-*    B  = error code
-*
-ll_term                  
-               clrb      
-               rts       
-
-* ll_init
-*
-* Entry:
-*    Y  = address of device descriptor
-*    U  = address of device memory area
-*
-* Exit:
-*    CC = carry set on error
-*    B  = error code
-*
-ll_init                  
-*               ldy      V.PORT-UOFFSET,u
-*               ldb      #$43
-*               stb      -$0A,y
-               clrb      
-               rts       
+               nop
+               bra       ll_setstat
+               nop
+           *** lbra      ll_term ***
+               clrb
+               rts
 
 
+*--------------------------------------------------------------------------
 * ll_getstat
 *
 * Entry:
@@ -80,35 +69,21 @@
 *    CC = carry set on error
 *    B  = error code
 *
-ll_getstat               
-               lda       R$B,x
+ll_getstat     ldx       PD.RGS,y           point X at stacked registers
+               lda       R$B,x              get function code
                cmpa      #SS.DSize
-               beq       SSDSize
-               ldb       #E$UnkSvc
-               coma      
-               rts       
-
+               beq       getSize            branch if "get disk size"
+               tfr       a,b
+               andb      #$F0               keep hi nibble
+               cmpb      #CMDEXD
+               beq       exCmd              branch if extended command with data
+               anda      #$FF-4             make sure "TFM" bit is cleared
+               cmpb      #CMDEX
+               beq       exCmd              branch if ext command without data
 
-* SS.DSize - Return size information about a device
-*
-* Entry: B = SS.DSize
-* Exit:  Carry = 1; error with code in B
-*        Carry = 0:
-*          IF B = 0
-*            A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
-*            X = Number of Sectors (bits 31-16)
-*            Y = Number of Sectors (Bits 15-0)
-*          IF B != 0
-*            A = Sector Size (1 = 256, 2 = 512, 4 = 1024, 8 = 2048)
-*            X = Number of Logical Cylinders
-*            B = Number of Logical Sides
-*            Y = Number of Logical Sectors/Track
-*
-SSDSize                  
-               clrb      
-               rts
+               *** Fall Thru ***
 
-
+*--------------------------------------------------------------------------
 * ll_setstat
 *
 * Entry:
@@ -119,60 +94,259 @@
 *    CC = carry set on error
 *    B  = error code
 *
-ll_setstat               
-               clrb      
-               rts       
+ll_setstat     comb                         set carry
+               ldb       #E$UnkSvc          return error
+               rts
+
+
+*--------------------------------------------------------------------------
+* SS.DSize - Return size information about a device
+*
+* Exit:
+*    Carry cleared for no error.
+*    A = Sector Size  (1=256, 2=512, 4=1024, 8=2048)
+*
+*      IF B = 0
+*          X = Number of Sectors (bits 31-16)
+*          Y = Number of Sectors (Bits 15-0)
+* 
+*      IF B != 0
+*          B = Number of Logical Sides
+*          X = Number of Logical Cylinders
+*          Y = Number of Logical Sectors/Track
+*
+getSize        lda       #CMDEX             primary command code
+               ora       PD.DRV,y           combine drive num with command
+               ldb       #'Q                "Query Size" sub-command
+               ldu       #$FFFF             I/O buffer = none
+               pshs      x                  save frame ptr
+               bsr       CommSDC            send query to controller
+               puls      x                  restore frame ptr
+               ldb       #E$NotRdy          error code
+               bcs       sizeRet            return if error
+               clra                         bits 31-24 of size always zero
+               ldb       -1,y               bits 23-16 of size
+               std       R$X,x              return bits 31-16 in X
+               ldd       ,y                 bits 15-0 of size
+               std       R$Y,x              return in Y
+               inca                         A = 1:  256 byte sectors
+               clrb                         B = 0:  LBA device
+               std       R$D,x              return in D
+sizeRet        rts
+
 
+*--------------------------------------------------------------------------
+* SDC Extended Device Commands
+*
+*   Entered with SDC command code in A.
+*
+*   Parameters are passed indirectly via the register frame:
+*       X = address of 256 byte I/O buffer or $FFFF if none
+*     U.L = optional param byte 1
+*       Y = optional param bytes 2 (hi) and 3 (low)
+*
+*   Response values are returned indirectly via the register frame:
+*       A = controller status
+*     U.H = 0
+*     U.L = response byte 1
+*       Y = response bytes 2 (hi) and 3 (low)
+*
+exCmd          pshs      u,y,x              preserve registers
+               leay      ,u                 Y = device memory area
+               ldu       R$X,x              U = I/O buffer address
+               ldb       R$U+1,x            B = param byte 1
+               ldx       R$Y,x              X = param bytes 2 and 3
+               bsr       CommSDC            do command protocol
+               puls      x                  restore register frame pointer
+               stb       R$A,x              [A] = controller status
+               lda       #0                 will clear top half of U
+               ldb       -1,y               get response byte 1 (FF49)
+               std       R$U,x              [U] = 1st response byte
+               ldd       ,y                 get response bytes 2,3 (FF4A,B)
+               std       R$Y,x              [Y] = 2nd and 3rd response bytes
+               ldb       #E$NotRdy          error code
+               bcs       exOut              skip next if error 
+               clrb                         no error
+exOut          puls      y,u,pc             return 
+
+
+*--------------------------------------------------------------------------
+* ll_write
+*
+*    Write one sector.
+*
+* Entry:
+*    Y  = address of path descriptor
+*    U  = address of device memory area
+*
+*
+ll_write       lda       #CMDWRITE          command code for Write
+               bsr       sectorIO           common sector I/O
+               bcc       wrRet              return if success
+               ldb       #E$Write           error code for write
+wrRet          rts
+
+               
+*--------------------------------------------------------------------------
 * ll_read
 *
+*    Read one sector.
+*
 * Entry:
 *    Y  = address of path descriptor
 *    U  = address of device memory area
 *
-* Static memory referenced:
-*    V.CchPSpot     = address of spot in cache where physical sector data will go
-*    sectsize       = sector size (0=256,1=512,2=1024,3=2048)
-*    V.SectCnt      = sectors to read
-*    V.PhysSect = physical sector to start read from
-ll_read              
-               lda       #$43
-               sta       $ff40
-               ldx       #0
-rdCmMd         lda       $ff48
-               lsra
-               bcc       rdStart
-               leax      -1,x
-               bne       rdCmMd
-               bra       rdFail
-               
-rdStart        lda       PD.DRV,y
-               ldb       V.PhysSect,u
-               ldx       V.PhysSect+1,u
-               ldy       V.PORT-UOFFSET,u
-               ldu       V.CchPSpot,u
+ll_read        lda       #CMDREAD+4         command code for 6309 Read (TFM)
+               fcb       $11                next instr is "LDE" on 6309
+               lda       #CMDREAD           command code for 6809 Read
+               bsr       sectorIO           common sector I/O
+               bcc       rdRet              return if success
+               ldb       #E$Read            error code for read
+rdRet          rts
+
+
+*--------------------------------------------------------------------------
+* Funnel code for sector read and write
+*
+* Entry:
+*    A  = read/write command code
+*    Y  = address of path descriptor
+*    U  = address of device memory area
+*
+sectorIO       ldb       #1                 highest drive number allowed
+               subb      PD.DRV,y           range check drive number
+               bcc       drvOK              branch if valid
+               ldb       #E$Unit            error code for bad drive number
+               puls      x,pc               pop top address then return
+
+drvOK          ora       PD.DRV,y           combine drive num with command
+               leay      ,u                 point Y at device mem
+               ldb       V.PhysSect,u       B = hi byte of LSN
+               ldx       V.PhysSect+1,u     X = lo word of LSN
+               ldu       V.CchPSpot,u       U = buffer address
+ 
+               *** Fall Thru ***
+
+*--------------------------------------------------------------------------
+* CommSDC
+*
+*    This is the core routine used for all
+*    transactions with the SDC controller.
+*
+* Entry:
+*    A = Command code
+*    B = LSN hi byte  / First parameter byte
+*    X = LSN lo word  / 2nd and third param bytes
+*    Y = Address of driver device memory area
+*    U = Address of I/O buffer ($FFFF = none)
+*
+* Exit:
+*    Carry set on error
+*    B = controller status code
+*    Y = address of SDC Data Register A (FF4A)
+*
+CommSDC
+
+* Save current MPI setting and activate the SDC slot
+               pshs      cc                 preserve CC (interrupt masks)
+               lsr       ,s                 shift carry out of saved CC
+               pshs      a,b                save cmd code, alloc byte for saving MPI
+               tfr       cc,a               get copy of current CC
+               ora       V.MaskIRQs,y       set I and F masks if FDC present
+               tfr       a,cc               update I and F in CC
+               lda       MPIREG             get current MPI slot
+               sta       1,s                save on stack where B was pushed
+               anda      #$30               mask out current SCS nibble
+               ora       V.SDCMPI,y         insert SCS nibble for SDC slot
+               ldy       #DATREGA           setup Y for hardware addressing
+               tsta                         was an SDC controller found?
+               bmi       sdcNone            exit if no
+               sta       MPIREG             activate MPI slot
+
+* Put controller in Command mode
+               lda       #CMDMODE           the magic number
+               sta       -10,y              send to control latch (FF40)
+               puls      a                  pull saved command code back into A
 
-               stb       -1,y
-               stx       ,y
-               ora       #$80
-               sta       -2,y
-               exg       a,a
+* Put input parameters into the registers.
+* It does no harm to put random data in the
+* registers for commands which dont use them.
+               stb       -1,y               high byte to param reg 1
+               stx       ,y                 low word to param regs 2 and 3
+
+* Wait for Not Busy.
+               lbsr     waitForIt           run polling loop
+               bcs      cmdExit             exit if error or timed out
+
+* Send command to controller
+               sta       -2,y               to command register (FF48)
+
+* Determine if a data block should be sent.
+* The code for any command which requires
+* a data block will have bit 5 set.
+               bita      #$20               test the "send block" command bit
+               beq       rxBlock            branch if no block to send
+
+* Wait for Ready to send
+               bsr      waitForIt           run polling loop
+               bcs      cmdExit             exit if error or timed out
+               leax     ,u                  move data address to X
+            IFGT Level-1
+               bita      #$40               extended command or sector write?
+               lbne      txCmd              branch if extended command
+            ENDIF
 
-               ldx       #0
-rdWait         lda       -2,y
-               bmi       rdFail
-               bita      #2
-               bne       rdRdy
-               leax      -1,x
-               bne       rdWait
-rdFail
-               clr       $ff40
-               ldb       #E$Read
-               coma
-               rts
+* Send 256 bytes of data
+               ldd       #32*256+8          32 chunks of 8 bytes
+txChunk        ldu       ,x                 send one chunk...
+               stu       ,y
+               ldu       2,x
+               stu       ,y
+               ldu       4,x
+               stu       ,y
+               ldu       6,x
+               stu       ,y
+               abx                          point X at next chunk
+               deca                         decrement chunk counter
+               bne       txChunk            loop until all 256 bytes sent
+
+* Wait for command to complete
+txCompl        lda       #5                 timeout retries
+txWait         bsr       waitForIt          run polling loop
+               bitb      #BUSY              test BUSY bit
+               beq       cmdExit            exit if completed
+               deca                         decrement retry counter
+               bne       txWait             repeat if until 0
+               coma                         set carry for timeout error
+               bra       cmdExit            exit
 
-rdRdy          leax      ,u
-               ldd       #32*256+8
-rdChnk         ldu       ,y
+* Set error condition and exit when no SDC hardware found
+sdcNone        leas      1,s                pop saved command code
+               comb                         set carry
+               ldb       #E$Unit            error number for missing hardware
+               bra       cmdExit            exit
+
+* For commands which return a 256 byte response block the
+* controller will set the READY bit in the Status register
+* when it has the data ready for transfer.   For commands
+* which do not return a response block the BUSY bit will
+* be cleared to indicate that the command has completed.
+*
+rxBlock        bsr       longWait           run long status polling loop
+               bls       cmdExit            exit if error, time out or completed
+               leax      1,u                test the provided buffer address
+               beq       cmdExit            exit if "no buffer" ($FFFF)
+               bita      #$04               test the "TFM" command bit
+               bne       rx6309             branch if set
+               leax      ,u                 move data address to X
+            IFGT Level-1
+               bita      #$40               extended command or sector read?
+               bne       rxCmd              branch if extended command
+            ENDIF
+
+* 6809 read transfer loop into current task space
+               ldd       #32*256+8          32 chunks of 8 bytes
+rxChunk        ldu       ,y                 read one chunk...
                stu       ,x
                ldu       ,y
                stu       2,x
@@ -180,78 +354,186 @@
                stu       4,x
                ldu       ,y
                stu       6,x
-               abx
-               deca
-               bne       rdChnk
+               abx                          update X for next chunk
+               deca                         decrement chunk counter
+               bne       rxChunk            loop until all 256 bytes transferred
+               bra       cmdOK              exit with SUCCESS
 
-               sta       $ff40
-               rts
+* 6309 read transfer using TFM into current task space
+rx6309         fcb       $10,$86,$01,$00    [ldw #256] block size = 256
+               orcc      #$50               ensure interrupts are masked
+               leax      1,y                point X at Data Register B (FF4B)
+               fcb       $11,$3B,$13        [tfm x,u+] read block
+cmdOK          clrb                         status code for SUCCESS, clear carry
+
+* Exit
+cmdExit        puls      a                  pull saved MPI settings
+               rol       ,s                 rotate carry into saved CC on stack
+               clr       -10,y              end command mode
+               sta       MPIREG             restore saved MPI settings
+               puls      cc,pc              restore irq masks, update carry and return
 
 
-* ll_write
+*--------------------------------------------------------------------------
+* Wait for controller status to indicate either "Not Busy" or "Ready".
+* Will time out if neither condition satisfied within a suitable period.
+*
+* Exit:
+*    CC.C set on error or time out.
+*    CC.Z set on "Not Busy" status (if carry cleared).
+*    B = status
+*    A, Y and U are preserved.
+*
+longWait       bsr       waitForIt          enter here for doubled timeout
+               bcc       waitRet            return if cleared in 1st pass
+waitForIt      ldx       #0                 setup timeout counter
+waitLp         comb                         set carry for assumed FAIL
+               ldb       -2,y               read status
+               bmi       waitRet            return if FAILED
+               lsrb                         BUSY --> Carry
+               bcc       waitDone           branch if not busy
+               bitb      #READY/2           test READY (shifted)
+               bne       waitRdy            branch if ready for transfer
+               bsr       waitRet            consume some time
+               ldb       #$81               status = timeout
+               leax      ,-x                decrement timeout counter
+               beq       waitRet            return if timed out
+               bra       waitLp             try again
+
+waitDone       clrb                         Not Busy: status = 0, set Z
+waitRdy        rolb                         On Ready: clear C and Z
+waitRet        rts                          return
+
+
+*--------------------------------------------------------------------------
+* Transfers of command and response data require special handling
+* in Level 2 due to separate address space for System/User tasks.
+*
+            IFGT Level-1
+* Send command data from User task space
+txCmd          bsr       tskPrep            B = task#, push word counter
+txWord         os9       F$LDABX            get byte from user space buffer
+               sta       ,y                 send 1st half of word
+               leax      1,x                increment buffer address
+               os9       F$LDABX            get byte from user space buffer
+               sta       1,y                send 2nd half of word
+               leax      1,x                increment buffer address
+               dec       ,s                 decrement word counter
+               bne       txWord             loop if more to send
+               leas      1,s                pop word counter
+               lbra      txCompl            go wait for command completion
+
+tskPrep        ldu       D.Proc             get current process ptr
+               ldb       P$Task,u           get task # for current process
+               lda       #128               number of words to transfer (256 bytes)
+               ldu       ,s+                half-pop return address into U
+               sta       ,s                 leave word counter on the stack
+               tfr       u,pc               return
+
+* Read response data into User task space
+rxCmd          bsr       tskPrep            B = task#, push word counter
+rxWord         lda       ,y                 read 1st half of word
+               os9       F$STABX            store in user space buffer
+               leax      1,x                increment buffer address
+               lda       1,y                read 2nd half of word
+               os9       F$STABX            store in user space buffer
+               leax      1,x                increment buffer address
+               dec       ,s                 decrement word counter
+               bne       rxWord             loop if more to read
+               leas      1,s                pop word counter
+               bra       cmdOK              exit with SUCCESS
+            ENDIF
+
+
+*--------------------------------------------------------------------------
+* ll_init
 *
 * Entry:
-*    Y  = address of path descriptor
+*    Y  = address of device descriptor
 *    U  = address of device memory area
 *
-* Static memory referenced:
-*    V.CchPSpot     = address of spot in cache where physical sector data is
-*    sectsize       = sector size (0=256,1=512,2=1024,3=2048)
-*    V.SectCnt      = sectors to read
-*    V.PhysSect     = physical sector to start read from
-ll_write                 
-               lda       #$43
-               sta       $ff40
-               ldx       #0
-wrCmMd         lda       $ff48
-               lsra
-               bcc       rwStart
-               leax      -1,x
-               bne       wrCmMd
-               bra       wrFail
+* Exit:
+*    CC = carry set on error
+*    B  = error code
+*
+ll_init        pshs      cc                 save irq masks
+               orcc      #$50               mask irqs
+               ldd       #$8080             prepare "not found" values
+               pshs      dp,b,a             alloc variables on stack
+               ldx       #CMDREG            point X at FDC command reg
+               ldb       MPIREG             get current MPI slot
+               andb      #$33               mask out the unused bits
+               stb       2,s                save on stack (in DP position)
+               orb       #$03               start SCS scan at slot 4
 
-rwStart        lda       PD.DRV,y
-               ldb       V.PhysSect,u
-               ldx       V.PhysSect+1,u
-               ldy       V.PORT-UOFFSET,u
-               ldu       V.CchPSpot,u
+chkSlot        stb       MPIREG             activate slot being scanned
+               lda       ,s                 have we already found CoCo SDC ?
+               bpl       chkFDC             branch if yes
+               lda       #$64               test pattern
+               sta       -6,x               store at Flash Data Reg address
+               lda       -5,x               get value from Flash Ctrl Reg
+               clr       -6,x               clear Flash Data Reg
+               eora      -5,x               get changed bits from Ctrl Reg
+               suba      #$60               did expected bits change?
+               bne       chkFDC             branch if not an SDC
+               stb       ,s                 record the SDC slot
+               bra       nxtSlot            go scan next slot
 
-               stb       -1,y
-               stx       ,y
-               ora       #$A0
-               sta       -2,y
-               exg       a,a
+chkFDC         lda       1,s                have we already found an FDC ?
+               bpl       nxtSlot            branch if yes
+               bsr       fdcTest            test if FDC present
+               bne       nxtSlot            branch if not present
+               stb       1,s                record the FDC slot
 
-               ldx       #0
-wrWait         lda       -2,y
-               bmi       wrFail
-               bita      #2
-               bne       wrRdy
-               leax      -1,x
-               bne       wrWait
-wrFail
-               clr       $ff40
-               ldb       #E$Write
-               coma
-               rts
+nxtSlot        decb                         decrement SCS slot number
+               bitb      #$08               have we scanned all slots?
+               beq       chkSlot            loop if more to scan
+               lda       ,s                 get slot with CoCo SDC
+               bmi       saveSDC            branch if none
+               cmpa      2,s                same as original slot selection?
+               bne       saveSDC            branch if no
+               eora      #$01               change original slot to..
+               sta       2,s                ..be something else
+               eora      #$01               back to the true SDC slot
+saveSDC        anda      #$83               keep SDC slot number or "not found"
+               sta       V.SDCMPI,u         store SDC slot info in device mem
+               lda       #$50               irq masks will be needed if FDC present
+               ldb       1,s                was an FDC found?
+               bpl       useSlot            branch if yes
+               clra                         irq masks not needed
+               ldb       2,s                get original MPI slot selection
+useSlot        stb       MPIREG             activate default MPI slot
+               sta       V.MaskIRQs,u       store irq masks in device mem
+               lda       $FF22              reset any latched CART interrupt
+               leas      3,s                pop variables off the stack
+               puls      cc                 restore saved irq masks
 
-wrRdy          leax      ,u
-               ldd       #64*256+4
-wrChnk         ldu       ,x
-               stu       ,y
-               ldu       2,x
-               stu       ,y
-               abx
-               deca
-               bne       wrChnk
+* Disable Floppy Emulation capability in SDC controller
+               lda       #$C0               primary command code
+               ldb       #'g                secondary command to "Set Global Flags"
+               ldx       #$FF80             mask/flag bytes
+               leay      ,u                 point Y at static variables
+               ldu       #$FFFF             "no buffer" address
+               lbsr      CommSDC            send command to controller
+               clrb                         no error
+               rts                          return
 
-wrComp         lda       -2,y
-               bmi       wrFail
-               lsra
-               bcs       wrComp
+* Test for presence of FDC in active slot
+fdcTest        lda       #$D0               FORCE INTERRUPT command
+               sta       ,x                 send to FDC command register
+               bsr       fdcDelay           wait awhile
+               lda       ,x                 read FDC status
+               lda       3,x                read FDC data register
+               coma                         invert all bits
+               sta       3,x                put inverted data back
+               bsr       fdcDelay           wait awhile
+               suba      3,x                test if read matches write
+fdcDelay       pshs      y,x,d,cc           push regs
+               mul                          delay cycles
+               puls      cc,d,x,y,pc        restore regs and return
 
-               clr       $ff40
-               rts
+
+*--------------------------------------------------------------------------
 
                EMOD      
 eom            EQU       *