Article View: net.micro.atari
Article #2408Re: Single to double density switching
From: langdon
Date: Fri, 07 Feb 1986 17:10
Date: Fri, 07 Feb 1986 17:10
268 lines
8163 bytes
8163 bytes
In article <328@sask.UUCP>, long@sask.UUCP (Warren Long) writes:
>
> I have been trying (unsuccessfully) to switch my disk drives
> to and fro from double density. It is easy to do from a
> DOS that does it. (eg. TOP DOS or MYDOS).
> What I want to do is to be able to do it from my program.
> I write everything in ACTION so assembly or machine code is
> quite acceptable.
Try this. It is supposed to become a directory fixer for DD diskettes;
that is only part started, but density detection and switching are in there
and they worked.
----------------------------------------------------------------------
Bruce Langdon L-472 langdon%lll-lcc@lll-crg.ARPA
Physics Department "langdon#bruce%d"@lll-mfe.ARPA
Lawrence Livermore National Laboratory
Livermore, CA 94550 (415) 422-5444
UUCP: ..{gymble,ihnp4,seismo}!lll-crg!lll-lcc!langdon
---------------------------------------------------------------------------
; DISKFIX.AC1 12/23/85 A. B. Langdon
DEFINE SIOUT="$80", SIOIN="$40"
BYTE Dtimeout=[15]
; Device Control Block for SIO:
BYTE DDEVIC=$0300, DUNIT=$0301,
DCOMND=$0302, DSTATS=$0303, DTIMLO=$0306
CARD DBUF=$0304, DBYTE=$0308, DAUX12=$030A
PROC SIOV=$E459() ;define location of serial bus handler
BYTE FUNC DSio()
; finish set up of Device Control Block
; and call the serial I/O routine.
DDEVIC = '1
DTIMLO = Dtimeout
SIOV()
RETURN (DSTATS)
MODULE; SECTIO ----------------------
; Adapted from OSS bbs.
; Sectors are numbered 1-720.
BYTE FUNC SectIO(BYTE drive, CARD sector, buffer, BYTE density)
DUNIT = drive
DBUF = buffer
; Set byte count for this density
IF (sector<=3) OR (density<3) THEN
DBYTE = 128
ELSE
DBYTE = 256
FI
DAUX12 = sector
RETURN (DSio())
BYTE FUNC ReadSector(BYTE drive, CARD sector, buffer, BYTE density)
DCOMND = 'R
DSTATS = SIOIN
SectIO(drive, sector, buffer, density)
[$60]; RETURN (SIO error code)
BYTE FUNC WriteSector(BYTE drive, CARD sector, buffer, BYTE density)
DCOMND = 'W
DSTATS = SIOUT
SectIO(drive, sector, buffer, density)
[$60]; RETURN (SIO error code)
MODULE; DENSITY ---------------------
; From Mark Reed, on ACS bulletin board. Mods by B. Langdon
;This program changes the density of a PERCOM-compatible drive from
;single to double density and vice versa. It also displays the values
;in the drive option table before and after the change.
;Note that by changing the Set_DENSITY() procedure you could configure
;the disk controller to handle a double sided or 96TPI (quad density)
;drive, assuming your controller can handle these drive types.
;(The PERCOM RFD-1 and ATR8000 can, the TRAK, INDUS, etc. can't)
DEFINE RdOCmd="'N", WrOCmd="'O"
BYTE ARRAY OptTable(12)
BYTE Ntracks=OptTable, StepRate=OptTable+1, Nsides=OptTable+4,
density=OptTable+5, present=OptTable+8
CARD Nsectors=OptTable+2, Nbytes=OptTable+6
PROC OPTION_TABLE_ERROR()
PrintF("ERROR %D%E",DSTATS)
RETURN
PROC OPTION_TABLE(BYTE drive, CMND)
DUNIT = drive
DCOMND = CMND
IF CMND=RdOCmd THEN ;read option table
DSTATS = SIOIN ;set for data in
ELSEIF CMND=WrOCmd THEN ;write option table
DSTATS = SIOUT ;set for data out
ELSE
OPTION_TABLE_ERROR()
RETURN
FI
DBYTE = 12
DBUF = OptTable
DSio()
IF DSTATS<>1 THEN
OPTION_TABLE_ERROR()
FI
RETURN
CARD FUNC SwapHiLo=*(CARD in)
; For Percom's 6809, must use Hi,Lo order.
[$86 $A0] ; STX value low
[$85 $A1] ; STA value high
[$60] ; RETURN
PROC TEST_OPTION_TABLE(BYTE drive)
; read the option table and displays the values
BYTE ARRAY SR=[6 12 20 30] ; step rates
CARD Ctemp
OPTION_TABLE(drive, RdOCmd)
IF DSTATS<>1 THEN RETURN FI
Ctemp=SwapHiLo(Nsectors)
PrintF("%D tracks of %D sectors, %D sides%E",Ntracks,Ctemp,Nsides+1)
PrintF("step rate %D ms. 'present'=%D%E",SR(StepRate),present)
Ctemp=SwapHiLo(Nbytes)
PrintF("%D bytes/sector; 'density'=%D%E",Ctemp,density)
RETURN
PROC Set_DENSITY(BYTE drive, NEW_DENSITY)
OPTION_TABLE(drive, RdOCmd) ;read option table
IF NEW_DENSITY=1 THEN ;sets single density
density=0 ;single/double flag
Nbytes=SwapHiLo(128)
OPTION_TABLE(drive, WrOCmd) ;write new info
ELSEIF NEW_DENSITY=2 THEN ;sets double density
density=4 ;density flag
Nbytes=SwapHiLo(256)
OPTION_TABLE(drive, WrOCmd)
FI
RETURN
MODULE; -----------------------------
BYTE drive, j
BYTE ARRAY buf(256), directory(1028)
BYTE ARRAY VTOC(256), SMap(90)=VTOC+10
CARD TotSect=VTOC+1, NSUnused=VTOC+3
CARD sector, i
CARD ARRAY SLinks(720)
CARD POINTER link
BYTE POINTER nfile
; Sectors are numbered 1-720 by drive.
; TotSec may always be 707.
TYPE DirEntry=[BYTE flag CARD count, sect]
; flag:
; =$00 entry never used
; 01 now writing file
; 02 a version 2 file
; 20 entry protected
; 40 entry in use
; 80 entry was deleted
; count=number of sectors,
; start=number of 1st sector.
DirEntry POINTER filedat
BYTE FUNC TestVTOC(CARD sector, BYTE ARRAY map)
; FMS bug: there is no sector for bit 0,
; no bit for sector 720.
BYTE index, mask
mask = $80 RSH (sector&7)
index = sector RSH 3
RETURN( map(index)&mask )
PROC SetVTOC(CARD sector, BYTE ARRAY map)
BYTE index, mask
mask = $80 RSH (sector&7)
index = sector RSH 3
map(index) ==% mask
; also dec sectors avail***
RETURN
CARD FUNC NextSect()
BYTE FUNC TraceFile(BYTE filen, CARD sector, BYTE ARRAY map)
; follow file 'filen' starting at 'sector'
; setting VTOC as we go.
CARD ns
link = buf+Nbytes-3
nfile = link
DO
ReadSector(drive,sector,buf,density)
SetVTOC(sector,map)
nfile^ = ($FC&nfile^) RSH 2
PrintF("sec %U file %U%E",sector,nfile^)
IF nfile^<>filen THEN RETURN(1) FI
ns = SwapHiLo(link^) & $3FF
SLinks(sector) = ns
sector = ns
UNTIL sector=0 OD
RETURN(0)
PROC TraceDisk()
link = buf+Nbytes-3
nfile = link
FOR sector=4 TO 719 DO
ReadSector(drive,sector,buf,density)
SLinks(sector) = SwapHiLo(link^) & $3FF
PrintF("sec %U file %U%E",link^,nfile^)
OD
RETURN
PROC GetDir() ; assemble all directory sectors
Zero(directory, 1028)
i = directory
FOR sector=361 TO 368 DO
ReadSector(drive, sector, buf, density)
IF buf(0)=0 THEN EXIT FI ;no more after this
MoveBlock(i, buf, 128) ;128 bytes used even in DD
i ==+ 128
OD
RETURN
PROC PrintFN(BYTE POINTER name)
BYTE DSPFLG=$2FE, i
DSPFLG = 1
name ==+ 5
FOR i=1 TO 11 DO
Put(name^)
name ==+ 1
OD
DSPFLG = 0
RETURN
PROC ShowDir()
BYTE nf
CARD Nfree
Nfree = 707 ;=720 -1 unused -3 boot -1 VTOC -8 directory
i = 0
FOR nf=0 to 63 DO
filedat = i+directory
IF filedat.flag=0 THEN EXIT FI ;no more after this
PrintFN(filedat)
PrintF(" %U %H %U %U%E",nf,filedat.flag,filedat.count,filedat.sect)
IF filedat.flag<$80 THEN
Nfree ==- filedat.count
FI
i ==+ 16
OD
PrintF("%U FREE SECTORS%E",Nfree)
PrintF("VTOC: %U %U%E",TotSect,NSUnused)
RETURN
PROC MAIN()
Print("ENTER THE DRIVE NUMBER: ")
drive=InputB()
TEST_OPTION_TABLE(drive)
IF DSTATS<> 1 THEN RETURN FI
NBytes = SwapHiLo(NBytes)
ReadSector(drive,360,VTOC,density)
Tracefile(0,4,SMap)
RETURN
GetDir()
ShowDir()
RETURN
Technical Details
Message-ID:
<140@lll-lcc.UUcp>Path:
arc1-ca.pugleaf.net!utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxn!ihnp4!houxm!whuxl!whuxlm!akgua!gatech!ut-sally!topaz!lll-crg!lll-lcc!langdonReferences:
<328@sask.UUCP>Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxn!ihnp4!houxm!whuxl!whuxlm!akgua!gatech!ut-sally!topaz!lll-crg!lll-lcc!langdon From: langdon@lll-lcc.UUCP Newsgroups: net.micro.atari Subject: Re: Single to double density switching Message-ID: <140@lll-lcc.UUcp> Date: Fri, 7-Feb-86 12:10:23 EST Article-I.D.: lll-lcc.140 Posted: Fri Feb 7 12:10:23 1986 Date-Received: Sun, 9-Feb-86 08:23:40 EST References: <328@sask.UUCP> Distribution: net Organization: Lawrence Livermore Labs, LCC, Livermore Ca Lines: 268 Summary: Action program to switch disk drive density and etc.