Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: 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. 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