þþð'd6X* ATARI 1050 DISK DRIVE OPERATING SYSTEM -- part 2nX*xX* command from CPU‚X*Œ…TKOM1 …RDKOM;read command–*…ERROR;command ok? K„NEXT;no, checksum errorª ‡PROCESS;execute´*…ERROR;everything fine?¾G„NEXT;other drive?È JƒKOK;okÒ, ‡SENDNAK;send NAK, can't execute commandÜ Q†STATUSæL>;set to o.k.ð P†STATUSúH„NEXT;alwaysX*ƒKOK …SENDA;send 'A' Q…ERROR"M>;read sector?,F…DOKOM;no, execute command6% …SLOAD;read sector from interface@*…ERROR;read error?JJ„KOK1;br if okT ‡SENDNAK;yes, send NAK^Q†STATUS;and indicate errorhL>r P†STATUS| H„NEXT†X*„KOK1 …SENDA;send 'A'š"…DOKOM ‡EXECUTE;execute command¤#Q†STATUS;read sector status bits®M>ü;reset i/o error¸ P†STATUSÂ)„NEXT$>;clear buffer for new commandÌQ>Ö„EBCLP†RDRIVE9à0ê I„EBCLô:þX*X* look at commandX*‡PROCESSQƒDRA&M>;drive number0 >;to X reg:Q…DRVNR9;drive number sameDR†RDRIVE;as in command frameNH…ERR80;no, errorX$>;commands 0 - 7 are o.k.bQ†RKOMND;seek in tablel‡KOMSUCHR‡READSEK9vF†KOMFND;br if found€0;otherwise, continueŠI‡KOMSUCH;until end of table”G…ERR40;unknown commandž%†KOMFND&…KOMND;save command number¨#(>;command with sector number?² E…NOSEK;no¼Q…RSEKL;otherwise, testÆ,;sector number in bufferÐL…RSEKH;can't be 0Ú F…ERR40äQƒDRA;in single densityîM> ø F…ZF33D$>Ð;max $2D0 sectors %> H…TSANZ .…ZF33D$>;in enhanced density $410 sectors*%>4 …TSANZ;>AH S…RSEKLRC\ S…RSEKHfD…ERR40;wrong sectorpX*z…NOSEKQ†RKOMND;get command„R‡WRITSEK;write sector?Ž&F…LSSET;if so, set load sector flag˜R‡WRVESEK;write with verify?¢F…LSSET;load sector, again¬R‡SPEZIAL;special command¶F…LSSET;load sector, againÀQ>;all other commandsÊF„NOLS;don't load sectorÔX*ÞX* set load sector flagèX*ò …LSSETQ>üX*X* reset load sector flagX*„NOLSP…ERROR$:.X*8X* indicate errorBX*L …ERR80Q>€V P…ERROR`:j …ERR40Q>@t P…ERROR~:ˆX*’X* send 'A' to CPUœX*¦ …SENDA%> A;ascii code for 'A'° …SBYTE;send byteº:ÄX*ÎX* send 'NAK' to CPUØX*â"‡SENDNAK%> N;ascii code for 'N'ì …SBYTE;sendö:X* X* send 'C' to CPUX* …SCONT%> C;ascii code for 'C'( …SBYTE;send2:<X*FX* send 'E' to CPU for errorPX*Z!†SERROR%> E;ascii code for 'E'd …SBYTE;sendn:xX*‚X* read a serial byteŒX*–†RDBYTE&„SBUF;save X reg ƒWSB*ƒDRA;wait for start bitª%J„ERR1;data interrupt from floppy?´#*ƒDRB;or DATA IN at PORT 6 high?¾ JƒWSB;noÈ;;otherwiseÒQ>€;bit 7 mark for endÜ$>;wait 0.5 bit timeæƒWHB0ðHƒWHBú„W32B$>;wait 2/3 bit time)…W32B10;to get first bit in the middle H…W32B14"4,46*ƒDRB;bit 1 or 0?@ J„BIT1J,;got a zeroT D†NXTBIT^„BIT1;;got a oneh4;keep in same tempo as BCCr†NXTBITW?;roll bit in result|D„W32B;already 8 bits?†?;yes, result in Y reg$„SBUF;restore X regš:¤„ERR17;balance stack®7¸!‡ERRSTAT;indicate errorÂX*Ì/X* read a command (4 chars) from serial portÖX*à…RDKOMQ>;number of charsê P…COUNTô$$>†RDRIVE;buffer is from addr $80þ$ „RDTO;read 4 bytes with TIME OUT*†NOTKOM*ƒDRB;wait until command on zero G†NOTKOM :;done&X*0X* read a sector:X*D…SLOADQ>€;sector lengthN P…COUNTX$>†SEKBUF;read to addr 0b „RDTO;from serial portl$> ;short delayv †DELAY1€:ŠX*”!X* read bytes from serial portž2X* number of bytes in COUNT/buffer address in X¨X*² „RDTOQ>ÿ¼ ‡TIMEOUT;set TIMEOUTÆQ>;reset checksumÐ P„SBUFÚ…RNXTB †RDBYTE;read byteä'†SEKBUF9;and store itî,;add to checksumø Q„SBUF O†SEKBUF9 O> P„SBUF 2;buffer pointer + 1*"…COUNT;job done?4H…RNXTB;no, continue> †RDBYTE;yes, read checksumH'†SEKBUF9;storeR,Q„SBUF;and compare with accumulated value\ N†SEKBUF9fF†NORERR;br if okpX*zX* indicate error / no error„X*Ž‡ERRSTATQ>@˜†NORERRP…ERROR¢ Q…TIM64;reset TIMEOUT counter¬:¶X*ÀX* send bytes from address XÊX* number of bytes in COUNTÔX*Þ„SENDQ>;checksumè …SEND1,ò%†SEKBUF9;add to checksumü O†SEKBUF9 O>  …SBYTE;send byte 2;buffer address + 1$ "…COUNT;job done?. H…SEND1;no, continue8 ?;send checksumB …SBYTEL :V X*` X* send sectorj X*t †SNDSEKQ>€;bytes/sector~ P…COUNTˆ $$>†SEKBUF;send from sector buffer’ !„SENDœ X*¦ X* send a byte to serial port° X*º …SBYTE'„SBUF;save charÄ P„SBUF;save checksumÎ &„SBUF;save XØ %>;send 8 bitsâ Q>þ;set start bitì MƒDRB;...and sendö PƒDRB #„SBUF;delay †SBYTE1W„SBUF;next data bit D…SBIT0;send '0' bit !Q>;send '1' bit if carry set( LƒDRB2 H„SBIT;send bit< …SBIT0Q>þ;send '0' bitF MƒDRBP 4;keep synchronousZ „SBIT$>;send bitd …SBIT20;delayn H…SBIT2x PƒDRB;to port‚ 1;done?Œ H†SBYTE1– $>;delay for last bit  …SBIT30ª H…SBIT3´ 4¾ "„SBUF;delayÈ Q>;send stop bitÒ LƒDRBÜ PƒDRBæ $>;delay for stop bitð …SBIT40ú H…SBIT4 $„SBUF;restore X %„SBUF;and Y Q„SBUF;and A" :;done, X*6 &X* execute command 0 - 7 from KOMND@ X*J %‡EXECUTE$…KOMND;get command numberT Q†JMPTBL9;get low byte^ "P…JUMPL;of command routine addrh Q†JMPTBH9;and high byter P…JUMPH| !@…JUMPL:;jump to routine† X* 9X* calculate track & sector from logical sector numberš X*¤ .…COMTS%…RSEKL;logical sector number to SBUF® '„SBUF¸ %…RSEKH '„SBUFÌ %>;reset track & sectorÖ '…TRACKà '†SEKTORê $3;transfer logical sector 1 ... nô  „SUBY;to 0 ... n-1þ Q> ;single or enhanced? MƒDRA H†SINGLE %%>;number of sectors/track in MD& H†COMTS10 #†SINGLE%>;sectors/tracks in SD: (†COMTS1 „SUBY;subtrackt as many timesD D†TOMUCH;as possibleN #…TRACK;count every timeX E†COMTS1;continueb %†TOMUCH#†SEKTOR;first sector is #1l :v X*€ X* B1,B2 - YŠ X*” „SUBY'„HZ95ž ;¨ &Q„SBUF;save remaining sector number² P†SEKTOR¼ !S„HZ95;subtrackt sectors/trackÆ P„SBUF;and store resultÐ Q„SBUF;hi byte alsoÚ S>ä P„SBUFî :ø X* X* read sector, command 'R' X* „READ …SREAD;read one sector  …QUITT;return 'C' or 'E'* !†SNDSEK;send sector4 +…SREAD …SETUP;set number of retries etc.> *†FCNTRL;drive ready?H I…READ1;br if okR :;otherwise error\ …READ1 „SEEK;on right track?f F…READ2;ok?p :;SEEK ERRORz /…READ2Q†SEKTOR;put sector number in register„ P†SEKREGŽ  ˆRDSEKTOR;read sector˜ H…READ3;error?¢ Q>;no, indicate 'no error'¬ P…ERROR¶ :;doneÀ …READ3"…COUNT;another retry?Ê F…READ4;br if no moreÔ #Q†FCNTRL;record not found error?Þ M>è &F…READ5;if so, try again, incl SEEKò ‡RESTOREü !…READ1…READ5Q>;last try? R…COUNTH…READ1;no, do it again$Q>;last try.P‡STEPCNT;another half step8Q>ÿ;backwardB P…STEPSLPƒDIRV …HSTEP;make half a step`Q>;and forward againjPƒDIRt …HSTEP;make half a step~ $>È;delayˆ †DELAY1’!…READ1;read another timeœ…READ4:;done or break¦X*°%X* set retry number, motor on etc.ºX*Ä…SETUPQ>€;assume errorÎ P…ERRORØQ>;retriesâ P…COUNTì# …COMTS;calculate track & sectorö*†FCNTRL;drive ready?G†SETUP1;no, exit  †TMOTON;otherwise, motor on †SETUP1:X*(X* quit off, send 'C' or 'E'2X*<…QUITT$>;delayF †DELAY1P Q†FCNTRLZP…CSTAT;return floppy statusd*…ERROR;error?nG†QUITTE;br if sox Q†STATUS‚!M>›;reset error bit in STATUSŒ P†STATUS– …SCONT;send 'C' :ª †QUITTEQ†STATUS;set error bit´L>¾ P†STATUSÈ †SERROR;send 'E'Ò:ÜX*æ0X* read a sector, head already on right trackðX*úˆRDSEKTOR$>;set timeoutQ>æ ‡TIMEOUT*Q>‚;read sector command for controller" P†FCNTRL, ‡READSE1*ƒDRA;IRQ controller?6 J‡READSE2@I‡READSE1;DRQ controller?JQ†DATREG;yes, read data byteTN>ÿ;invert^%P†SEKBUF9;and put in sector bufferhQ…TIM64;reset timerr2;sector buffer pointer + 1|*I‡READSE1;continue until 128 bytes read†Q>/‡READSE3*†FCNTRL;wait until controller readyš H‡READSE3¤,Q†FCNTRL;mask status bits for READ SECTOR®M>,¸ :;done‡READSE2Q†FCNTRLÌM>;controller still busy?ÖF‡READSE4;br if notà"Q>æ;otherwise, set timer againê ‡TIMEOUTôH‡READSE1;and read againþ‡READSE4Q…TIM64;reset timerQ†FCNTRL;lost data?M>HˆRDSEKTOR;yes, read again&Q>;otherwise error0 :;and exit:X*D$X* execute 'read address' commandNX*X%…RDADR$>z;buffer for address infobQ>€;set timeoutl ‡TIMEOUTv,Q>À;'read address' command to controller€ P†FCNTRLŠ†RDADR1*ƒDRA;wait for IRQ” J†RDADR3ž"I†RDADR1;or DRQ from controller¨$Q†DATREG;read / store data at DRQ² P†SEKBUF9¼Q…TIM64;reset timerÆ2ÐI†RDADR1;until doneÚQ>;and waitä'†RDADR2*†FCNTRL;for controller readyî H†RDADR2øQ†FCNTRL;read statusM> ;mask relevant bits  :;done"†RDADR3 †DFORCE;force interrupt Q>;return error*:4X*>X* set timeout, value in AHX*R$‡TIMEOUTP…TIM64;set timeout value\ P†T1024If:pX*z0X* write sector without verify -- command 'P'„X*Ž…WRITE †WRITE1;write sector˜ …QUITT;return result¢:¬X*¶"†WRITE1 …SETUP;set retries etc.À*†FCNTRL;drive ready?ÊI†WRITE2;br if soÔ:Þ†WRITE2 „SEEK;goto trackèF†WRITE3;ok?ò:;no, errorü†WRITE3Q†SEKTOR;set sector P†SEKREG ˆWRSEKTOR;write sectorH†WRITE4;br if error$Q>;indicate no error. P…ERROR8 :;doneB †WRITE4"…COUNT;another retry?LF†WRITE5;no, errorV& ‡RESTORE;otherwise, do it all over` !†WRITE2j†WRITE5:;done or breaktX*~)X* write sector, head already on trackˆX*’ˆWRSEKTOR$>œQ>æ;set timeout¦ ‡TIMEOUT°-Q>¢;'write sector' command for controllerº P†FCNTRLÄ/‡WRITSE1Q†SEKBUF9;read data byte from bufferÎN>ÿ;invertØ%‡WRITSE2*ƒDRA;IRQ from controller?âJ‡WRITSE3;yes, errorì!I‡WRITSE2;DRQ from controller?öP†DATREG;yes, put byteQ…TIM64;reset timer 2;next byteI‡WRITSE1;if anyQ>;otherwise,(-‡WRITSE4*†FCNTRL;wait for controller ready2 H‡WRITSE4<Q†FCNTRL;read statusFM> ;mask relevant bitsP :;doneZ‡WRITSE3Q†FCNTRL;errord!M>;wait for controller readyn F‡WRITSE5xQ>æ;set timeout‚ ‡TIMEOUTŒH‡WRITSE1;continue–‡WRITSE5Q…TIM64;reset timer  Q†FCNTRLªM>;lost data?´HˆWRSEKTOR;do it again¾#Q†FCNTRL;otherwise, return errorÈ:ÒX*Ü-X* write sector with verify -- command 'W'æX*ð,†VWRITE †WRITE1;write sector, same as 'P'ú*…ERROR;test for error G‡VWRITE1Q>;set retry to 2 P…COUNT" †VERIFY;check sector, ‡VWRITE1 …QUITT;return result6: