CoCoZilla Page NoCan3 Page NoCan2 Page Bottom Connector Page MPI Clone Page IDEZilla Page Pocket IDE Page 512K Schematic, BIG 828 x 1114. MFM HardDrive Page 4MHZ Page PLCC 6309 Page
Make a NitrOS-9 Boot Disk. NoCan3 Information Page Address Selection Page Pocket IDE Photos 4MHz PCB Page
Frequently Asked Questions NoCan3 Circuit Board Page NoCan2 PCB Page IDE PCB Page
I2C Page NoCan3 Jumpers Page NoCan2 Jumpers Page IDE CHS Driver Page
Update Your 26-3024 MPI for CoCo-3 Use Auto-Refresh No Excuses List IDE LBA Driver Page
HiDensity Modifications HiDensity Mod Text FIle
NoCan3 with I2C Bus Bart GIF Page Get the 26-3024 UpGrade GAL MPI 26-3124 UpGrade Page Back to the Thumbnail Page

 
CoCoZilla's MFM Mass Storage
Presented by: Only On Saturday Night
This is the WDXT slot.Schematic: CoCo to WDXT This is a record of my first attempts at mass storage. I used a WXDT ISA-PC type hard-disk card. This is how I wired the IBM card-edge connector to get the WDXT card to respond. Only connections needed are: A0, A1, /IORD, /IOWR and the 8 data lines, besides the +5v and the +12V (ignore the neg12V connection, WDXT cards don't need it). Signals /IOWR and /IORD need to be address decoded, A0, A1, (the address lines) GD0 to GD7 (the data lines) connect direct.
 
Here's the source code that I used until IDE came along:
 nam 'CCHDisk' 
 ttl OS9/NitrOS-9 Hard Disk Driver MFM
* Date: April 21, 1999
* for: 6809E CPU
*      WDXT-GEN2+
*      WDXT-GEN
*
NDrvs    equ 2      * change to 1 if only single drive wanted
*
Rev      equ 15
*
Card     equ $FF3C  * the base address of the WDXT card
RData    equ card+0 * from $FF3C to ...
WData    equ card+0
Status   equ card+1 * $FF3D
Reset    equ card+1
Config   equ card+2 * $FF3E
Select   equ card+2
IntReg   equ card+3 * $FF3F
*
Fodder   equ $FF
Blocks   equ $01
Interlv  equ $03
*
HdSize   equ 512
Os9Size  equ 256
Mask     equ $0F
AdvMask  equ $3F
Selected equ $0D
CmdByte  equ $0D
WrByte   equ $09
RdByte   equ $0B
CmpByte  equ $0F
ErrBit   equ %00000010
Drv1Bit  equ %00100000
NDrv1Bit equ %11011111
IntBit   equ %00000010
DoTk00   equ $06
SeekStil equ $08
*
* MFM commands:
*
TestCmd  equ $00
RecalCmd equ $01
ReqsCmd  equ $03
FmtCmd   equ $04
VfyCmd   equ $05
ReadCmd  equ $08
WritCmd  equ $0A
SeekCmd  equ $0B
InitCmd  equ $0C
ReadBuf  equ $0E
WritBuf  equ $0F
*
 ifp1
 use /DD/DEFS/DEFSFile
 endc
*
tylg set Drivr+Objct
atrv set ReEnt+Rev
*
 mod pgmend,modnam,tylg,atrv,start,size
*
 fcb %11111111 mode byte
*
 org DrvBeg
H0 rmb DrvMem
 ifeq NDrvs-2
H1 rmb DrvMem
 endc
*
* Init values for each Drive:
*
DiskVar0 rmb 8
 ifeq NDrvs-2
DiskVar1 rmb 8
 endc
*
* Command Block to Drive:
*
Class    rmb 1
Head     rmb 1
SecCyl   rmb 1
Cylindr  rmb 1
BlkCnt   rmb 1
StepSiz  rmb 1
*
* Linear Sector Number Storage:
*
Odd      rmb 1
HiByte   rmb 1
MidByte  rmb 1
LowByte  rmb 1
ZeroFlag rmb 1
*
* Various Buffers:
*
RetStat  rmb 1
ReqBufr  rmb 4
HdBuff   rmb HdSize
Stack    rmb 40
Size     equ .
*
Start
 lbra Init
 bra  ReadSec
 nop
 lbra WriteSec
 lbra Reads3   * GetSta
 lbra SetSta
 lbra Reads3   * Termin
*
ReadSec
 lbsr LSN
 lbsr ChkSeek
 bcs  RdXit
 bsr  Read
 bcc  Reads2
 lbsr Request
 lbcs Test
*
Reads2
 lbsr Blk2Os9
 lda  ZeroFlag,u
 bne  Reads3
 bsr  Lsn0
*
Reads3
 clrb
*
RdXit
 rts
*
Read
 lda  #ReadCmd
 lbsr SendCmd
 leax HdBuff,u
 ldd  #HdSize
*
* D=Count
*
BlkIn
 pshs y
 tfr  d,y
*
Read2
 lda  Status
 lsra
 bcc  Read2
*
 ldb  RData
 stb  ,x+
 leay -1,y
 bne  Read2
*
 puls y
 lbra Complete
*
Lsn0
 lbsr Getable * target
 ldb  #DD.SIZ * length
 pshs y
 ldy  PD.BUF,y * source
*
Read3
 lda  ,y+
 sta  ,x+
 decb
 bne  Read3
 puls y,pc
*
* patch in the appropriate
* OS9 256 byte block into
* the /H0 512 byte sector
*
WriteSec
 bsr  LSN
 lbsr ChkSeek
 bcs  WrErr
 bsr  Read
 bcc  Writes2
 lbsr Request
 bcs  WrErr
*
Writes2
 lbsr Os92Blk
 bsr  Write
 bcc  Writes3
 lbsr Request
 bcs  WrErr
*
Writes3
 tst  PD.VFY,y
 bne  RetNoErr
 bsr  Verify
 bcc  RetNoErr
 comb
 ldb  #E$Write
*
WrErr
 rts
*
RetNoErr
 clrb
 rts
*
Write
 lda #WritCmd
*
Write0
 lbsr SendCmd
 leax HdBuff,u
 ldd  #HdSize

* D=Count
*
BlkOut
 pshs y
 tfr  d,y
*
Data2
 lda  Status
 lsra
 bcc  Data2
*
 ldb  ,x+
 stb  WData
 leay -1,y
 bne  Data2
*
 puls y
 lbra Complete
*
Verify
 lda  #VfyCmd
 lbsr General
 ldb  RetStat,u
 beq  VfyXit
 coma
*
VfyXit
 rts
*
* LSN
* 0000000C:CCCCCCCC:CSSSSHHO
* for up to 20meg drives only.
* for 4 heads only !
* Cylinder-bits, Sector-bits, Head-bits, Odd-bit
* Odd-bit decides which half of the 512-byte sector
* gets read or (read, modify &) write.
*
LSN
 clr  Odd,u
 stb  HiByte,u
 stx  MidByte,u
 orb  MidByte,u
 orb  LowByte,u
 stb  ZeroFlag,u
*
 ldd  MidByte,u * move one cylinder bit
 lslb
 rola
 rol  HiByte,u
 sta  Cylindr,u
*
 lda  HiByte,u * get ls-bit of LSN
 lsra
 rorb
 lsra
 rorb
 rol  Odd,u * save that bit
*
 tfr  b,a
 andb #%11001111
 stb  SecCyl,u
 lsra
 lsra
 lsra
 lsra
 sta  Head,u
 rts
*
Os92Blk
 pshs y
 clrb         * Loop transfer counter
 ldx  PD.BUF,y
 leay HdBuff,u
 tst  Odd,u
 beq  LowHalf
 leay Os9Size,y
*
LowHalf
 lda  ,x+
 sta  ,y+
 decb
 bne  LowHalf
 puls y,pc
*
Blk2Os9
 pshs y
 clrb          * Loop Counter
 leax HdBuff,u * destination
 ldy  PD.BUF,y * source
 tst  Odd,u
 beq  LowHalf
 leax Os9Size,x
 bra  LowHalf
*
TestDrv
 lda  #TestCmd
 bsr  SendCmd
*
Test1
 lda  Status
 anda #Mask
 cmpa  #CmpByte
 bne  Test1
 ldb  WData     * get error bits
 andb #^Drv1Bit * without drive#
 beq  TestXit
 coma         * set error flag
*
TestXit
 rts
*
Sleep
 pshs x
 ldx  #1
 OS9  F$Sleep
 puls x,pc
*
Chk2
 bsr  Sleep
*
ChkSeek
 bsr  TestDrv
 bcc  Exit2
 cmpb #SeekStil
 beq  Chk2
 cmpb #DoTk00
 beq  Chk2
 bra  Request   * some other error
*
Exit2
 rts
*
 ifeq NDrvs-2
GetDrive
  lda  Head,u    * get drive/head variable
  tst  PD.DRV,y * if /H0
  beq  UseH0
  ora  #Drv1Bit * slave, /H1
  bra  Drive
*-
UseH0
  anda #^Drv1Bit * master, /H0
*-
Drive
  sta  Head,u    * update drive-bit
  rts
 endc
*
SendCmd
 sta  Select
 sta  Class,u
 bsr  GetDrive
*
NotRdy
 lda  Status
 anda #Mask
 cmpa #Selected
 bne  NotRdy
 leax Class,u
 ldb  #6

SendData
 lda  Status
 lsra
 bcc  SendData * 1=ready for data
 lda  ,x+
 sta  WData
 decb
 bne  SendData
 rts
*
General
 bsr  SendCmd
*
Complete
 lda  Status
 anda #Mask
 cmpa #CmpByte
 bne  Complete
 ldb  RData
 andb #ErrBit
 stb  RetStat,u
 beq  CompExit
 coma           * set carry bit
*
CompExit
 rts
*
Request
 lda  #ReqsCmd
 bsr  SendCmd
 leax ReqBufr,u
 ldd  #$04      * get request data string
 lbsr BlkIn
 ldb  ReqBufr,u * check the error byte
 andb #AdvMask  * eliminate the ADV-BIT
 bne  Test      * if not=0 then error
 clrb
 rts
*
Test
 cmpb #4
 bne  tst2
 comb
 ldb  #$FA
 rts
*
Tst2
 cmpb #3
 bne  tst3
 comb
 ldb  #$F5
 rts
*
Tst3
 cmpb #2
 bne  Tst4
 comb
 ldb  #$F0
 rts
*
Tst4
 cmpb #$15
 bne  Tst5
 comb
 ldb  #$F7
 rts
*
Tst5
 cmpb #$21
 bne  ErrSet
 comb
 ldb  #$F1
 rts
*
ErrSet
 comb
 ldb  #$CB
 rts
*-
GeTable
 ifeq NDrvs-2
  tst  PD.DRV,y
  bne  Slave
 endc
 leax H0,u
 rts
*-
 ifeq NDrvs-2
Slave
  leax H1,u
  rts
 endc
*
Init
 sta  Reset
 ldb  #NDrvs
 stb  V.NDRV,u
 lda  #$FF
 leax H0,u
*
InitLoop
 sta  DD.TOT+1,x
 sta  V.TRAK,x
 ifeq NDrvs-2
  leax DRVMEM,x
  decb
  bne  InitLoop
 endc
*
 lda  #IntBit
 sta  IntReg  * no interrupts
 sta  Reset   * reset the controller
 ldb  $14,y   * It.Stp dev desc
 orb  #$C0    * step rate bits
 stb  StepSiz,u
 clr  SecCyl,u
 clr  Cylindr,u
 clr  V.BUSY,u
 clr  V.WAKE,u
 lda  #Blocks * sector count
 sta  BlkCnt,u
 leax $20+1,y * IT.SAS+1
 pshs x,y     * Y is on bottom
 bsr  GetVar
 tfr  x,y
 puls x       * Y is still there
 ldb  #$08
*
MoveIt
 lda  ,x+
 sta  ,y+
 decb
 bne  MoveIt
*
 puls y
 lda  #InitCmd
 lbsr SendCmd
 bsr  GetVar * X=pointer
 ldd  #8     * table length
 lbsr BlkOut * send command
 bra  Home
*
GetVar
 leax DiskVar0,u
 ifeq NDrvs-2
  tst  PD.DRV,y
  beq  GetH0
  leax DiskVar1,u
*
GetH0
 endc
 rts
*
SetSta
 cmpb #SS.Reset
 bne  Set2
 bsr  Home
 rts
*
Set2
 cmpb #SS.Wtrk
 bne  SetErr
 bsr  FmtHd * low-level format
 rts
*
SetErr
 comb
 ldb  #E$UnkSvc
*
Exit
 rts
*
* Format a MFM Hard Drive:
*   first:  "dmode /h0 dns=0"
*   second: "format /h0"
*  This allows drive to be low-level formatted.
*  Software then sets dns=1 and quits.
*
FmtHd
 tst  PD.DNS,y
 beq  FmtCont * if =0 then FORMAT & set=1
*
Fmt2
 lda  #Blocks
 sta  PD.DNS,y * formatting is forced OFF
 sta  BlkCnt,u
 clrb
 rts
* First: fill the MDM drive's
*   internal buffer with sector data.
* Second: format the WHOLE drive with that data.
FmtCont
 bsr  Home
 bcs  Exit
 lda  #WritBuf * the fill-buffer command
 lbsr SendCmd
 lda  #Fodder  * the data to fill every sector with
 ldx  #HdSize
*
Loop
 ldb  Status   * send that buffer data
 andb #Mask
 cmpb #WrByte
 bne  Loop
*
 sta  WData
 leax -1,x
 bne  Loop
*
 lbsr Complete
 bcs  Exit
*
 lda  #Interlv * now format the while drive
 sta  BlkCnt,u
 lda  #FmtCmd  * with the MFM-FORMAT command
 lbsr General  * listen to it step ...
 bcs  Exit
 bsr  Fmt2     * same as: dmode /h0 dns=1
*
* and fall into...
*
Home
 lbsr GeTable   * move the drive heads to track=00
 clr  V.TRAK,x
 clr  Cylindr,u
 clr  SecCyl,u
 clr  Head,u
 ifeq NDrvs-2
  lbsr GetDrive  * update drive# bit
 endc
 lda  #RecalCmd * send heads to tk00
 lbsr General
 bcc  Exit
 lbra Request
*
modnam fcs /CCHDisk/
 fcb   Rev
*
 emod
pgmend equ *
 end
Hosted by www.Geocities.ws

1